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