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