bt2: field.py: raise ValueError when setting out of range value to Integer
[babeltrace.git] / src / bindings / python / bt2 / bt2 / field.py
CommitLineData
81447b5b
PP
1# The MIT License (MIT)
2#
811644b8 3# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
81447b5b
PP
4#
5# Permission is hereby granted, free of charge, to any person obtaining a copy
6# of this software and associated documentation files (the "Software"), to deal
7# in the Software without restriction, including without limitation the rights
8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9# copies of the Software, and to permit persons to whom the Software is
10# furnished to do so, subject to the following conditions:
11#
12# The above copyright notice and this permission notice shall be included in
13# all copies or substantial portions of the Software.
14#
15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21# THE SOFTWARE.
22
23from bt2 import native_bt, object, utils
3fb99a22 24from bt2 import field_class as bt2_field_class
81447b5b
PP
25import collections.abc
26import functools
27import numbers
28import math
81447b5b
PP
29
30
f0a42b33
FD
31def _create_field_from_ptr_template(
32 object_map, ptr, owner_ptr, owner_get_ref, owner_put_ref
33):
34
2ae9f48c 35 field_class_ptr = native_bt.field_borrow_class_const(ptr)
2ae9f48c 36 typeid = native_bt.field_class_get_type(field_class_ptr)
f0a42b33 37 field = object_map[typeid]._create_from_ptr_and_get_ref(
cfbd7cf3
FD
38 ptr, owner_ptr, owner_get_ref, owner_put_ref
39 )
81447b5b
PP
40 return field
41
42
f0a42b33
FD
43def _create_field_from_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
44 return _create_field_from_ptr_template(
45 _TYPE_ID_TO_OBJ, ptr, owner_ptr, owner_get_ref, owner_put_ref
46 )
47
48
49def _create_field_from_const_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
50 return _create_field_from_ptr_template(
51 _TYPE_ID_TO_CONST_OBJ, ptr, owner_ptr, owner_get_ref, owner_put_ref
52 )
53
54
cec0261d
PP
55# Get the "effective" field of `field`. If `field` is a variant, return
56# the currently selected field. If `field` is an option, return the
57# content field. If `field` is of any other type, return `field`
1eccc498 58# directly.
81447b5b 59
cfbd7cf3 60
1eccc498 61def _get_leaf_field(field):
f0a42b33 62 if isinstance(field, _VariantFieldConst):
cec0261d 63 return _get_leaf_field(field.selected_option)
1eccc498 64
f0a42b33 65 if isinstance(field, _OptionFieldConst):
cec0261d
PP
66 return _get_leaf_field(field.field)
67
68 return field
81447b5b 69
e1c6bebd 70
f0a42b33
FD
71class _FieldConst(object._UniqueObject):
72 _create_field_from_ptr = staticmethod(_create_field_from_const_ptr)
73 _create_field_class_from_ptr_and_get_ref = staticmethod(
74 bt2_field_class._create_field_class_from_const_ptr_and_get_ref
75 )
76 _borrow_class_ptr = staticmethod(native_bt.field_borrow_class_const)
77
1eccc498 78 def __eq__(self, other):
e1c6bebd
JG
79 other = _get_leaf_field(other)
80 return self._spec_eq(other)
81
81447b5b 82 @property
d8e2073c 83 def cls(self):
f0a42b33 84 field_class_ptr = self._borrow_class_ptr(self._ptr)
838a5a52 85 assert field_class_ptr is not None
f0a42b33 86 return self._create_field_class_from_ptr_and_get_ref(field_class_ptr)
81447b5b 87
12bf0d88
JG
88 def _repr(self):
89 raise NotImplementedError
90
91 def __repr__(self):
1eccc498 92 return self._repr()
12bf0d88 93
81447b5b 94
f0a42b33
FD
95class _Field(_FieldConst):
96 _create_field_from_ptr = staticmethod(_create_field_from_ptr)
97 _create_field_class_from_ptr_and_get_ref = staticmethod(
98 bt2_field_class._create_field_class_from_ptr_and_get_ref
99 )
100 _borrow_class_ptr = staticmethod(native_bt.field_borrow_class)
101
102
103class _BitArrayFieldConst(_FieldConst):
104 _NAME = 'Const bit array'
ead8c3d4
PP
105
106 @property
107 def value_as_integer(self):
108 return native_bt.field_bit_array_get_value_as_integer(self._ptr)
109
ead8c3d4
PP
110 def _spec_eq(self, other):
111 if type(other) is not type(self):
112 return False
113
114 return self.value_as_integer == other.value_as_integer
115
116 def _repr(self):
117 return repr(self.value_as_integer)
118
119 def __str__(self):
120 return str(self.value_as_integer)
121
122 def __len__(self):
d8e2073c 123 return self.cls.length
ead8c3d4
PP
124
125
f0a42b33
FD
126class _BitArrayField(_BitArrayFieldConst, _Field):
127 _NAME = 'Bit array'
128
129 def _value_as_integer(self, value):
130 utils._check_uint64(value)
131 native_bt.field_bit_array_set_value_as_integer(self._ptr, value)
132
133 value_as_integer = property(
134 fget=_BitArrayFieldConst.value_as_integer.fget, fset=_value_as_integer
135 )
136
137
81447b5b 138@functools.total_ordering
f0a42b33 139class _NumericFieldConst(_FieldConst):
81447b5b
PP
140 @staticmethod
141 def _extract_value(other):
f0a42b33 142 if isinstance(other, _BoolFieldConst) or isinstance(other, bool):
aae30e61 143 return bool(other)
81447b5b
PP
144
145 if isinstance(other, numbers.Integral):
146 return int(other)
147
148 if isinstance(other, numbers.Real):
149 return float(other)
150
151 if isinstance(other, numbers.Complex):
152 return complex(other)
153
cfbd7cf3
FD
154 raise TypeError(
155 "'{}' object is not a number object".format(other.__class__.__name__)
156 )
81447b5b
PP
157
158 def __int__(self):
e1c6bebd 159 return int(self._value)
81447b5b
PP
160
161 def __float__(self):
e1c6bebd 162 return float(self._value)
81447b5b 163
12bf0d88 164 def _repr(self):
5abb9e33 165 return repr(self._value)
81447b5b
PP
166
167 def __lt__(self, other):
168 if not isinstance(other, numbers.Number):
cfbd7cf3
FD
169 raise TypeError(
170 'unorderable types: {}() < {}()'.format(
171 self.__class__.__name__, other.__class__.__name__
172 )
173 )
81447b5b 174
09a926c1 175 return self._value < self._extract_value(other)
81447b5b 176
e1c6bebd 177 def _spec_eq(self, other):
f11ed062
PP
178 try:
179 return self._value == self._extract_value(other)
4c4935bf 180 except Exception:
f11ed062 181 return False
81447b5b 182
dda659b3
FD
183 def __hash__(self):
184 return hash(self._value)
185
81447b5b 186 def __rmod__(self, other):
e1c6bebd 187 return self._extract_value(other) % self._value
81447b5b
PP
188
189 def __mod__(self, other):
e1c6bebd 190 return self._value % self._extract_value(other)
81447b5b
PP
191
192 def __rfloordiv__(self, other):
e1c6bebd 193 return self._extract_value(other) // self._value
81447b5b
PP
194
195 def __floordiv__(self, other):
e1c6bebd 196 return self._value // self._extract_value(other)
81447b5b
PP
197
198 def __round__(self, ndigits=None):
199 if ndigits is None:
e1c6bebd 200 return round(self._value)
81447b5b 201 else:
e1c6bebd 202 return round(self._value, ndigits)
81447b5b
PP
203
204 def __ceil__(self):
e1c6bebd 205 return math.ceil(self._value)
81447b5b
PP
206
207 def __floor__(self):
e1c6bebd 208 return math.floor(self._value)
81447b5b
PP
209
210 def __trunc__(self):
e1c6bebd 211 return int(self._value)
81447b5b
PP
212
213 def __abs__(self):
e1c6bebd 214 return abs(self._value)
81447b5b
PP
215
216 def __add__(self, other):
e1c6bebd 217 return self._value + self._extract_value(other)
81447b5b
PP
218
219 def __radd__(self, other):
220 return self.__add__(other)
221
222 def __neg__(self):
e1c6bebd 223 return -self._value
81447b5b
PP
224
225 def __pos__(self):
e1c6bebd 226 return +self._value
81447b5b
PP
227
228 def __mul__(self, other):
e1c6bebd 229 return self._value * self._extract_value(other)
81447b5b
PP
230
231 def __rmul__(self, other):
232 return self.__mul__(other)
233
234 def __truediv__(self, other):
e1c6bebd 235 return self._value / self._extract_value(other)
81447b5b
PP
236
237 def __rtruediv__(self, other):
e1c6bebd 238 return self._extract_value(other) / self._value
81447b5b
PP
239
240 def __pow__(self, exponent):
e1c6bebd 241 return self._value ** self._extract_value(exponent)
81447b5b
PP
242
243 def __rpow__(self, base):
e1c6bebd 244 return self._extract_value(base) ** self._value
81447b5b 245
81447b5b 246
f0a42b33 247class _NumericField(_NumericFieldConst, _Field):
dda659b3
FD
248 def __hash__(self):
249 # Non const field are not hashable as their value may be modified
250 # without changing the underlying Python object.
251 raise TypeError('unhashable type: \'{}\''.format(self._NAME))
f0a42b33
FD
252
253
254class _IntegralFieldConst(_NumericFieldConst, numbers.Integral):
81447b5b 255 def __lshift__(self, other):
e1c6bebd 256 return self._value << self._extract_value(other)
81447b5b
PP
257
258 def __rlshift__(self, other):
e1c6bebd 259 return self._extract_value(other) << self._value
81447b5b
PP
260
261 def __rshift__(self, other):
e1c6bebd 262 return self._value >> self._extract_value(other)
81447b5b
PP
263
264 def __rrshift__(self, other):
e1c6bebd 265 return self._extract_value(other) >> self._value
81447b5b
PP
266
267 def __and__(self, other):
e1c6bebd 268 return self._value & self._extract_value(other)
81447b5b
PP
269
270 def __rand__(self, other):
e1c6bebd 271 return self._extract_value(other) & self._value
81447b5b
PP
272
273 def __xor__(self, other):
e1c6bebd 274 return self._value ^ self._extract_value(other)
81447b5b
PP
275
276 def __rxor__(self, other):
e1c6bebd 277 return self._extract_value(other) ^ self._value
81447b5b
PP
278
279 def __or__(self, other):
e1c6bebd 280 return self._value | self._extract_value(other)
81447b5b
PP
281
282 def __ror__(self, other):
e1c6bebd 283 return self._extract_value(other) | self._value
81447b5b
PP
284
285 def __invert__(self):
e1c6bebd 286 return ~self._value
81447b5b 287
81447b5b 288
f0a42b33
FD
289class _IntegralField(_IntegralFieldConst, _NumericField):
290 pass
291
292
293class _BoolFieldConst(_IntegralFieldConst, _FieldConst):
294 _NAME = 'Const boolean'
aae30e61
PP
295
296 def __bool__(self):
297 return self._value
298
f0a42b33
FD
299 @classmethod
300 def _value_to_bool(cls, value):
301 if isinstance(value, _BoolFieldConst):
aae30e61
PP
302 value = value._value
303
304 if not isinstance(value, bool):
305 raise TypeError(
f0a42b33 306 "'{}' object is not a 'bool', '_BoolFieldConst', or '_BoolField' object".format(
aae30e61
PP
307 value.__class__
308 )
309 )
310
311 return value
312
313 @property
314 def _value(self):
315 return bool(native_bt.field_bool_get_value(self._ptr))
316
f0a42b33
FD
317
318class _BoolField(_BoolFieldConst, _IntegralField, _Field):
319 _NAME = 'Boolean'
320
aae30e61
PP
321 def _set_value(self, value):
322 value = self._value_to_bool(value)
323 native_bt.field_bool_set_value(self._ptr, value)
324
325 value = property(fset=_set_value)
326
327
f0a42b33 328class _IntegerFieldConst(_IntegralFieldConst, _FieldConst):
81447b5b
PP
329 pass
330
331
f0a42b33 332class _IntegerField(_IntegerFieldConst, _IntegralField, _Field):
1198c635
FD
333 def _check_range(self, value):
334 if not (value >= self._lower_bound and value <= self._upper_bound):
335 raise ValueError(
336 "Value {} is outside valid range [{}, {}]".format(
337 value, self._lower_bound, self._upper_bound
338 )
339 )
f0a42b33
FD
340
341
342class _UnsignedIntegerFieldConst(_IntegerFieldConst, _FieldConst):
343 _NAME = 'Const unsigned integer'
1eccc498 344
f0a42b33
FD
345 @classmethod
346 def _value_to_int(cls, value):
25bb9bab
PP
347 if not isinstance(value, numbers.Integral):
348 raise TypeError('expecting an integral number object')
81447b5b 349
1198c635 350 return int(value)
81447b5b
PP
351
352 @property
e1c6bebd 353 def _value(self):
9c08c816 354 return native_bt.field_integer_unsigned_get_value(self._ptr)
81447b5b 355
f0a42b33
FD
356
357class _UnsignedIntegerField(_UnsignedIntegerFieldConst, _IntegerField, _Field):
358 _NAME = 'Unsigned integer'
359
2ae9f48c
SM
360 def _set_value(self, value):
361 value = self._value_to_int(value)
1198c635
FD
362
363 self._check_range(value)
364
9c08c816 365 native_bt.field_integer_unsigned_set_value(self._ptr, value)
2ae9f48c
SM
366
367 value = property(fset=_set_value)
368
1198c635
FD
369 @property
370 def _lower_bound(self):
371 return 0
372
373 @property
374 def _upper_bound(self):
375 return (2 ** self.cls.field_value_range) - 1
376
2ae9f48c 377
f0a42b33
FD
378class _SignedIntegerFieldConst(_IntegerFieldConst, _FieldConst):
379 _NAME = 'Const signed integer'
1eccc498 380
f0a42b33
FD
381 @classmethod
382 def _value_to_int(cls, value):
25bb9bab
PP
383 if not isinstance(value, numbers.Integral):
384 raise TypeError('expecting an integral number object')
e1c6bebd 385
1198c635 386 return int(value)
81447b5b 387
2ae9f48c
SM
388 @property
389 def _value(self):
9c08c816 390 return native_bt.field_integer_signed_get_value(self._ptr)
2ae9f48c 391
f0a42b33
FD
392
393class _SignedIntegerField(_SignedIntegerFieldConst, _IntegerField, _Field):
394 _NAME = 'Signed integer'
395
e1c6bebd 396 def _set_value(self, value):
81447b5b 397 value = self._value_to_int(value)
1198c635
FD
398
399 self._check_range(value)
400
9c08c816 401 native_bt.field_integer_signed_set_value(self._ptr, value)
81447b5b 402
e1c6bebd 403 value = property(fset=_set_value)
81447b5b 404
1198c635
FD
405 @property
406 def _lower_bound(self):
407 return -1 * (2 ** (self.cls.field_value_range - 1))
408
409 @property
410 def _upper_bound(self):
411 return (2 ** (self.cls.field_value_range - 1)) - 1
412
0b03f63e 413
f0a42b33
FD
414class _RealFieldConst(_NumericFieldConst, numbers.Real):
415 _NAME = 'Const real'
81447b5b 416
f0a42b33
FD
417 @classmethod
418 def _value_to_float(cls, value):
81447b5b
PP
419 if not isinstance(value, numbers.Real):
420 raise TypeError("expecting a real number object")
421
422 return float(value)
423
424 @property
e1c6bebd 425 def _value(self):
2ae9f48c 426 return native_bt.field_real_get_value(self._ptr)
81447b5b 427
f0a42b33
FD
428
429class _RealField(_RealFieldConst, _NumericField):
430 _NAME = 'Real'
431
e1c6bebd 432 def _set_value(self, value):
81447b5b 433 value = self._value_to_float(value)
2ae9f48c 434 native_bt.field_real_set_value(self._ptr, value)
81447b5b 435
e1c6bebd 436 value = property(fset=_set_value)
81447b5b 437
0b03f63e 438
f0a42b33 439class _EnumerationFieldConst(_IntegerFieldConst):
1eccc498
SM
440 def _repr(self):
441 return '{} ({})'.format(self._value, ', '.join(self.labels))
81447b5b
PP
442
443 @property
1eccc498 444 def labels(self):
d24d5663 445 status, labels = self._get_mapping_labels(self._ptr)
cfbd7cf3 446 utils._handle_func_status(status, "cannot get label for enumeration field")
81447b5b 447
1eccc498
SM
448 assert labels is not None
449 return labels
81447b5b 450
4addd228 451
f0a42b33
FD
452class _EnumerationField(_EnumerationFieldConst, _IntegerField):
453 pass
454
455
456class _UnsignedEnumerationFieldConst(
457 _EnumerationFieldConst, _UnsignedIntegerFieldConst
458):
459 _NAME = 'Const unsigned Enumeration'
cfbd7cf3 460 _get_mapping_labels = staticmethod(
9c08c816 461 native_bt.field_enumeration_unsigned_get_mapping_labels
cfbd7cf3 462 )
e1c6bebd 463
e1c6bebd 464
f0a42b33
FD
465class _UnsignedEnumerationField(
466 _UnsignedEnumerationFieldConst, _EnumerationField, _UnsignedIntegerField
467):
468 _NAME = 'Unsigned enumeration'
469
470
471class _SignedEnumerationFieldConst(_EnumerationFieldConst, _SignedIntegerFieldConst):
472 _NAME = 'Const signed Enumeration'
cfbd7cf3 473 _get_mapping_labels = staticmethod(
9c08c816 474 native_bt.field_enumeration_signed_get_mapping_labels
cfbd7cf3 475 )
81447b5b
PP
476
477
f0a42b33
FD
478class _SignedEnumerationField(
479 _SignedEnumerationFieldConst, _EnumerationField, _SignedIntegerField
480):
481 _NAME = 'Signed enumeration'
482
483
81447b5b 484@functools.total_ordering
f0a42b33
FD
485class _StringFieldConst(_FieldConst):
486 _NAME = 'Const string'
81447b5b 487
f0a42b33
FD
488 @classmethod
489 def _value_to_str(cls, value):
490 if isinstance(value, _StringFieldConst):
e1c6bebd 491 value = value._value
81447b5b
PP
492
493 if not isinstance(value, str):
494 raise TypeError("expecting a 'str' object")
495
496 return value
497
498 @property
e1c6bebd 499 def _value(self):
1eccc498 500 return native_bt.field_string_get_value(self._ptr)
81447b5b 501
e1c6bebd 502 def _spec_eq(self, other):
81447b5b 503 try:
f11ed062 504 return self._value == self._value_to_str(other)
4c4935bf 505 except Exception:
81447b5b
PP
506 return False
507
81447b5b 508 def __lt__(self, other):
e1c6bebd 509 return self._value < self._value_to_str(other)
81447b5b
PP
510
511 def __bool__(self):
e1c6bebd 512 return bool(self._value)
81447b5b 513
dda659b3
FD
514 def __hash__(self):
515 return hash(self._value)
516
12bf0d88 517 def _repr(self):
d623d2e9
JG
518 return repr(self._value)
519
81447b5b 520 def __str__(self):
1eccc498 521 return str(self._value)
81447b5b
PP
522
523 def __getitem__(self, index):
e1c6bebd 524 return self._value[index]
81447b5b
PP
525
526 def __len__(self):
1eccc498 527 return native_bt.field_string_get_length(self._ptr)
81447b5b 528
f0a42b33
FD
529
530class _StringField(_StringFieldConst, _Field):
531 _NAME = 'String'
532
533 def _set_value(self, value):
534 value = self._value_to_str(value)
535 native_bt.field_string_set_value(self._ptr, value)
536
537 value = property(fset=_set_value)
538
81447b5b
PP
539 def __iadd__(self, value):
540 value = self._value_to_str(value)
d24d5663 541 status = native_bt.field_string_append(self._ptr, value)
cfbd7cf3
FD
542 utils._handle_func_status(
543 status, "cannot append to string field object's value"
544 )
81447b5b
PP
545 return self
546
dda659b3
FD
547 def __hash__(self):
548 # Non const field are not hashable as their value may be modified
549 # without changing the underlying Python object.
550 raise TypeError('unhashable type: \'{}\''.format(self._NAME))
551
81447b5b 552
f0a42b33 553class _ContainerFieldConst(_FieldConst):
81447b5b
PP
554 def __bool__(self):
555 return len(self) != 0
556
f0a42b33
FD
557 def _count(self):
558 return len(self.cls)
559
81447b5b
PP
560 def __len__(self):
561 count = self._count()
1eccc498 562 assert count >= 0
81447b5b
PP
563 return count
564
565 def __delitem__(self, index):
566 raise NotImplementedError
567
f0a42b33
FD
568 def __setitem__(self, index, value):
569 raise TypeError(
570 '\'{}\' object does not support item assignment'.format(self.__class__)
571 )
81447b5b 572
81447b5b 573
f0a42b33
FD
574class _ContainerField(_ContainerFieldConst, _Field):
575 pass
81447b5b 576
81447b5b 577
f0a42b33
FD
578class _StructureFieldConst(_ContainerFieldConst, collections.abc.Mapping):
579 _NAME = 'Const structure'
580 _borrow_member_field_ptr_by_index = staticmethod(
581 native_bt.field_structure_borrow_member_field_by_index_const
582 )
583 _borrow_member_field_ptr_by_name = staticmethod(
584 native_bt.field_structure_borrow_member_field_by_name_const
585 )
586
587 def _count(self):
588 return len(self.cls)
81447b5b 589
81447b5b
PP
590 def __iter__(self):
591 # same name iterator
d8e2073c 592 return iter(self.cls)
81447b5b 593
e1c6bebd 594 def _spec_eq(self, other):
f11ed062
PP
595 if not isinstance(other, collections.abc.Mapping):
596 return False
81447b5b 597
f11ed062
PP
598 if len(self) != len(other):
599 # early mismatch
600 return False
81447b5b 601
f11ed062
PP
602 for self_key in self:
603 if self_key not in other:
604 return False
81447b5b 605
f11ed062
PP
606 if self[self_key] != other[self_key]:
607 return False
e1c6bebd 608
f11ed062 609 return True
81447b5b 610
12bf0d88 611 def _repr(self):
ac7e2dc6
JG
612 items = ['{}: {}'.format(repr(k), repr(v)) for k, v in self.items()]
613 return '{{{}}}'.format(', '.join(items))
614
1eccc498
SM
615 def __getitem__(self, key):
616 utils._check_str(key)
f0a42b33 617 field_ptr = self._borrow_member_field_ptr_by_name(self._ptr, key)
0b03f63e 618
1eccc498
SM
619 if field_ptr is None:
620 raise KeyError(key)
81447b5b 621
f0a42b33 622 return self._create_field_from_ptr(
cfbd7cf3
FD
623 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
624 )
811644b8 625
1eccc498
SM
626 def member_at_index(self, index):
627 utils._check_uint64(index)
811644b8 628
1eccc498
SM
629 if index >= len(self):
630 raise IndexError
f0a42b33 631 field_ptr = self._borrow_member_field_ptr_by_index(self._ptr, index)
1eccc498 632 assert field_ptr is not None
f0a42b33 633 return self._create_field_from_ptr(
cfbd7cf3
FD
634 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
635 )
1eccc498
SM
636
637
f0a42b33
FD
638class _StructureField(
639 _StructureFieldConst, _ContainerField, collections.abc.MutableMapping
640):
641 _NAME = 'Structure'
642 _borrow_member_field_ptr_by_index = staticmethod(
643 native_bt.field_structure_borrow_member_field_by_index
644 )
645 _borrow_member_field_ptr_by_name = staticmethod(
646 native_bt.field_structure_borrow_member_field_by_name
647 )
648
649 def __setitem__(self, key, value):
650 # raises if key is somehow invalid
651 field = self[key]
652
653 # the field's property does the appropriate conversion or raises
654 # the appropriate exception
655 field.value = value
656
657 def _set_value(self, values):
658 try:
659 for key, value in values.items():
660 self[key].value = value
661 except Exception:
662 raise
663
664 value = property(fset=_set_value)
665
666
667class _OptionFieldConst(_FieldConst):
668 _NAME = 'Const option'
669 _borrow_field_ptr = staticmethod(native_bt.field_option_borrow_field_const)
cec0261d
PP
670
671 @property
672 def field(self):
f0a42b33 673 field_ptr = self._borrow_field_ptr(self._ptr)
cec0261d
PP
674
675 if field_ptr is None:
676 return
677
f0a42b33 678 return self._create_field_from_ptr(
cec0261d
PP
679 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
680 )
681
682 @property
683 def has_field(self):
684 return self.field is not None
685
cec0261d
PP
686 def _spec_eq(self, other):
687 return _get_leaf_field(self) == other
688
689 def __bool__(self):
690 return self.has_field
691
692 def __str__(self):
693 return str(self.field)
694
695 def _repr(self):
696 return repr(self.field)
697
f0a42b33
FD
698
699class _OptionField(_OptionFieldConst, _Field):
700 _NAME = 'Option'
701 _borrow_field_ptr = staticmethod(native_bt.field_option_borrow_field)
702
703 def _has_field(self, value):
704 utils._check_bool(value)
705 native_bt.field_option_set_has_field(self._ptr, value)
706
707 has_field = property(fget=_OptionFieldConst.has_field.fget, fset=_has_field)
708
cec0261d
PP
709 def _set_value(self, value):
710 self.has_field = True
711 field = self.field
712 assert field is not None
713 field.value = value
714
715 value = property(fset=_set_value)
716
717
f0a42b33
FD
718class _VariantFieldConst(_ContainerFieldConst, _FieldConst):
719 _NAME = 'Const variant'
720 _borrow_selected_option_field_ptr = staticmethod(
721 native_bt.field_variant_borrow_selected_option_field_const
722 )
81447b5b 723
2b9aa00b
FD
724 def _count(self):
725 return len(self.cls)
726
81447b5b 727 @property
1eccc498
SM
728 def selected_option_index(self):
729 return native_bt.field_variant_get_selected_option_field_index(self._ptr)
81447b5b 730
1eccc498
SM
731 @property
732 def selected_option(self):
5ae9f1bf
SM
733 # TODO: Is there a way to check if the variant field has a selected_option,
734 # so we can raise an exception instead of hitting a pre-condition check?
735 # If there is something, that check should be added to selected_option_index too.
f0a42b33 736 field_ptr = self._borrow_selected_option_field_ptr(self._ptr)
81447b5b 737
f0a42b33 738 return self._create_field_from_ptr(
cfbd7cf3
FD
739 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
740 )
81447b5b 741
e1c6bebd 742 def _spec_eq(self, other):
f11ed062 743 return _get_leaf_field(self) == other
811644b8
PP
744
745 def __bool__(self):
1eccc498 746 raise NotImplementedError
81447b5b 747
12bf0d88 748 def __str__(self):
1eccc498 749 return str(self.selected_option)
12bf0d88
JG
750
751 def _repr(self):
1eccc498 752 return repr(self.selected_option)
e1c6bebd 753
f0a42b33
FD
754
755class _VariantField(_VariantFieldConst, _ContainerField, _Field):
756 _NAME = 'Variant'
757 _borrow_selected_option_field_ptr = staticmethod(
758 native_bt.field_variant_borrow_selected_option_field
759 )
760
761 def _selected_option_index(self, index):
762 if index < 0 or index >= len(self):
763 raise IndexError('{} field object index is out of range'.format(self._NAME))
764
765 native_bt.field_variant_select_option_field_by_index(self._ptr, index)
766
767 selected_option_index = property(
768 fget=_VariantFieldConst.selected_option_index.fget, fset=_selected_option_index
769 )
770
e1c6bebd 771 def _set_value(self, value):
1eccc498 772 self.selected_option.value = value
e1c6bebd
JG
773
774 value = property(fset=_set_value)
81447b5b 775
0b03f63e 776
f0a42b33
FD
777class _ArrayFieldConst(_ContainerFieldConst, _FieldConst, collections.abc.Sequence):
778 _borrow_element_field_ptr_by_index = staticmethod(
779 native_bt.field_array_borrow_element_field_by_index_const
780 )
781
1eccc498
SM
782 def _get_length(self):
783 return native_bt.field_array_get_length(self._ptr)
784
785 length = property(fget=_get_length)
786
81447b5b
PP
787 def __getitem__(self, index):
788 if not isinstance(index, numbers.Integral):
cfbd7cf3
FD
789 raise TypeError(
790 "'{}' is not an integral number object: invalid index".format(
791 index.__class__.__name__
792 )
793 )
81447b5b
PP
794
795 index = int(index)
796
797 if index < 0 or index >= len(self):
798 raise IndexError('{} field object index is out of range'.format(self._NAME))
799
f0a42b33 800 field_ptr = self._borrow_element_field_ptr_by_index(self._ptr, index)
cfbd7cf3 801 assert field_ptr
f0a42b33 802 return self._create_field_from_ptr(
cfbd7cf3
FD
803 field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
804 )
81447b5b 805
81447b5b
PP
806 def insert(self, index, value):
807 raise NotImplementedError
808
e1c6bebd 809 def _spec_eq(self, other):
f11ed062
PP
810 if not isinstance(other, collections.abc.Sequence):
811 return False
7c54e2e7 812
f11ed062
PP
813 if len(self) != len(other):
814 # early mismatch
e1c6bebd 815 return False
7c54e2e7 816
f11ed062
PP
817 for self_elem, other_elem in zip(self, other):
818 if self_elem != other_elem:
819 return False
820
821 return True
822
12bf0d88 823 def _repr(self):
2bc21382
JG
824 return '[{}]'.format(', '.join([repr(v) for v in self]))
825
81447b5b 826
f0a42b33
FD
827class _ArrayField(
828 _ArrayFieldConst, _ContainerField, _Field, collections.abc.MutableSequence
829):
830 _borrow_element_field_ptr_by_index = staticmethod(
831 native_bt.field_array_borrow_element_field_by_index
832 )
833
834 def __setitem__(self, index, value):
835 # raises if index is somehow invalid
836 field = self[index]
837
838 if not isinstance(field, (_NumericField, _StringField)):
839 raise TypeError('can only set the value of a number or string field')
840
841 # the field's property does the appropriate conversion or raises
842 # the appropriate exception
843 field.value = value
844
845
846class _StaticArrayFieldConst(_ArrayFieldConst, _FieldConst):
847 _NAME = 'Const static array'
81447b5b
PP
848
849 def _count(self):
1eccc498 850 return native_bt.field_array_get_length(self._ptr)
81447b5b 851
f0a42b33
FD
852
853class _StaticArrayField(_StaticArrayFieldConst, _ArrayField, _Field):
854 _NAME = 'Static array'
855
e1c6bebd
JG
856 def _set_value(self, values):
857 if len(self) != len(values):
cfbd7cf3 858 raise ValueError('expected length of value and array field to match')
e1c6bebd 859
1eccc498
SM
860 for index, value in enumerate(values):
861 if value is not None:
862 self[index].value = value
e1c6bebd
JG
863
864 value = property(fset=_set_value)
865
81447b5b 866
f0a42b33
FD
867class _DynamicArrayFieldConst(_ArrayFieldConst, _FieldConst):
868 _NAME = 'Const dynamic array'
81447b5b
PP
869
870 def _count(self):
1eccc498 871 return self.length
81447b5b 872
f0a42b33
FD
873
874class _DynamicArrayField(_DynamicArrayFieldConst, _ArrayField, _Field):
875 _NAME = 'Dynamic array'
876
1eccc498
SM
877 def _set_length(self, length):
878 utils._check_uint64(length)
9c08c816 879 status = native_bt.field_array_dynamic_set_length(self._ptr, length)
d24d5663 880 utils._handle_func_status(status, "cannot set dynamic array length")
81447b5b 881
1eccc498 882 length = property(fget=_ArrayField._get_length, fset=_set_length)
81447b5b 883
e1c6bebd 884 def _set_value(self, values):
1eccc498
SM
885 if len(values) != self.length:
886 self.length = len(values)
e1c6bebd 887
1eccc498
SM
888 for index, value in enumerate(values):
889 if value is not None:
890 self[index].value = value
e1c6bebd
JG
891
892 value = property(fset=_set_value)
81447b5b 893
0b03f63e 894
f0a42b33
FD
895_TYPE_ID_TO_CONST_OBJ = {
896 native_bt.FIELD_CLASS_TYPE_BOOL: _BoolFieldConst,
897 native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayFieldConst,
898 native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerFieldConst,
899 native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerFieldConst,
900 native_bt.FIELD_CLASS_TYPE_REAL: _RealFieldConst,
901 native_bt.FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: _UnsignedEnumerationFieldConst,
902 native_bt.FIELD_CLASS_TYPE_SIGNED_ENUMERATION: _SignedEnumerationFieldConst,
903 native_bt.FIELD_CLASS_TYPE_STRING: _StringFieldConst,
904 native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureFieldConst,
905 native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayFieldConst,
906 native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY: _DynamicArrayFieldConst,
907 native_bt.FIELD_CLASS_TYPE_OPTION: _OptionFieldConst,
908 native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantFieldConst,
909 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: _VariantFieldConst,
910 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: _VariantFieldConst,
911}
912
81447b5b 913_TYPE_ID_TO_OBJ = {
aae30e61 914 native_bt.FIELD_CLASS_TYPE_BOOL: _BoolField,
ead8c3d4 915 native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayField,
2ae9f48c
SM
916 native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerField,
917 native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerField,
918 native_bt.FIELD_CLASS_TYPE_REAL: _RealField,
1eccc498
SM
919 native_bt.FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: _UnsignedEnumerationField,
920 native_bt.FIELD_CLASS_TYPE_SIGNED_ENUMERATION: _SignedEnumerationField,
2ae9f48c
SM
921 native_bt.FIELD_CLASS_TYPE_STRING: _StringField,
922 native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureField,
1eccc498
SM
923 native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayField,
924 native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY: _DynamicArrayField,
cec0261d 925 native_bt.FIELD_CLASS_TYPE_OPTION: _OptionField,
45c51519
PP
926 native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantField,
927 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: _VariantField,
928 native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: _VariantField,
81447b5b 929}
This page took 0.094831 seconds and 4 git commands to generate.