bt2: add user attributes property support
[babeltrace.git] / src / bindings / python / bt2 / bt2 / field_class.py
index 7f25136889e3d494573f52ff5d664d857492ac9f..d467bcc4129fa8a986fb3dc47054e3fd25e1f0ef 100644 (file)
@@ -22,9 +22,9 @@
 
 from bt2 import native_bt, object, utils
 import collections.abc
-import bt2.field
-import bt2.field_path
-import bt2.integer_range_set
+from bt2 import field_path as bt2_field_path
+from bt2 import integer_range_set as bt2_integer_range_set
+from bt2 import value as bt2_value
 import bt2
 
 
@@ -46,10 +46,37 @@ class _FieldClass(object._SharedObject):
 
     def _check_create_status(self, ptr):
         if ptr is None:
-            raise bt2.MemoryError(
+            raise bt2._MemoryError(
                 'cannot create {} field class object'.format(self._NAME.lower())
             )
 
+    @property
+    def user_attributes(self):
+        ptr = native_bt.field_class_borrow_user_attributes(self._ptr)
+        assert ptr is not None
+        return bt2_value._create_from_ptr_and_get_ref(ptr)
+
+    def _user_attributes(self, user_attributes):
+        value = bt2_value.create_value(user_attributes)
+        utils._check_type(value, bt2_value.MapValue)
+        native_bt.field_class_set_user_attributes(self._ptr, value._ptr)
+
+    _user_attributes = property(fset=_user_attributes)
+
+
+class _BoolFieldClass(_FieldClass):
+    _NAME = 'Boolean'
+
+
+class _BitArrayFieldClass(_FieldClass):
+    _NAME = 'Bit array'
+
+    @property
+    def length(self):
+        length = native_bt.field_class_bit_array_get_length(self._ptr)
+        assert length >= 1
+        return length
+
 
 class _IntegerFieldClass(_FieldClass):
     @property
@@ -134,7 +161,7 @@ class _EnumerationFieldClassMapping:
 
 
 class _UnsignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping):
-    _ranges_type = bt2.integer_range_set.UnsignedIntegerRangeSet
+    _ranges_type = bt2_integer_range_set.UnsignedIntegerRangeSet
     _as_enumeration_field_class_mapping_ptr = staticmethod(
         native_bt.field_class_enumeration_unsigned_mapping_as_mapping_const
     )
@@ -144,7 +171,7 @@ class _UnsignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping):
 
 
 class _SignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping):
-    _ranges_type = bt2.integer_range_set.SignedIntegerRangeSet
+    _ranges_type = bt2_integer_range_set.SignedIntegerRangeSet
     _as_enumeration_field_class_mapping_ptr = staticmethod(
         native_bt.field_class_enumeration_signed_mapping_as_mapping_const
     )
@@ -203,7 +230,7 @@ class _UnsignedEnumerationFieldClass(
     _EnumerationFieldClass, _UnsignedIntegerFieldClass
 ):
     _NAME = 'Unsigned enumeration'
-    _range_set_type = bt2.integer_range_set.UnsignedIntegerRangeSet
+    _range_set_type = bt2_integer_range_set.UnsignedIntegerRangeSet
     _add_mapping = staticmethod(native_bt.field_class_enumeration_unsigned_add_mapping)
 
     @staticmethod
