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