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