@@ -235,7 +262,7 @@ class _UnsignedEnumerationFieldClass(
 
 class _SignedEnumerationFieldClass(_EnumerationFieldClass, _SignedIntegerFieldClass):
     _NAME = 'Signed enumeration'
-    _range_set_type = bt2.integer_range_set.SignedIntegerRangeSet
+    _range_set_type = bt2_integer_range_set.SignedIntegerRangeSet
     _add_mapping = staticmethod(native_bt.field_class_enumeration_signed_add_mapping)
 
     @staticmethod
@@ -270,29 +297,58 @@ class _StringFieldClass(_FieldClass):
 
 
 class _StructureFieldClassMember:
-    def __init__(self, name, field_class):
-        self._name = name
-        self._field_class = field_class
+    def __init__(self, owning_struct_fc, member_ptr):
+        # this field class owns the member; keeping it here maintains
+        # the member alive as members are not shared objects
+        self._owning_struct_fc = owning_struct_fc
+        self._ptr = member_ptr
 
     @property
     def name(self):
-        return self._name
+        name = native_bt.field_class_structure_member_get_name(self._ptr)
+        assert name is not None
+        return name
 
     @property
     def field_class(self):
-        return self._field_class
+        fc_ptr = native_bt.field_class_structure_member_borrow_field_class_const(
+            self._ptr
+        )
+        assert fc_ptr is not None
+        return _create_field_class_from_ptr_and_get_ref(fc_ptr)
+
+    @property
+    def user_attributes(self):
+        ptr = native_bt.field_class_structure_member_borrow_user_attributes(self._ptr)
+        assert ptr is not None
+        return bt2_value._create_from_ptr_and_get_ref(ptr)
+
+    def _user_attributes(self, user_attributes):
+        value = bt2_value.create_value(user_attributes)
+        utils._check_type(value, bt2_value.MapValue)
+        native_bt.field_class_structure_member_set_user_attributes(
+            self._ptr, value._ptr
+        )
+
+    _user_attributes = property(fset=_user_attributes)
 
 
 class _StructureFieldClass(_FieldClass, collections.abc.Mapping):
     _NAME = 'Structure'
 
-    def append_member(self, name, field_class):
+    def append_member(self, name, field_class, user_attributes=None):
         utils._check_str(name)
         utils._check_type(field_class, _FieldClass)
 
         if name in self:
             raise ValueError("duplicate member name '{}'".format(name))
 
+        user_attributes_value = None
+
+        if user_attributes is not None:
+            # check now that user attributes are valid
+            user_attributes_value = bt2.create_value(user_attributes)
+
         status = native_bt.field_class_structure_append_member(
             self._ptr, name, field_class._ptr
         )
@@ -300,21 +356,16 @@ class _StructureFieldClass(_FieldClass, collections.abc.Mapping):
             status, 'cannot append member to structure field class object'
         )
 
+        if user_attributes is not None:
+            self[name]._user_attributes = user_attributes_value
+
     def __len__(self):
         count = native_bt.field_class_structure_get_member_count(self._ptr)
         assert count >= 0
         return count
 
-    @staticmethod
-    def _create_member_from_ptr(member_ptr):
-        name = native_bt.field_class_structure_member_get_name(member_ptr)
-        assert name is not None
-        fc_ptr = native_bt.field_class_structure_member_borrow_field_class_const(
-            member_ptr
-        )
-        assert fc_ptr is not None
-        fc = _create_field_class_from_ptr_and_get_ref(fc_ptr)
-        return _StructureFieldClassMember(name, fc)
+    def _create_member_from_ptr(self, member_ptr):
+        return _StructureFieldClassMember(self, member_ptr)
 
     def __getitem__(self, key):
         if not isinstance(key, str):
@@ -358,28 +409,54 @@ class _StructureFieldClass(_FieldClass, collections.abc.Mapping):
         return self._create_member_from_ptr(member_ptr)
 
 
+class _OptionFieldClass(_FieldClass):
+    @property
+    def field_class(self):
+        elem_fc_ptr = native_bt.field_class_option_borrow_field_class_const(self._ptr)
+        return _create_field_class_from_ptr_and_get_ref(elem_fc_ptr)
+
+    @property
+    def selector_field_path(self):
+        ptr = native_bt.field_class_option_borrow_selector_field_path_const(self._ptr)
+        if ptr is None:
+            return
+
+        return bt2_field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
+
+
 class _VariantFieldClassOption:
-    def __init__(self, name, field_class):
-        self._name = name
-        self._field_class = field_class
+    def __init__(self, owning_var_fc, option_ptr):
+        # this field class owns the option; keeping it here maintains
+        # the option alive as options are not shared objects
+        self._owning_var_fc = owning_var_fc
+        self._ptr = option_ptr
 
     @property
     def name(self):
-        return self._name
+        name = native_bt.field_class_variant_option_get_name(self._ptr)
+        assert name is not None
+        return name
 
     @property
     def field_class(self):
-        return self._field_class
+        fc_ptr = native_bt.field_class_variant_option_borrow_field_class_const(
+            self._ptr
+        )
+        assert fc_ptr is not None
+        return _create_field_class_from_ptr_and_get_ref(fc_ptr)
 
+    @property
+    def user_attributes(self):
+        ptr = native_bt.field_class_variant_option_borrow_user_attributes(self._ptr)
+        assert ptr is not None
+        return bt2_value._create_from_ptr_and_get_ref(ptr)
 
-class _VariantFieldClassWithSelectorOption(_VariantFieldClassOption):
-    def __init__(self, name, field_class, ranges):
-        super().__init__(name, field_class)
-        self._ranges = ranges
+    def _user_attributes(self, user_attributes):
+        value = bt2_value.create_value(user_attributes)
+        utils._check_type(value, bt2_value.MapValue)
+        native_bt.field_class_variant_option_set_user_attributes(self._ptr, value._ptr)
 
-    @property
-    def ranges(self):
-        return self._ranges
+    _user_attributes = property(fset=_user_attributes)
 
 
 class _VariantFieldClass(_FieldClass, collections.abc.Mapping):
@@ -396,12 +473,7 @@ class _VariantFieldClass(_FieldClass, collections.abc.Mapping):
         return opt_ptr
 
     def _create_option_from_ptr(self, opt_ptr):
-        name = native_bt.field_class_variant_option_get_name(opt_ptr)
-        assert name is not None
-        fc_ptr = native_bt.field_class_variant_option_borrow_field_class_const(opt_ptr)
-        assert fc_ptr is not None
-        fc = _create_field_class_from_ptr_and_get_ref(fc_ptr)
-        return _VariantFieldClassOption(name, fc)
+        return _VariantFieldClassOption(self, opt_ptr)
 
     def __len__(self):
         count = native_bt.field_class_variant_get_option_count(self._ptr)
@@ -442,13 +514,19 @@ class _VariantFieldClass(_FieldClass, collections.abc.Mapping):
 class _VariantFieldClassWithoutSelector(_VariantFieldClass):
     _NAME = 'Variant (without selector)'
 
-    def append_option(self, name, field_class):
+    def append_option(self, name, field_class, user_attributes=None):
         utils._check_str(name)
         utils._check_type(field_class, _FieldClass)
 
         if name in self:
             raise ValueError("duplicate option name '{}'".format(name))
 
+        user_attributes_value = None
+
+        if user_attributes is not None:
+            # check now that user attributes are valid
+            user_attributes_value = bt2.create_value(user_attributes)
+
         status = native_bt.field_class_variant_without_selector_append_option(
             self._ptr, name, field_class._ptr
         )
@@ -456,6 +534,9 @@ class _VariantFieldClassWithoutSelector(_VariantFieldClass):
             status, 'cannot append option to variant field class object'
         )
 
+        if user_attributes is not None:
+            self[name]._user_attributes = user_attributes_value
+
     def __iadd__(self, options):
         for name, field_class in options:
             self.append_option(name, field_class)
@@ -463,22 +544,45 @@ class _VariantFieldClassWithoutSelector(_VariantFieldClass):
         return self
 
 
+class _VariantFieldClassWithSelectorOption(_VariantFieldClassOption):
+    def __init__(self, owning_var_fc, spec_opt_ptr):
+        self._spec_ptr = spec_opt_ptr
+        super().__init__(owning_var_fc, self._as_option_ptr(spec_opt_ptr))
+
+    @property
+    def ranges(self):
+        range_set_ptr = self._borrow_ranges_ptr(self._spec_ptr)
+        assert range_set_ptr is not None
+        return self._range_set_type._create_from_ptr_and_get_ref(range_set_ptr)
+
+
+class _VariantFieldClassWithSignedSelectorOption(_VariantFieldClassWithSelectorOption):
+    _as_option_ptr = staticmethod(
+        native_bt.field_class_variant_with_selector_signed_option_as_option_const
+    )
+    _borrow_ranges_ptr = staticmethod(
+        native_bt.field_class_variant_with_selector_signed_option_borrow_ranges_const
+    )
+    _range_set_type = bt2_integer_range_set.SignedIntegerRangeSet
+
+
+class _VariantFieldClassWithUnsignedSelectorOption(
+    _VariantFieldClassWithSelectorOption
+):
+    _as_option_ptr = staticmethod(
+        native_bt.field_class_variant_with_selector_unsigned_option_as_option_const
+    )
+    _borrow_ranges_ptr = staticmethod(
+        native_bt.field_class_variant_with_selector_unsigned_option_borrow_ranges_const
+    )
+    _range_set_type = bt2_integer_range_set.UnsignedIntegerRangeSet
+
+
 class _VariantFieldClassWithSelector(_VariantFieldClass):
     _NAME = 'Variant (with selector)'
 
     def _create_option_from_ptr(self, opt_ptr):
-        base_opt_ptr = self._as_option_ptr(opt_ptr)
-        name = native_bt.field_class_variant_option_get_name(base_opt_ptr)
-        assert name is not None
-        fc_ptr = native_bt.field_class_variant_option_borrow_field_class_const(
-            base_opt_ptr
-        )
-        assert fc_ptr is not None
-        fc = _create_field_class_from_ptr_and_get_ref(fc_ptr)
-        range_set_ptr = self._option_borrow_ranges_ptr(opt_ptr)
-        assert range_set_ptr is not None
-        range_set = self._range_set_type._create_from_ptr_and_get_ref(range_set_ptr)
-        return _VariantFieldClassWithSelectorOption(name, fc, range_set)
+        return self._option_type(self, opt_ptr)
 
     @property
     def selector_field_path(self):
@@ -489,12 +593,12 @@ class _VariantFieldClassWithSelector(_VariantFieldClass):
         if ptr is None:
             return
 
-        return bt2.field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
+        return bt2_field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
 
-    def append_option(self, name, field_class, ranges):
+    def append_option(self, name, field_class, ranges, user_attributes=None):
         utils._check_str(name)
         utils._check_type(field_class, _FieldClass)
-        utils._check_type(ranges, self._range_set_type)
+        utils._check_type(ranges, self._option_type._range_set_type)
 
         if name in self:
             raise ValueError("duplicate option name '{}'".format(name))
@@ -502,6 +606,12 @@ class _VariantFieldClassWithSelector(_VariantFieldClass):
         if len(ranges) == 0:
             raise ValueError('range set is empty')
 
+        user_attributes_value = None
+
+        if user_attributes is not None:
+            # check now that user attributes are valid
+            user_attributes_value = bt2.create_value(user_attributes)
+
         # TODO: check overlaps (precondition of self._append_option())
 
         status = self._append_option(self._ptr, name, field_class._ptr, ranges._ptr)
@@ -509,6 +619,9 @@ class _VariantFieldClassWithSelector(_VariantFieldClass):
             status, 'cannot append option to variant field class object'
         )
 
+        if user_attributes is not None:
+            self[name]._user_attributes = user_attributes_value
+
     def __iadd__(self, options):
         for name, field_class, ranges in options:
             self.append_option(name, field_class, ranges)
@@ -524,16 +637,11 @@ class _VariantFieldClassWithUnsignedSelector(_VariantFieldClassWithSelector):
     _borrow_member_by_index_ptr = staticmethod(
         native_bt.field_class_variant_with_selector_unsigned_borrow_option_by_index_const
     )
-    _as_option_ptr = staticmethod(
-        native_bt.field_class_variant_with_selector_unsigned_option_as_option_const
-    )
     _append_option = staticmethod(
         native_bt.field_class_variant_with_selector_unsigned_append_option
     )
-    _option_borrow_ranges_ptr = staticmethod(
-        native_bt.field_class_variant_with_selector_unsigned_option_borrow_ranges_const
-    )
-    _range_set_type = bt2.integer_range_set.UnsignedIntegerRangeSet
+    _option_type = _VariantFieldClassWithUnsignedSelectorOption
+    _as_option_ptr = staticmethod(_option_type._as_option_ptr)
 
 
 class _VariantFieldClassWithSignedSelector(_VariantFieldClassWithSelector):
@@ -544,16 +652,11 @@ class _VariantFieldClassWithSignedSelector(_VariantFieldClassWithSelector):
     _borrow_member_by_index_ptr = staticmethod(
         native_bt.field_class_variant_with_selector_signed_borrow_option_by_index_const
     )
-    _as_option_ptr = staticmethod(
-        native_bt.field_class_variant_with_selector_signed_option_as_option_const
-    )
     _append_option = staticmethod(
         native_bt.field_class_variant_with_selector_signed_append_option
     )
-    _option_borrow_ranges_ptr = staticmethod(
-        native_bt.field_class_variant_with_selector_signed_option_borrow_ranges_const
-    )
-    _range_set_type = bt2.integer_range_set.SignedIntegerRangeSet
+    _option_type = _VariantFieldClassWithSignedSelectorOption
+    _as_option_ptr = staticmethod(_option_type._as_option_ptr)
 
 
 class _ArrayFieldClass(_FieldClass):
@@ -580,10 +683,12 @@ class _DynamicArrayFieldClass(_ArrayFieldClass):
         if ptr is None:
             return
 
-        return bt2.field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
+        return bt2_field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
 
 
 _FIELD_CLASS_TYPE_TO_OBJ = {
+    native_bt.FIELD_CLASS_TYPE_BOOL: _BoolFieldClass,
+    native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayFieldClass,
     native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerFieldClass,
     native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerFieldClass,
     native_bt.FIELD_CLASS_TYPE_REAL: _RealFieldClass,
@@ -593,6 +698,7 @@ _FIELD_CLASS_TYPE_TO_OBJ = {
     native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureFieldClass,
     native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayFieldClass,
     native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY: _DynamicArrayFieldClass,
+    native_bt.FIELD_CLASS_TYPE_OPTION: _OptionFieldClass,
     native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantFieldClassWithoutSelector,
     native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: _VariantFieldClassWithUnsignedSelector,
     native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: _VariantFieldClassWithSignedSelector,
This page took 0.027849 seconds and 4 git commands to generate.