bt2: Add remaining trace-ir `*Const` classes and adapt tests
authorFrancis Deslauriers <francis.deslauriers@efficios.com>
Tue, 27 Aug 2019 19:23:15 +0000 (15:23 -0400)
committerFrancis Deslauriers <francis.deslauriers@efficios.com>
Tue, 10 Sep 2019 01:05:12 +0000 (21:05 -0400)
Split Python classes into Const and Non-Const classes to mimic the type
safety offered by the C api. Const classes offer a read-only view of the
data. Non-Const classes subclass their respective Const classes.

Signed-off-by: Francis Deslauriers <francis.deslauriers@efficios.com>
Change-Id: I82b10d48bc9183d9a6bdcc6006ef0a886f9def83
Reviewed-on: https://review.lttng.org/c/babeltrace/+/1924
Tested-by: jenkins <jenkins@lttng.org>
Reviewed-by: Simon Marchi <simon.marchi@efficios.com>
28 files changed:
src/bindings/python/bt2/bt2/__init__.py
src/bindings/python/bt2/bt2/event.py
src/bindings/python/bt2/bt2/event_class.py
src/bindings/python/bt2/bt2/field.py
src/bindings/python/bt2/bt2/field_class.py
src/bindings/python/bt2/bt2/message.py
src/bindings/python/bt2/bt2/message_iterator.py
src/bindings/python/bt2/bt2/packet.py
src/bindings/python/bt2/bt2/stream.py
src/bindings/python/bt2/bt2/stream_class.py
src/bindings/python/bt2/bt2/trace.py
src/bindings/python/bt2/bt2/trace_class.py
tests/bindings/python/bt2/test_clock_class.py
tests/bindings/python/bt2/test_event.py
tests/bindings/python/bt2/test_event_class.py
tests/bindings/python/bt2/test_field.py
tests/bindings/python/bt2/test_field_class.py
tests/bindings/python/bt2/test_graph.py
tests/bindings/python/bt2/test_message.py
tests/bindings/python/bt2/test_message_iterator.py
tests/bindings/python/bt2/test_package.py
tests/bindings/python/bt2/test_packet.py
tests/bindings/python/bt2/test_stream.py
tests/bindings/python/bt2/test_stream_class.py
tests/bindings/python/bt2/test_trace.py
tests/bindings/python/bt2/test_trace_class.py
tests/bindings/python/bt2/test_trace_collection_message_iterator.py
tests/bindings/python/bt2/utils.py

index 3ae303bf599a9699033f34afb2aff08bc3c3f228..b7aa3e838a648951866690045f507168a93b01de 100644 (file)
@@ -57,6 +57,22 @@ from bt2.field import _VariantField
 from bt2.field import _ArrayField
 from bt2.field import _StaticArrayField
 from bt2.field import _DynamicArrayField
+from bt2.field import _BoolFieldConst
+from bt2.field import _BitArrayFieldConst
+from bt2.field import _IntegerFieldConst
+from bt2.field import _UnsignedIntegerFieldConst
+from bt2.field import _SignedIntegerFieldConst
+from bt2.field import _RealFieldConst
+from bt2.field import _EnumerationFieldConst
+from bt2.field import _UnsignedEnumerationFieldConst
+from bt2.field import _SignedEnumerationFieldConst
+from bt2.field import _StringFieldConst
+from bt2.field import _StructureFieldConst
+from bt2.field import _OptionFieldConst
+from bt2.field import _VariantFieldConst
+from bt2.field import _ArrayFieldConst
+from bt2.field import _StaticArrayFieldConst
+from bt2.field import _DynamicArrayFieldConst
 from bt2.field_class import IntegerDisplayBase
 from bt2.field_class import _BoolFieldClass
 from bt2.field_class import _BitArrayFieldClass
@@ -78,6 +94,26 @@ from bt2.field_class import _VariantFieldClassWithSignedSelector
 from bt2.field_class import _ArrayFieldClass
 from bt2.field_class import _StaticArrayFieldClass
 from bt2.field_class import _DynamicArrayFieldClass
+from bt2.field_class import _BoolFieldClassConst
+from bt2.field_class import _BitArrayFieldClassConst
+from bt2.field_class import _IntegerFieldClassConst
+from bt2.field_class import _UnsignedIntegerFieldClassConst
+from bt2.field_class import _SignedIntegerFieldClassConst
+from bt2.field_class import _RealFieldClassConst
+from bt2.field_class import _EnumerationFieldClassConst
+from bt2.field_class import _UnsignedEnumerationFieldClassConst
+from bt2.field_class import _SignedEnumerationFieldClassConst
+from bt2.field_class import _StringFieldClassConst
+from bt2.field_class import _StructureFieldClassConst
+from bt2.field_class import _OptionFieldClassConst
+from bt2.field_class import _VariantFieldClassConst
+from bt2.field_class import _VariantFieldClassWithoutSelectorConst
+from bt2.field_class import _VariantFieldClassWithSelectorConst
+from bt2.field_class import _VariantFieldClassWithUnsignedSelectorConst
+from bt2.field_class import _VariantFieldClassWithSignedSelectorConst
+from bt2.field_class import _ArrayFieldClassConst
+from bt2.field_class import _StaticArrayFieldClassConst
+from bt2.field_class import _DynamicArrayFieldClassConst
 from bt2.field_path import FieldPathScope
 from bt2.field_path import _IndexFieldPathItem
 from bt2.field_path import _CurrentArrayElementFieldPathItem
@@ -100,6 +136,14 @@ from bt2.message import _StreamEndMessage
 from bt2.message import _MessageIteratorInactivityMessage
 from bt2.message import _DiscardedEventsMessage
 from bt2.message import _DiscardedPacketsMessage
+from bt2.message import _EventMessageConst
+from bt2.message import _PacketBeginningMessageConst
+from bt2.message import _PacketEndMessageConst
+from bt2.message import _StreamBeginningMessageConst
+from bt2.message import _StreamEndMessageConst
+from bt2.message import _MessageIteratorInactivityMessageConst
+from bt2.message import _DiscardedEventsMessageConst
+from bt2.message import _DiscardedPacketsMessageConst
 from bt2.message_iterator import _UserMessageIterator
 from bt2.mip import get_greatest_operative_mip_version
 from bt2.mip import get_maximal_mip_version
index afa54947f983cb78e6a74701578ed4627a33e565..08d6ae0949b108ccb9be366740ebb98fa4d6cb94 100644 (file)
@@ -27,12 +27,28 @@ from bt2 import stream as bt2_stream
 from bt2 import field as bt2_field
 
 
-class _Event(object._UniqueObject):
+class _EventConst(object._UniqueObject):
+    _borrow_class_ptr = staticmethod(native_bt.event_borrow_class_const)
+    _borrow_packet_ptr = staticmethod(native_bt.event_borrow_packet_const)
+    _borrow_stream_ptr = staticmethod(native_bt.event_borrow_stream_const)
+    _borrow_common_context_field_ptr = staticmethod(
+        native_bt.event_borrow_common_context_field_const
+    )
+    _borrow_specific_context_field_ptr = staticmethod(
+        native_bt.event_borrow_specific_context_field_const
+    )
+    _borrow_payload_field_ptr = staticmethod(native_bt.event_borrow_payload_field_const)
+    _create_field_from_ptr = staticmethod(bt2_field._create_field_from_const_ptr)
+
+    _event_class_pycls = property(lambda _: bt2_event_class._EventClassConst)
+    _packet_pycls = property(lambda _: bt2_packet._PacketConst)
+    _stream_pycls = property(lambda _: bt2_stream._StreamConst)
+
     @property
     def cls(self):
-        event_class_ptr = native_bt.event_borrow_class(self._ptr)
+        event_class_ptr = self._borrow_class_ptr(self._ptr)
         assert event_class_ptr is not None
-        return bt2_event_class._EventClass._create_from_ptr_and_get_ref(event_class_ptr)
+        return self._event_class_pycls._create_from_ptr_and_get_ref(event_class_ptr)
 
     @property
     def name(self):
@@ -44,49 +60,49 @@ class _Event(object._UniqueObject):
 
     @property
     def packet(self):
-        packet_ptr = native_bt.event_borrow_packet(self._ptr)
+        packet_ptr = self._borrow_packet_ptr(self._ptr)
 
         if packet_ptr is None:
             return
 
-        return bt2_packet._Packet._create_from_ptr_and_get_ref(packet_ptr)
+        return self._packet_pycls._create_from_ptr_and_get_ref(packet_ptr)
 
     @property
     def stream(self):
-        stream_ptr = native_bt.event_borrow_stream(self._ptr)
+        stream_ptr = self._borrow_stream_ptr(self._ptr)
         assert stream_ptr is not None
-        return bt2_stream._Stream._create_from_ptr_and_get_ref(stream_ptr)
+        return self._stream_pycls._create_from_ptr_and_get_ref(stream_ptr)
 
     @property
     def common_context_field(self):
-        field_ptr = native_bt.event_borrow_common_context_field(self._ptr)
+        field_ptr = self._borrow_common_context_field_ptr(self._ptr)
 
         if field_ptr is None:
             return
 
-        return bt2_field._create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
     @property
     def specific_context_field(self):
-        field_ptr = native_bt.event_borrow_specific_context_field(self._ptr)
+        field_ptr = self._borrow_specific_context_field_ptr(self._ptr)
 
         if field_ptr is None:
             return
 
-        return bt2_field._create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
     @property
     def payload_field(self):
-        field_ptr = native_bt.event_borrow_payload_field(self._ptr)
+        field_ptr = self._borrow_payload_field_ptr(self._ptr)
 
         if field_ptr is None:
             return
 
-        return bt2_field._create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
@@ -113,3 +129,21 @@ class _Event(object._UniqueObject):
             return packet_context_field[key]
 
         raise KeyError(key)
+
+
+class _Event(_EventConst):
+    _borrow_class_ptr = staticmethod(native_bt.event_borrow_class)
+    _borrow_packet_ptr = staticmethod(native_bt.event_borrow_packet)
+    _borrow_stream_ptr = staticmethod(native_bt.event_borrow_stream)
+    _borrow_common_context_field_ptr = staticmethod(
+        native_bt.event_borrow_common_context_field
+    )
+    _borrow_specific_context_field_ptr = staticmethod(
+        native_bt.event_borrow_specific_context_field
+    )
+    _borrow_payload_field_ptr = staticmethod(native_bt.event_borrow_payload_field)
+    _create_field_from_ptr = staticmethod(bt2_field._create_field_from_ptr)
+
+    _event_class_pycls = property(lambda _: bt2_event_class._EventClass)
+    _packet_pycls = property(lambda _: bt2_packet._Packet)
+    _stream_pycls = property(lambda _: bt2_stream._Stream)
index afa42d03afee8b4d398fe0fc84db309cc9aff96b..b981d1e7cafbc76b02648dbf970c410fcb8befaf 100644 (file)
@@ -44,40 +44,46 @@ class EventClassLogLevel:
     DEBUG = native_bt.EVENT_CLASS_LOG_LEVEL_DEBUG
 
 
-class _EventClass(object._SharedObject):
+class _EventClassConst(object._SharedObject):
     _get_ref = staticmethod(native_bt.event_class_get_ref)
     _put_ref = staticmethod(native_bt.event_class_put_ref)
+    _borrow_stream_class_ptr = staticmethod(
+        native_bt.event_class_borrow_stream_class_const
+    )
+    _borrow_specific_context_field_class_ptr = staticmethod(
+        native_bt.event_class_borrow_specific_context_field_class_const
+    )
+    _borrow_payload_field_class_ptr = staticmethod(
+        native_bt.event_class_borrow_payload_field_class_const
+    )
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.event_class_borrow_user_attributes_const
+    )
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        bt2_field_class._create_field_class_from_const_ptr_and_get_ref
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
+    _stream_class_pycls = property(lambda s: bt2_stream_class._StreamClassConst)
 
     @property
     def stream_class(self):
-        sc_ptr = native_bt.event_class_borrow_stream_class(self._ptr)
+        sc_ptr = self._borrow_stream_class_ptr(self._ptr)
 
         if sc_ptr is not None:
-            return bt2_stream_class._StreamClass._create_from_ptr_and_get_ref(sc_ptr)
+            return self._stream_class_pycls._create_from_ptr_and_get_ref(sc_ptr)
 
     @property
     def user_attributes(self):
-        ptr = native_bt.event_class_borrow_user_attributes(self._ptr)
+        ptr = self._borrow_user_attributes_ptr(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.event_class_set_user_attributes(self._ptr, value._ptr)
-
-    _user_attributes = property(fset=_user_attributes)
+        return self._create_value_from_ptr_and_get_ref(ptr)
 
     @property
     def name(self):
         return native_bt.event_class_get_name(self._ptr)
 
-    def _name(self, name):
-        utils._check_str(name)
-        return native_bt.event_class_set_name(self._ptr, name)
-
-    _name = property(fset=_name)
-
     @property
     def id(self):
         id = native_bt.event_class_get_id(self._ptr)
@@ -92,6 +98,61 @@ class _EventClass(object._SharedObject):
 
         return _EVENT_CLASS_LOG_LEVEL_TO_OBJ[log_level]
 
+    @property
+    def emf_uri(self):
+        return native_bt.event_class_get_emf_uri(self._ptr)
+
+    @property
+    def specific_context_field_class(self):
+        fc_ptr = self._borrow_specific_context_field_class_ptr(self._ptr)
+
+        if fc_ptr is None:
+            return
+
+        return self._create_field_class_from_ptr_and_get_ref(fc_ptr)
+
+    @property
+    def payload_field_class(self):
+        fc_ptr = self._borrow_payload_field_class_ptr(self._ptr)
+
+        if fc_ptr is None:
+            return
+
+        return self._create_field_class_from_ptr_and_get_ref(fc_ptr)
+
+
+class _EventClass(_EventClassConst):
+    _borrow_stream_class_ptr = staticmethod(native_bt.event_class_borrow_stream_class)
+    _borrow_specific_context_field_class_ptr = staticmethod(
+        native_bt.event_class_borrow_specific_context_field_class
+    )
+    _borrow_payload_field_class_ptr = staticmethod(
+        native_bt.event_class_borrow_payload_field_class
+    )
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.event_class_borrow_user_attributes
+    )
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        bt2_field_class._create_field_class_from_ptr_and_get_ref
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
+    _stream_class_pycls = property(lambda s: bt2_stream_class._StreamClass)
+
+    def _user_attributes(self, user_attributes):
+        value = bt2_value.create_value(user_attributes)
+        utils._check_type(value, bt2_value.MapValue)
+        native_bt.event_class_set_user_attributes(self._ptr, value._ptr)
+
+    _user_attributes = property(fset=_user_attributes)
+
+    def _name(self, name):
+        utils._check_str(name)
+        return native_bt.event_class_set_name(self._ptr, name)
+
+    _name = property(fset=_name)
+
     def _log_level(self, log_level):
         log_levels = (
             EventClassLogLevel.EMERGENCY,
@@ -118,10 +179,6 @@ class _EventClass(object._SharedObject):
 
     _log_level = property(fset=_log_level)
 
-    @property
-    def emf_uri(self):
-        return native_bt.event_class_get_emf_uri(self._ptr)
-
     def _emf_uri(self, emf_uri):
         utils._check_str(emf_uri)
         status = native_bt.event_class_set_emf_uri(self._ptr, emf_uri)
@@ -129,17 +186,6 @@ class _EventClass(object._SharedObject):
 
     _emf_uri = property(fset=_emf_uri)
 
-    @property
-    def specific_context_field_class(self):
-        fc_ptr = native_bt.event_class_borrow_specific_context_field_class_const(
-            self._ptr
-        )
-
-        if fc_ptr is None:
-            return
-
-        return bt2_field_class._create_field_class_from_ptr_and_get_ref(fc_ptr)
-
     def _specific_context_field_class(self, context_field_class):
         if context_field_class is not None:
             utils._check_type(context_field_class, bt2_field_class._StructureFieldClass)
@@ -152,15 +198,6 @@ class _EventClass(object._SharedObject):
 
     _specific_context_field_class = property(fset=_specific_context_field_class)
 
-    @property
-    def payload_field_class(self):
-        fc_ptr = native_bt.event_class_borrow_payload_field_class_const(self._ptr)
-
-        if fc_ptr is None:
-            return
-
-        return bt2_field_class._create_field_class_from_ptr_and_get_ref(fc_ptr)
-
     def _payload_field_class(self, payload_field_class):
         if payload_field_class is not None:
             utils._check_type(payload_field_class, bt2_field_class._StructureFieldClass)
index 56f94f0fb33b8fd4ed33db31059e5849742c8420..4f89d1e43a10ccedcf36c9eff846f9a1f6f09f0e 100644 (file)
@@ -28,15 +28,30 @@ import numbers
 import math
 
 
-def _create_field_from_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
+def _create_field_from_ptr_template(
+    object_map, ptr, owner_ptr, owner_get_ref, owner_put_ref
+):
+
     field_class_ptr = native_bt.field_borrow_class_const(ptr)
     typeid = native_bt.field_class_get_type(field_class_ptr)
-    field = _TYPE_ID_TO_OBJ[typeid]._create_from_ptr_and_get_ref(
+    field = object_map[typeid]._create_from_ptr_and_get_ref(
         ptr, owner_ptr, owner_get_ref, owner_put_ref
     )
     return field
 
 
+def _create_field_from_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
+    return _create_field_from_ptr_template(
+        _TYPE_ID_TO_OBJ, ptr, owner_ptr, owner_get_ref, owner_put_ref
+    )
+
+
+def _create_field_from_const_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
+    return _create_field_from_ptr_template(
+        _TYPE_ID_TO_CONST_OBJ, ptr, owner_ptr, owner_get_ref, owner_put_ref
+    )
+
+
 # Get the "effective" field of `field`.  If `field` is a variant, return
 # the currently selected field.  If `field` is an option, return the
 # content field.  If `field` is of any other type, return `field`
@@ -44,25 +59,31 @@ def _create_field_from_ptr(ptr, owner_ptr, owner_get_ref, owner_put_ref):
 
 
 def _get_leaf_field(field):
-    if isinstance(field, _VariantField):
+    if isinstance(field, _VariantFieldConst):
         return _get_leaf_field(field.selected_option)
 
-    if isinstance(field, _OptionField):
+    if isinstance(field, _OptionFieldConst):
         return _get_leaf_field(field.field)
 
     return field
 
 
-class _Field(object._UniqueObject):
+class _FieldConst(object._UniqueObject):
+    _create_field_from_ptr = staticmethod(_create_field_from_const_ptr)
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        bt2_field_class._create_field_class_from_const_ptr_and_get_ref
+    )
+    _borrow_class_ptr = staticmethod(native_bt.field_borrow_class_const)
+
     def __eq__(self, other):
         other = _get_leaf_field(other)
         return self._spec_eq(other)
 
     @property
     def cls(self):
-        field_class_ptr = native_bt.field_borrow_class_const(self._ptr)
+        field_class_ptr = self._borrow_class_ptr(self._ptr)
         assert field_class_ptr is not None
-        return bt2_field_class._create_field_class_from_ptr_and_get_ref(field_class_ptr)
+        return self._create_field_class_from_ptr_and_get_ref(field_class_ptr)
 
     def _repr(self):
         raise NotImplementedError
@@ -71,18 +92,21 @@ class _Field(object._UniqueObject):
         return self._repr()
 
 
-class _BitArrayField(_Field):
-    _NAME = 'Bit array'
+class _Field(_FieldConst):
+    _create_field_from_ptr = staticmethod(_create_field_from_ptr)
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        bt2_field_class._create_field_class_from_ptr_and_get_ref
+    )
+    _borrow_class_ptr = staticmethod(native_bt.field_borrow_class)
+
+
+class _BitArrayFieldConst(_FieldConst):
+    _NAME = 'Const bit array'
 
     @property
     def value_as_integer(self):
         return native_bt.field_bit_array_get_value_as_integer(self._ptr)
 
-    @value_as_integer.setter
-    def value_as_integer(self, value):
-        utils._check_uint64(value)
-        native_bt.field_bit_array_set_value_as_integer(self._ptr, value)
-
     def _spec_eq(self, other):
         if type(other) is not type(self):
             return False
@@ -99,11 +123,23 @@ class _BitArrayField(_Field):
         return self.cls.length
 
 
+class _BitArrayField(_BitArrayFieldConst, _Field):
+    _NAME = 'Bit array'
+
+    def _value_as_integer(self, value):
+        utils._check_uint64(value)
+        native_bt.field_bit_array_set_value_as_integer(self._ptr, value)
+
+    value_as_integer = property(
+        fget=_BitArrayFieldConst.value_as_integer.fget, fset=_value_as_integer
+    )
+
+
 @functools.total_ordering
-class _NumericField(_Field):
+class _NumericFieldConst(_FieldConst):
     @staticmethod
     def _extract_value(other):
-        if isinstance(other, _BoolField) or isinstance(other, bool):
+        if isinstance(other, _BoolFieldConst) or isinstance(other, bool):
             return bool(other)
 
         if isinstance(other, numbers.Integral):
@@ -205,7 +241,11 @@ class _NumericField(_Field):
         return self._extract_value(base) ** self._value
 
 
-class _IntegralField(_NumericField, numbers.Integral):
+class _NumericField(_NumericFieldConst, _Field):
+    pass
+
+
+class _IntegralFieldConst(_NumericFieldConst, numbers.Integral):
     def __lshift__(self, other):
         return self._value << self._extract_value(other)
 
@@ -240,19 +280,24 @@ class _IntegralField(_NumericField, numbers.Integral):
         return ~self._value
 
 
-class _BoolField(_IntegralField, _Field):
-    _NAME = 'Boolean'
+class _IntegralField(_IntegralFieldConst, _NumericField):
+    pass
+
+
+class _BoolFieldConst(_IntegralFieldConst, _FieldConst):
+    _NAME = 'Const boolean'
 
     def __bool__(self):
         return self._value
 
-    def _value_to_bool(self, value):
-        if isinstance(value, _BoolField):
+    @classmethod
+    def _value_to_bool(cls, value):
+        if isinstance(value, _BoolFieldConst):
             value = value._value
 
         if not isinstance(value, bool):
             raise TypeError(
-                "'{}' object is not a 'bool' or '_BoolField' object".format(
+                "'{}' object is not a 'bool', '_BoolFieldConst', or '_BoolField' object".format(
                     value.__class__
                 )
             )
@@ -263,6 +308,10 @@ class _BoolField(_IntegralField, _Field):
     def _value(self):
         return bool(native_bt.field_bool_get_value(self._ptr))
 
+
+class _BoolField(_BoolFieldConst, _IntegralField, _Field):
+    _NAME = 'Boolean'
+
     def _set_value(self, value):
         value = self._value_to_bool(value)
         native_bt.field_bool_set_value(self._ptr, value)
@@ -270,14 +319,19 @@ class _BoolField(_IntegralField, _Field):
     value = property(fset=_set_value)
 
 
-class _IntegerField(_IntegralField, _Field):
+class _IntegerFieldConst(_IntegralFieldConst, _FieldConst):
     pass
 
 
-class _UnsignedIntegerField(_IntegerField, _Field):
-    _NAME = 'Unsigned integer'
+class _IntegerField(_IntegerFieldConst, _IntegralField, _Field):
+    pass
+
+
+class _UnsignedIntegerFieldConst(_IntegerFieldConst, _FieldConst):
+    _NAME = 'Const unsigned integer'
 
-    def _value_to_int(self, value):
+    @classmethod
+    def _value_to_int(cls, value):
         if not isinstance(value, numbers.Integral):
             raise TypeError('expecting an integral number object')
 
@@ -290,6 +344,10 @@ class _UnsignedIntegerField(_IntegerField, _Field):
     def _value(self):
         return native_bt.field_integer_unsigned_get_value(self._ptr)
 
+
+class _UnsignedIntegerField(_UnsignedIntegerFieldConst, _IntegerField, _Field):
+    _NAME = 'Unsigned integer'
+
     def _set_value(self, value):
         value = self._value_to_int(value)
         native_bt.field_integer_unsigned_set_value(self._ptr, value)
@@ -297,10 +355,11 @@ class _UnsignedIntegerField(_IntegerField, _Field):
     value = property(fset=_set_value)
 
 
-class _SignedIntegerField(_IntegerField, _Field):
-    _NAME = 'Signed integer'
+class _SignedIntegerFieldConst(_IntegerFieldConst, _FieldConst):
+    _NAME = 'Const signed integer'
 
-    def _value_to_int(self, value):
+    @classmethod
+    def _value_to_int(cls, value):
         if not isinstance(value, numbers.Integral):
             raise TypeError('expecting an integral number object')
 
@@ -313,6 +372,10 @@ class _SignedIntegerField(_IntegerField, _Field):
     def _value(self):
         return native_bt.field_integer_signed_get_value(self._ptr)
 
+
+class _SignedIntegerField(_SignedIntegerFieldConst, _IntegerField, _Field):
+    _NAME = 'Signed integer'
+
     def _set_value(self, value):
         value = self._value_to_int(value)
         native_bt.field_integer_signed_set_value(self._ptr, value)
@@ -320,10 +383,11 @@ class _SignedIntegerField(_IntegerField, _Field):
     value = property(fset=_set_value)
 
 
-class _RealField(_NumericField, numbers.Real):
-    _NAME = 'Real'
+class _RealFieldConst(_NumericFieldConst, numbers.Real):
+    _NAME = 'Const real'
 
-    def _value_to_float(self, value):
+    @classmethod
+    def _value_to_float(cls, value):
         if not isinstance(value, numbers.Real):
             raise TypeError("expecting a real number object")
 
@@ -333,6 +397,10 @@ class _RealField(_NumericField, numbers.Real):
     def _value(self):
         return native_bt.field_real_get_value(self._ptr)
 
+
+class _RealField(_RealFieldConst, _NumericField):
+    _NAME = 'Real'
+
     def _set_value(self, value):
         value = self._value_to_float(value)
         native_bt.field_real_set_value(self._ptr, value)
@@ -340,7 +408,7 @@ class _RealField(_NumericField, numbers.Real):
     value = property(fset=_set_value)
 
 
-class _EnumerationField(_IntegerField):
+class _EnumerationFieldConst(_IntegerFieldConst):
     def _repr(self):
         return '{} ({})'.format(self._value, ', '.join(self.labels))
 
@@ -353,26 +421,45 @@ class _EnumerationField(_IntegerField):
         return labels
 
 
-class _UnsignedEnumerationField(_EnumerationField, _UnsignedIntegerField):
-    _NAME = 'Unsigned Enumeration'
+class _EnumerationField(_EnumerationFieldConst, _IntegerField):
+    pass
+
+
+class _UnsignedEnumerationFieldConst(
+    _EnumerationFieldConst, _UnsignedIntegerFieldConst
+):
+    _NAME = 'Const unsigned Enumeration'
     _get_mapping_labels = staticmethod(
         native_bt.field_enumeration_unsigned_get_mapping_labels
     )
 
 
-class _SignedEnumerationField(_EnumerationField, _SignedIntegerField):
-    _NAME = 'Signed Enumeration'
+class _UnsignedEnumerationField(
+    _UnsignedEnumerationFieldConst, _EnumerationField, _UnsignedIntegerField
+):
+    _NAME = 'Unsigned enumeration'
+
+
+class _SignedEnumerationFieldConst(_EnumerationFieldConst, _SignedIntegerFieldConst):
+    _NAME = 'Const signed Enumeration'
     _get_mapping_labels = staticmethod(
         native_bt.field_enumeration_signed_get_mapping_labels
     )
 
 
+class _SignedEnumerationField(
+    _SignedEnumerationFieldConst, _EnumerationField, _SignedIntegerField
+):
+    _NAME = 'Signed enumeration'
+
+
 @functools.total_ordering
-class _StringField(_Field):
-    _NAME = 'String'
+class _StringFieldConst(_FieldConst):
+    _NAME = 'Const string'
 
-    def _value_to_str(self, value):
-        if isinstance(value, self.__class__):
+    @classmethod
+    def _value_to_str(cls, value):
+        if isinstance(value, _StringFieldConst):
             value = value._value
 
         if not isinstance(value, str):
@@ -384,12 +471,6 @@ class _StringField(_Field):
     def _value(self):
         return native_bt.field_string_get_value(self._ptr)
 
-    def _set_value(self, value):
-        value = self._value_to_str(value)
-        native_bt.field_string_set_value(self._ptr, value)
-
-    value = property(fset=_set_value)
-
     def _spec_eq(self, other):
         try:
             return self._value == self._value_to_str(other)
@@ -414,6 +495,16 @@ class _StringField(_Field):
     def __len__(self):
         return native_bt.field_string_get_length(self._ptr)
 
+
+class _StringField(_StringFieldConst, _Field):
+    _NAME = 'String'
+
+    def _set_value(self, value):
+        value = self._value_to_str(value)
+        native_bt.field_string_set_value(self._ptr, value)
+
+    value = property(fset=_set_value)
+
     def __iadd__(self, value):
         value = self._value_to_str(value)
         status = native_bt.field_string_append(self._ptr, value)
@@ -423,10 +514,13 @@ class _StringField(_Field):
         return self
 
 
-class _ContainerField(_Field):
+class _ContainerFieldConst(_FieldConst):
     def __bool__(self):
         return len(self) != 0
 
+    def _count(self):
+        return len(self.cls)
+
     def __len__(self):
         count = self._count()
         assert count >= 0
@@ -435,20 +529,27 @@ class _ContainerField(_Field):
     def __delitem__(self, index):
         raise NotImplementedError
 
+    def __setitem__(self, index, value):
+        raise TypeError(
+            '\'{}\' object does not support item assignment'.format(self.__class__)
+        )
 
-class _StructureField(_ContainerField, collections.abc.MutableMapping):
-    _NAME = 'Structure'
 
-    def _count(self):
-        return len(self.cls)
+class _ContainerField(_ContainerFieldConst, _Field):
+    pass
 
-    def __setitem__(self, key, value):
-        # raises if key is somehow invalid
-        field = self[key]
 
-        # the field's property does the appropriate conversion or raises
-        # the appropriate exception
-        field.value = value
+class _StructureFieldConst(_ContainerFieldConst, collections.abc.Mapping):
+    _NAME = 'Const structure'
+    _borrow_member_field_ptr_by_index = staticmethod(
+        native_bt.field_structure_borrow_member_field_by_index_const
+    )
+    _borrow_member_field_ptr_by_name = staticmethod(
+        native_bt.field_structure_borrow_member_field_by_name_const
+    )
+
+    def _count(self):
+        return len(self.cls)
 
     def __iter__(self):
         # same name iterator
@@ -471,29 +572,18 @@ class _StructureField(_ContainerField, collections.abc.MutableMapping):
 
         return True
 
-    def _set_value(self, values):
-        try:
-            for key, value in values.items():
-                self[key].value = value
-        except Exception:
-            raise
-
-    value = property(fset=_set_value)
-
     def _repr(self):
         items = ['{}: {}'.format(repr(k), repr(v)) for k, v in self.items()]
         return '{{{}}}'.format(', '.join(items))
 
     def __getitem__(self, key):
         utils._check_str(key)
-        field_ptr = native_bt.field_structure_borrow_member_field_by_name(
-            self._ptr, key
-        )
+        field_ptr = self._borrow_member_field_ptr_by_name(self._ptr, key)
 
         if field_ptr is None:
             raise KeyError(key)
 
-        return _create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
@@ -502,27 +592,54 @@ class _StructureField(_ContainerField, collections.abc.MutableMapping):
 
         if index >= len(self):
             raise IndexError
-
-        field_ptr = native_bt.field_structure_borrow_member_field_by_index(
-            self._ptr, index
-        )
+        field_ptr = self._borrow_member_field_ptr_by_index(self._ptr, index)
         assert field_ptr is not None
-        return _create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
 
-class _OptionField(_Field):
-    _NAME = 'Option'
+class _StructureField(
+    _StructureFieldConst, _ContainerField, collections.abc.MutableMapping
+):
+    _NAME = 'Structure'
+    _borrow_member_field_ptr_by_index = staticmethod(
+        native_bt.field_structure_borrow_member_field_by_index
+    )
+    _borrow_member_field_ptr_by_name = staticmethod(
+        native_bt.field_structure_borrow_member_field_by_name
+    )
+
+    def __setitem__(self, key, value):
+        # raises if key is somehow invalid
+        field = self[key]
+
+        # the field's property does the appropriate conversion or raises
+        # the appropriate exception
+        field.value = value
+
+    def _set_value(self, values):
+        try:
+            for key, value in values.items():
+                self[key].value = value
+        except Exception:
+            raise
+
+    value = property(fset=_set_value)
+
+
+class _OptionFieldConst(_FieldConst):
+    _NAME = 'Const option'
+    _borrow_field_ptr = staticmethod(native_bt.field_option_borrow_field_const)
 
     @property
     def field(self):
-        field_ptr = native_bt.field_option_borrow_field_const(self._ptr)
+        field_ptr = self._borrow_field_ptr(self._ptr)
 
         if field_ptr is None:
             return
 
-        return _create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
@@ -530,11 +647,6 @@ class _OptionField(_Field):
     def has_field(self):
         return self.field is not None
 
-    @has_field.setter
-    def has_field(self, value):
-        utils._check_bool(value)
-        native_bt.field_option_set_has_field(self._ptr, value)
-
     def _spec_eq(self, other):
         return _get_leaf_field(self) == other
 
@@ -547,6 +659,17 @@ class _OptionField(_Field):
     def _repr(self):
         return repr(self.field)
 
+
+class _OptionField(_OptionFieldConst, _Field):
+    _NAME = 'Option'
+    _borrow_field_ptr = staticmethod(native_bt.field_option_borrow_field)
+
+    def _has_field(self, value):
+        utils._check_bool(value)
+        native_bt.field_option_set_has_field(self._ptr, value)
+
+    has_field = property(fget=_OptionFieldConst.has_field.fget, fset=_has_field)
+
     def _set_value(self, value):
         self.has_field = True
         field = self.field
@@ -556,8 +679,11 @@ class _OptionField(_Field):
     value = property(fset=_set_value)
 
 
-class _VariantField(_ContainerField, _Field):
-    _NAME = 'Variant'
+class _VariantFieldConst(_ContainerFieldConst, _FieldConst):
+    _NAME = 'Const variant'
+    _borrow_selected_option_field_ptr = staticmethod(
+        native_bt.field_variant_borrow_selected_option_field_const
+    )
 
     def _count(self):
         return len(self.cls)
@@ -566,21 +692,14 @@ class _VariantField(_ContainerField, _Field):
     def selected_option_index(self):
         return native_bt.field_variant_get_selected_option_field_index(self._ptr)
 
-    @selected_option_index.setter
-    def selected_option_index(self, index):
-        if index < 0 or index >= len(self):
-            raise IndexError('{} field object index is out of range'.format(self._NAME))
-
-        native_bt.field_variant_select_option_field_by_index(self._ptr, index)
-
     @property
     def selected_option(self):
         # TODO: Is there a way to check if the variant field has a selected_option,
         # so we can raise an exception instead of hitting a pre-condition check?
         # If there is something, that check should be added to selected_option_index too.
-        field_ptr = native_bt.field_variant_borrow_selected_option_field(self._ptr)
+        field_ptr = self._borrow_selected_option_field_ptr(self._ptr)
 
-        return _create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
@@ -596,13 +715,34 @@ class _VariantField(_ContainerField, _Field):
     def _repr(self):
         return repr(self.selected_option)
 
+
+class _VariantField(_VariantFieldConst, _ContainerField, _Field):
+    _NAME = 'Variant'
+    _borrow_selected_option_field_ptr = staticmethod(
+        native_bt.field_variant_borrow_selected_option_field
+    )
+
+    def _selected_option_index(self, index):
+        if index < 0 or index >= len(self):
+            raise IndexError('{} field object index is out of range'.format(self._NAME))
+
+        native_bt.field_variant_select_option_field_by_index(self._ptr, index)
+
+    selected_option_index = property(
+        fget=_VariantFieldConst.selected_option_index.fget, fset=_selected_option_index
+    )
+
     def _set_value(self, value):
         self.selected_option.value = value
 
     value = property(fset=_set_value)
 
 
-class _ArrayField(_ContainerField, _Field, collections.abc.MutableSequence):
+class _ArrayFieldConst(_ContainerFieldConst, _FieldConst, collections.abc.Sequence):
+    _borrow_element_field_ptr_by_index = staticmethod(
+        native_bt.field_array_borrow_element_field_by_index_const
+    )
+
     def _get_length(self):
         return native_bt.field_array_get_length(self._ptr)
 
@@ -621,25 +761,12 @@ class _ArrayField(_ContainerField, _Field, collections.abc.MutableSequence):
         if index < 0 or index >= len(self):
             raise IndexError('{} field object index is out of range'.format(self._NAME))
 
-        field_ptr = native_bt.field_array_borrow_element_field_by_index(
-            self._ptr, index
-        )
+        field_ptr = self._borrow_element_field_ptr_by_index(self._ptr, index)
         assert field_ptr
-        return _create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._owner_ptr, self._owner_get_ref, self._owner_put_ref
         )
 
-    def __setitem__(self, index, value):
-        # raises if index is somehow invalid
-        field = self[index]
-
-        if not isinstance(field, (_NumericField, _StringField)):
-            raise TypeError('can only set the value of a number or string field')
-
-        # the field's property does the appropriate conversion or raises
-        # the appropriate exception
-        field.value = value
-
     def insert(self, index, value):
         raise NotImplementedError
 
@@ -661,12 +788,35 @@ class _ArrayField(_ContainerField, _Field, collections.abc.MutableSequence):
         return '[{}]'.format(', '.join([repr(v) for v in self]))
 
 
-class _StaticArrayField(_ArrayField, _Field):
-    _NAME = 'Static array'
+class _ArrayField(
+    _ArrayFieldConst, _ContainerField, _Field, collections.abc.MutableSequence
+):
+    _borrow_element_field_ptr_by_index = staticmethod(
+        native_bt.field_array_borrow_element_field_by_index
+    )
+
+    def __setitem__(self, index, value):
+        # raises if index is somehow invalid
+        field = self[index]
+
+        if not isinstance(field, (_NumericField, _StringField)):
+            raise TypeError('can only set the value of a number or string field')
+
+        # the field's property does the appropriate conversion or raises
+        # the appropriate exception
+        field.value = value
+
+
+class _StaticArrayFieldConst(_ArrayFieldConst, _FieldConst):
+    _NAME = 'Const static array'
 
     def _count(self):
         return native_bt.field_array_get_length(self._ptr)
 
+
+class _StaticArrayField(_StaticArrayFieldConst, _ArrayField, _Field):
+    _NAME = 'Static array'
+
     def _set_value(self, values):
         if len(self) != len(values):
             raise ValueError('expected length of value and array field to match')
@@ -678,12 +828,16 @@ class _StaticArrayField(_ArrayField, _Field):
     value = property(fset=_set_value)
 
 
-class _DynamicArrayField(_ArrayField, _Field):
-    _NAME = 'Dynamic array'
+class _DynamicArrayFieldConst(_ArrayFieldConst, _FieldConst):
+    _NAME = 'Const dynamic array'
 
     def _count(self):
         return self.length
 
+
+class _DynamicArrayField(_DynamicArrayFieldConst, _ArrayField, _Field):
+    _NAME = 'Dynamic array'
+
     def _set_length(self, length):
         utils._check_uint64(length)
         status = native_bt.field_array_dynamic_set_length(self._ptr, length)
@@ -702,6 +856,24 @@ class _DynamicArrayField(_ArrayField, _Field):
     value = property(fset=_set_value)
 
 
+_TYPE_ID_TO_CONST_OBJ = {
+    native_bt.FIELD_CLASS_TYPE_BOOL: _BoolFieldConst,
+    native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayFieldConst,
+    native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerFieldConst,
+    native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerFieldConst,
+    native_bt.FIELD_CLASS_TYPE_REAL: _RealFieldConst,
+    native_bt.FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: _UnsignedEnumerationFieldConst,
+    native_bt.FIELD_CLASS_TYPE_SIGNED_ENUMERATION: _SignedEnumerationFieldConst,
+    native_bt.FIELD_CLASS_TYPE_STRING: _StringFieldConst,
+    native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureFieldConst,
+    native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayFieldConst,
+    native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY: _DynamicArrayFieldConst,
+    native_bt.FIELD_CLASS_TYPE_OPTION: _OptionFieldConst,
+    native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantFieldConst,
+    native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: _VariantFieldConst,
+    native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: _VariantFieldConst,
+}
+
 _TYPE_ID_TO_OBJ = {
     native_bt.FIELD_CLASS_TYPE_BOOL: _BoolField,
     native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayField,
index d467bcc4129fa8a986fb3dc47054e3fd25e1f0ef..03e6e4e3569c405dea401410da5e78f1a482a9fa 100644 (file)
@@ -28,9 +28,21 @@ from bt2 import value as bt2_value
 import bt2
 
 
-def _create_field_class_from_ptr_and_get_ref(ptr):
+def _create_field_class_from_ptr_and_get_ref_template(type_map, ptr):
     typeid = native_bt.field_class_get_type(ptr)
-    return _FIELD_CLASS_TYPE_TO_OBJ[typeid]._create_from_ptr_and_get_ref(ptr)
+    return type_map[typeid]._create_from_ptr_and_get_ref(ptr)
+
+
+def _create_field_class_from_ptr_and_get_ref(ptr):
+    return _create_field_class_from_ptr_and_get_ref_template(
+        _FIELD_CLASS_TYPE_TO_OBJ, ptr
+    )
+
+
+def _create_field_class_from_const_ptr_and_get_ref(ptr):
+    return _create_field_class_from_ptr_and_get_ref_template(
+        _FIELD_CLASS_TYPE_TO_CONST_OBJ, ptr
+    )
 
 
 class IntegerDisplayBase:
@@ -40,9 +52,15 @@ class IntegerDisplayBase:
     HEXADECIMAL = native_bt.FIELD_CLASS_INTEGER_PREFERRED_DISPLAY_BASE_HEXADECIMAL
 
 
-class _FieldClass(object._SharedObject):
+class _FieldClassConst(object._SharedObject):
     _get_ref = staticmethod(native_bt.field_class_get_ref)
     _put_ref = staticmethod(native_bt.field_class_put_ref)
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.field_class_borrow_user_attributes_const
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
 
     def _check_create_status(self, ptr):
         if ptr is None:
@@ -52,9 +70,18 @@ class _FieldClass(object._SharedObject):
 
     @property
     def user_attributes(self):
-        ptr = native_bt.field_class_borrow_user_attributes(self._ptr)
+        ptr = self._borrow_user_attributes_ptr(self._ptr)
         assert ptr is not None
-        return bt2_value._create_from_ptr_and_get_ref(ptr)
+        return self._create_value_from_ptr_and_get_ref(ptr)
+
+
+class _FieldClass(_FieldClassConst):
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.field_class_borrow_user_attributes
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
 
     def _user_attributes(self, user_attributes):
         value = bt2_value.create_value(user_attributes)
@@ -64,12 +91,16 @@ class _FieldClass(object._SharedObject):
     _user_attributes = property(fset=_user_attributes)
 
 
-class _BoolFieldClass(_FieldClass):
+class _BoolFieldClassConst(_FieldClassConst):
+    _NAME = 'Const Boolean'
+
+
+class _BoolFieldClass(_BoolFieldClassConst, _FieldClass):
     _NAME = 'Boolean'
 
 
-class _BitArrayFieldClass(_FieldClass):
-    _NAME = 'Bit array'
+class _BitArrayFieldClassConst(_FieldClassConst):
+    _NAME = 'Const Bit array'
 
     @property
     def length(self):
@@ -78,13 +109,25 @@ class _BitArrayFieldClass(_FieldClass):
         return length
 
 
-class _IntegerFieldClass(_FieldClass):
+class _BitArrayFieldClass(_BitArrayFieldClassConst, _FieldClass):
+    _NAME = 'Bit array'
+
+
+class _IntegerFieldClassConst(_FieldClassConst):
     @property
     def field_value_range(self):
         size = native_bt.field_class_integer_get_field_value_range(self._ptr)
         assert size >= 1
         return size
 
+    @property
+    def preferred_display_base(self):
+        base = native_bt.field_class_integer_get_preferred_display_base(self._ptr)
+        assert base >= 0
+        return base
+
+
+class _IntegerFieldClass(_FieldClass, _IntegerFieldClassConst):
     def _field_value_range(self, size):
         if size < 1 or size > 64:
             raise ValueError("Value is outside valid range [1, 64] ({})".format(size))
@@ -92,12 +135,6 @@ class _IntegerFieldClass(_FieldClass):
 
     _field_value_range = property(fset=_field_value_range)
 
-    @property
-    def preferred_display_base(self):
-        base = native_bt.field_class_integer_get_preferred_display_base(self._ptr)
-        assert base >= 0
-        return base
-
     def _preferred_display_base(self, base):
         utils._check_uint64(base)
 
@@ -114,21 +151,37 @@ class _IntegerFieldClass(_FieldClass):
     _preferred_display_base = property(fset=_preferred_display_base)
 
 
-class _UnsignedIntegerFieldClass(_IntegerFieldClass):
+class _UnsignedIntegerFieldClassConst(_IntegerFieldClassConst, _FieldClassConst):
+    _NAME = 'Const unsigned integer'
+
+
+class _UnsignedIntegerFieldClass(
+    _UnsignedIntegerFieldClassConst, _IntegerFieldClass, _FieldClass
+):
     _NAME = 'Unsigned integer'
 
 
-class _SignedIntegerFieldClass(_IntegerFieldClass):
+class _SignedIntegerFieldClassConst(_IntegerFieldClassConst, _FieldClassConst):
+    _NAME = 'Const signed integer'
+
+
+class _SignedIntegerFieldClass(
+    _SignedIntegerFieldClassConst, _IntegerFieldClass, _FieldClass
+):
     _NAME = 'Signed integer'
 
 
-class _RealFieldClass(_FieldClass):
-    _NAME = 'Real'
+class _RealFieldClassConst(_FieldClassConst):
+    _NAME = 'Const real'
 
     @property
     def is_single_precision(self):
         return native_bt.field_class_real_is_single_precision(self._ptr)
 
+
+class _RealFieldClass(_FieldClass, _RealFieldClassConst):
+    _NAME = 'Real'
+
     def _is_single_precision(self, is_single_precision):
         utils._check_bool(is_single_precision)
         native_bt.field_class_real_set_is_single_precision(
@@ -160,7 +213,7 @@ class _EnumerationFieldClassMapping:
         return self._ranges
 
 
-class _UnsignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping):
+class _UnsignedEnumerationFieldClassMappingConst(_EnumerationFieldClassMapping):
     _ranges_type = bt2_integer_range_set.UnsignedIntegerRangeSet
     _as_enumeration_field_class_mapping_ptr = staticmethod(
         native_bt.field_class_enumeration_unsigned_mapping_as_mapping_const
@@ -170,7 +223,7 @@ class _UnsignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping):
     )
 
 
-class _SignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping):
+class _SignedEnumerationFieldClassMappingConst(_EnumerationFieldClassMapping):
     _ranges_type = bt2_integer_range_set.SignedIntegerRangeSet
     _as_enumeration_field_class_mapping_ptr = staticmethod(
         native_bt.field_class_enumeration_signed_mapping_as_mapping_const
@@ -180,25 +233,15 @@ class _SignedEnumerationFieldClassMapping(_EnumerationFieldClassMapping):
     )
 
 
-class _EnumerationFieldClass(_IntegerFieldClass, collections.abc.Mapping):
+class _EnumerationFieldClassConst(_IntegerFieldClassConst, collections.abc.Mapping):
     def __len__(self):
         count = native_bt.field_class_enumeration_get_mapping_count(self._ptr)
         assert count >= 0
         return count
 
-    def add_mapping(self, label, ranges):
-        utils._check_str(label)
-        utils._check_type(ranges, self._range_set_type)
-
-        if label in self:
-            raise ValueError("duplicate mapping label '{}'".format(label))
-
-        status = self._add_mapping(self._ptr, label, ranges._ptr)
-        utils._handle_func_status(
-            status, 'cannot add mapping to enumeration field class object'
-        )
-
     def mappings_for_value(self, value):
+        self._check_int_type(value)
+
         status, labels = self._get_mapping_labels_for_value(self._ptr, value)
         utils._handle_func_status(
             status, 'cannot get mapping labels for value {}'.format(value)
@@ -207,17 +250,31 @@ class _EnumerationFieldClass(_IntegerFieldClass, collections.abc.Mapping):
 
     def __iter__(self):
         for idx in range(len(self)):
-            mapping = self._get_mapping_by_index(self._ptr, idx)
-            yield mapping.label
+            mapping_ptr = self._borrow_mapping_ptr_by_index(self._ptr, idx)
+            yield self._mapping_pycls(mapping_ptr).label
 
     def __getitem__(self, label):
         utils._check_str(label)
-        mapping = self._get_mapping_by_label(self._ptr, label)
+        mapping_ptr = self._borrow_mapping_ptr_by_label(self._ptr, label)
 
-        if mapping is None:
+        if mapping_ptr is None:
             raise KeyError(label)
 
-        return mapping
+        return self._mapping_pycls(mapping_ptr)
+
+
+class _EnumerationFieldClass(_EnumerationFieldClassConst, _IntegerFieldClass):
+    def add_mapping(self, label, ranges):
+        utils._check_str(label)
+        utils._check_type(ranges, self._range_set_type)
+
+        if label in self:
+            raise ValueError("duplicate mapping label '{}'".format(label))
+
+        status = self._add_mapping(self._ptr, label, ranges._ptr)
+        utils._handle_func_status(
+            status, 'cannot add mapping to enumeration field class object'
+        )
 
     def __iadd__(self, mappings):
         for label, ranges in mappings:
@@ -226,77 +283,80 @@ class _EnumerationFieldClass(_IntegerFieldClass, collections.abc.Mapping):
         return self
 
 
-class _UnsignedEnumerationFieldClass(
-    _EnumerationFieldClass, _UnsignedIntegerFieldClass
+class _UnsignedEnumerationFieldClassConst(
+    _EnumerationFieldClassConst, _UnsignedIntegerFieldClassConst
 ):
-    _NAME = 'Unsigned enumeration'
+    _NAME = 'Const nsigned enumeration'
     _range_set_type = bt2_integer_range_set.UnsignedIntegerRangeSet
-    _add_mapping = staticmethod(native_bt.field_class_enumeration_unsigned_add_mapping)
-
-    @staticmethod
-    def _get_mapping_by_index(enum_ptr, index):
-        mapping_ptr = native_bt.field_class_enumeration_unsigned_borrow_mapping_by_index_const(
-            enum_ptr, index
-        )
-        assert mapping_ptr is not None
-        return _UnsignedEnumerationFieldClassMapping(mapping_ptr)
+    _borrow_mapping_ptr_by_label = staticmethod(
+        native_bt.field_class_enumeration_unsigned_borrow_mapping_by_label_const
+    )
+    _borrow_mapping_ptr_by_index = staticmethod(
+        native_bt.field_class_enumeration_unsigned_borrow_mapping_by_index_const
+    )
+    _mapping_pycls = property(lambda _: _UnsignedEnumerationFieldClassMappingConst)
+    _get_mapping_labels_for_value = staticmethod(
+        native_bt.field_class_enumeration_unsigned_get_mapping_labels_for_value
+    )
+    _check_int_type = staticmethod(utils._check_uint64)
 
-    @staticmethod
-    def _get_mapping_by_label(enum_ptr, label):
-        mapping_ptr = native_bt.field_class_enumeration_unsigned_borrow_mapping_by_label_const(
-            enum_ptr, label
-        )
 
-        if mapping_ptr is None:
-            return
+class _UnsignedEnumerationFieldClass(
+    _UnsignedEnumerationFieldClassConst,
+    _EnumerationFieldClass,
+    _UnsignedIntegerFieldClass,
+):
+    _NAME = 'Unsigned enumeration'
+    _add_mapping = staticmethod(native_bt.field_class_enumeration_unsigned_add_mapping)
 
-        return _UnsignedEnumerationFieldClassMapping(mapping_ptr)
 
-    @staticmethod
-    def _get_mapping_labels_for_value(enum_ptr, value):
-        utils._check_uint64(value)
-        return native_bt.field_class_enumeration_unsigned_get_mapping_labels_for_value(
-            enum_ptr, value
-        )
+class _SignedEnumerationFieldClassConst(
+    _EnumerationFieldClassConst, _SignedIntegerFieldClassConst
+):
+    _NAME = 'Const signed enumeration'
+    _range_set_type = bt2_integer_range_set.SignedIntegerRangeSet
+    _borrow_mapping_ptr_by_label = staticmethod(
+        native_bt.field_class_enumeration_signed_borrow_mapping_by_label_const
+    )
+    _borrow_mapping_ptr_by_index = staticmethod(
+        native_bt.field_class_enumeration_signed_borrow_mapping_by_index_const
+    )
+    _mapping_pycls = property(lambda _: _SignedEnumerationFieldClassMappingConst)
+    _get_mapping_labels_for_value = staticmethod(
+        native_bt.field_class_enumeration_signed_get_mapping_labels_for_value
+    )
+    _check_int_type = staticmethod(utils._check_int64)
 
 
-class _SignedEnumerationFieldClass(_EnumerationFieldClass, _SignedIntegerFieldClass):
+class _SignedEnumerationFieldClass(
+    _SignedEnumerationFieldClassConst, _EnumerationFieldClass, _SignedIntegerFieldClass
+):
     _NAME = 'Signed enumeration'
-    _range_set_type = bt2_integer_range_set.SignedIntegerRangeSet
     _add_mapping = staticmethod(native_bt.field_class_enumeration_signed_add_mapping)
 
-    @staticmethod
-    def _get_mapping_by_index(enum_ptr, index):
-        mapping_ptr = native_bt.field_class_enumeration_signed_borrow_mapping_by_index_const(
-            enum_ptr, index
-        )
-        assert mapping_ptr is not None
-        return _SignedEnumerationFieldClassMapping(mapping_ptr)
-
-    @staticmethod
-    def _get_mapping_by_label(enum_ptr, label):
-        mapping_ptr = native_bt.field_class_enumeration_signed_borrow_mapping_by_label_const(
-            enum_ptr, label
-        )
-
-        if mapping_ptr is None:
-            return
 
-        return _SignedEnumerationFieldClassMapping(mapping_ptr)
-
-    @staticmethod
-    def _get_mapping_labels_for_value(enum_ptr, value):
-        utils._check_int64(value)
-        return native_bt.field_class_enumeration_signed_get_mapping_labels_for_value(
-            enum_ptr, value
-        )
+class _StringFieldClassConst(_FieldClassConst):
+    _NAME = 'Const string'
 
 
-class _StringFieldClass(_FieldClass):
+class _StringFieldClass(_StringFieldClassConst, _FieldClass):
     _NAME = 'String'
 
 
-class _StructureFieldClassMember:
+class _StructureFieldClassMemberConst:
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_const_ptr_and_get_ref
+    )
+    _borrow_field_class_ptr = staticmethod(
+        native_bt.field_class_structure_member_borrow_field_class_const
+    )
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.field_class_structure_member_borrow_user_attributes_const
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
+
     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
@@ -311,17 +371,30 @@ class _StructureFieldClassMember:
 
     @property
     def field_class(self):
-        fc_ptr = native_bt.field_class_structure_member_borrow_field_class_const(
-            self._ptr
-        )
+        fc_ptr = self._borrow_field_class_ptr(self._ptr)
         assert fc_ptr is not None
-        return _create_field_class_from_ptr_and_get_ref(fc_ptr)
+        return self._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)
+        ptr = self._borrow_user_attributes_ptr(self._ptr)
         assert ptr is not None
-        return bt2_value._create_from_ptr_and_get_ref(ptr)
+        return self._create_value_from_ptr_and_get_ref(ptr)
+
+
+class _StructureFieldClassMember(_StructureFieldClassMemberConst):
+    _borrow_field_class_ptr = staticmethod(
+        native_bt.field_class_structure_member_borrow_field_class
+    )
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.field_class_structure_member_borrow_user_attributes
+    )
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_ptr_and_get_ref
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
 
     def _user_attributes(self, user_attributes):
         value = bt2_value.create_value(user_attributes)
@@ -333,8 +406,62 @@ class _StructureFieldClassMember:
     _user_attributes = property(fset=_user_attributes)
 
 
-class _StructureFieldClass(_FieldClass, collections.abc.Mapping):
+class _StructureFieldClassConst(_FieldClassConst, collections.abc.Mapping):
+    _NAME = 'Const structure'
+    _borrow_member_ptr_by_index = staticmethod(
+        native_bt.field_class_structure_borrow_member_by_index_const
+    )
+    _borrow_member_ptr_by_name = staticmethod(
+        native_bt.field_class_structure_borrow_member_by_name_const
+    )
+    _structure_member_field_class_pycls = property(
+        lambda _: _StructureFieldClassMemberConst
+    )
+
+    def __len__(self):
+        count = native_bt.field_class_structure_get_member_count(self._ptr)
+        assert count >= 0
+        return count
+
+    def __getitem__(self, key):
+        if not isinstance(key, str):
+            raise TypeError(
+                "key must be a 'str' object, got '{}'".format(key.__class__.__name__)
+            )
+
+        member_ptr = self._borrow_member_ptr_by_name(self._ptr, key)
+
+        if member_ptr is None:
+            raise KeyError(key)
+
+        return self._structure_member_field_class_pycls(self, member_ptr)
+
+    def __iter__(self):
+        for idx in range(len(self)):
+            member_ptr = self._borrow_member_ptr_by_index(self._ptr, idx)
+            assert member_ptr is not None
+            yield native_bt.field_class_structure_member_get_name(member_ptr)
+
+    def member_at_index(self, index):
+        utils._check_uint64(index)
+
+        if index >= len(self):
+            raise IndexError
+
+        member_ptr = self._borrow_member_ptr_by_index(self._ptr, index)
+        assert member_ptr is not None
+        return self._structure_member_field_class_pycls(self, member_ptr)
+
+
+class _StructureFieldClass(_StructureFieldClassConst, _FieldClass):
     _NAME = 'Structure'
+    _borrow_member_by_index = staticmethod(
+        native_bt.field_class_structure_borrow_member_by_index
+    )
+    _borrow_member_ptr_by_name = staticmethod(
+        native_bt.field_class_structure_borrow_member_by_name
+    )
+    _structure_member_field_class_pycls = property(lambda _: _StructureFieldClassMember)
 
     def append_member(self, name, field_class, user_attributes=None):
         utils._check_str(name)
@@ -359,72 +486,63 @@ class _StructureFieldClass(_FieldClass, collections.abc.Mapping):
         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
-
-    def _create_member_from_ptr(self, member_ptr):
-        return _StructureFieldClassMember(self, member_ptr)
-
-    def __getitem__(self, key):
-        if not isinstance(key, str):
-            raise TypeError(
-                "key must be a 'str' object, got '{}'".format(key.__class__.__name__)
-            )
-
-        member_ptr = native_bt.field_class_structure_borrow_member_by_name_const(
-            self._ptr, key
-        )
-
-        if member_ptr is None:
-            raise KeyError(key)
-
-        return self._create_member_from_ptr(member_ptr)
-
-    def __iter__(self):
-        for idx in range(len(self)):
-            member_ptr = native_bt.field_class_structure_borrow_member_by_index_const(
-                self._ptr, idx
-            )
-            assert member_ptr is not None
-            yield native_bt.field_class_structure_member_get_name(member_ptr)
-
     def __iadd__(self, members):
         for name, field_class in members:
             self.append_member(name, field_class)
 
         return self
 
-    def member_at_index(self, index):
-        utils._check_uint64(index)
-
-        if index >= len(self):
-            raise IndexError
-
-        member_ptr = native_bt.field_class_structure_borrow_member_by_index_const(
-            self._ptr, index
-        )
-        assert member_ptr is not None
-        return self._create_member_from_ptr(member_ptr)
 
+class _OptionFieldClassConst(_FieldClassConst):
+    _NAME = 'Const Option'
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_const_ptr_and_get_ref
+    )
+    _borrow_field_class_ptr = staticmethod(
+        native_bt.field_class_option_borrow_field_class_const
+    )
+    _borrow_selector_field_path = staticmethod(
+        native_bt.field_class_option_borrow_selector_field_path_const
+    )
 
-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)
+        elem_fc_ptr = self._borrow_field_class_ptr(self._ptr)
+        return self._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)
+        ptr = self._borrow_selector_field_path(self._ptr)
         if ptr is None:
             return
 
         return bt2_field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
 
 
-class _VariantFieldClassOption:
+class _OptionFieldClass(_OptionFieldClassConst, _FieldClass):
+    _NAME = 'Option'
+    _borrow_field_class_ptr = staticmethod(
+        native_bt.field_class_option_borrow_field_class
+    )
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_ptr_and_get_ref
+    )
+
+
+class _VariantFieldClassOptionConst:
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_const_ptr_and_get_ref
+    )
+    _borrow_field_class_ptr = staticmethod(
+        native_bt.field_class_variant_option_borrow_field_class_const
+    )
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.field_class_variant_option_borrow_user_attributes_const
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
+
     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
@@ -439,17 +557,30 @@ class _VariantFieldClassOption:
 
     @property
     def field_class(self):
-        fc_ptr = native_bt.field_class_variant_option_borrow_field_class_const(
-            self._ptr
-        )
+        fc_ptr = self._borrow_field_class_ptr(self._ptr)
         assert fc_ptr is not None
-        return _create_field_class_from_ptr_and_get_ref(fc_ptr)
+        return self._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)
+        ptr = self._borrow_user_attributes_ptr(self._ptr)
         assert ptr is not None
-        return bt2_value._create_from_ptr_and_get_ref(ptr)
+        return self._create_value_from_ptr_and_get_ref(ptr)
+
+
+class _VariantFieldClassOption(_VariantFieldClassOptionConst):
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_ptr_and_get_ref
+    )
+    _borrow_field_class_ptr = staticmethod(
+        native_bt.field_class_variant_option_borrow_field_class
+    )
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.field_class_variant_option_borrow_user_attributes_const
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
 
     def _user_attributes(self, user_attributes):
         value = bt2_value.create_value(user_attributes)
@@ -459,21 +590,78 @@ class _VariantFieldClassOption:
     _user_attributes = property(fset=_user_attributes)
 
 
-class _VariantFieldClass(_FieldClass, collections.abc.Mapping):
-    _NAME = 'Variant'
-    _borrow_option_by_name_ptr = staticmethod(
+class _VariantFieldClassWithSelectorOptionConst(_VariantFieldClassOptionConst):
+    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 _VariantFieldClassWithSelectorOption(
+    _VariantFieldClassWithSelectorOptionConst, _VariantFieldClassOption
+):
+    pass
+
+
+class _VariantFieldClassWithSignedSelectorOptionConst(
+    _VariantFieldClassWithSelectorOptionConst
+):
+    _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 _VariantFieldClassWithSignedSelectorOption(
+    _VariantFieldClassWithSignedSelectorOptionConst,
+    _VariantFieldClassWithSelectorOption,
+):
+    pass
+
+
+class _VariantFieldClassWithUnsignedSelectorOptionConst(
+    _VariantFieldClassWithSelectorOptionConst
+):
+    _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 _VariantFieldClassWithUnsignedSelectorOption(
+    _VariantFieldClassWithUnsignedSelectorOptionConst,
+    _VariantFieldClassWithSelectorOption,
+):
+    pass
+
+
+class _VariantFieldClassConst(_FieldClassConst, collections.abc.Mapping):
+    _NAME = 'Const Variant'
+    _borrow_option_ptr_by_name = staticmethod(
         native_bt.field_class_variant_borrow_option_by_name_const
     )
-    _borrow_member_by_index_ptr = staticmethod(
+    _borrow_option_ptr_by_index = staticmethod(
         native_bt.field_class_variant_borrow_option_by_index_const
     )
+    _variant_option_pycls = _VariantFieldClassOptionConst
 
     @staticmethod
     def _as_option_ptr(opt_ptr):
         return opt_ptr
 
     def _create_option_from_ptr(self, opt_ptr):
-        return _VariantFieldClassOption(self, opt_ptr)
+        return self._variant_option_pycls(self, opt_ptr)
 
     def __len__(self):
         count = native_bt.field_class_variant_get_option_count(self._ptr)
@@ -486,7 +674,7 @@ class _VariantFieldClass(_FieldClass, collections.abc.Mapping):
                 "key must be a 'str' object, got '{}'".format(key.__class__.__name__)
             )
 
-        opt_ptr = self._borrow_option_by_name_ptr(self._ptr, key)
+        opt_ptr = self._borrow_option_ptr_by_name(self._ptr, key)
 
         if opt_ptr is None:
             raise KeyError(key)
@@ -495,7 +683,7 @@ class _VariantFieldClass(_FieldClass, collections.abc.Mapping):
 
     def __iter__(self):
         for idx in range(len(self)):
-            opt_ptr = self._borrow_member_by_index_ptr(self._ptr, idx)
+            opt_ptr = self._borrow_option_ptr_by_index(self._ptr, idx)
             assert opt_ptr is not None
             base_opt_ptr = self._as_option_ptr(opt_ptr)
             yield native_bt.field_class_variant_option_get_name(base_opt_ptr)
@@ -506,12 +694,29 @@ class _VariantFieldClass(_FieldClass, collections.abc.Mapping):
         if index >= len(self):
             raise IndexError
 
-        opt_ptr = self._borrow_member_by_index_ptr(self._ptr, index)
+        opt_ptr = self._borrow_option_ptr_by_index(self._ptr, index)
         assert opt_ptr is not None
         return self._create_option_from_ptr(opt_ptr)
 
 
-class _VariantFieldClassWithoutSelector(_VariantFieldClass):
+class _VariantFieldClass(_VariantFieldClassConst, _FieldClass, collections.abc.Mapping):
+    _NAME = 'Variant'
+    _borrow_option_ptr_by_name = staticmethod(
+        native_bt.field_class_variant_borrow_option_by_name
+    )
+    _borrow_option_ptr_by_index = staticmethod(
+        native_bt.field_class_variant_borrow_option_by_index
+    )
+    _variant_option_pycls = _VariantFieldClassOption
+
+
+class _VariantFieldClassWithoutSelectorConst(_VariantFieldClassConst):
+    _NAME = 'Const Variant (without selector)'
+
+
+class _VariantFieldClassWithoutSelector(
+    _VariantFieldClassWithoutSelectorConst, _VariantFieldClass
+):
     _NAME = 'Variant (without selector)'
 
     def append_option(self, name, field_class, user_attributes=None):
@@ -544,45 +749,8 @@ 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):
-        return self._option_type(self, opt_ptr)
+class _VariantFieldClassWithSelectorConst(_VariantFieldClassConst):
+    _NAME = 'Const Variant (with selector)'
 
     @property
     def selector_field_path(self):
@@ -595,10 +763,16 @@ class _VariantFieldClassWithSelector(_VariantFieldClass):
 
         return bt2_field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
 
+
+class _VariantFieldClassWithSelector(
+    _VariantFieldClassWithSelectorConst, _VariantFieldClass
+):
+    _NAME = 'Variant (with selector)'
+
     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._option_type._range_set_type)
+        utils._check_type(ranges, self._variant_option_pycls._range_set_type)
 
         if name in self:
             raise ValueError("duplicate option name '{}'".format(name))
@@ -629,52 +803,90 @@ class _VariantFieldClassWithSelector(_VariantFieldClass):
         return self
 
 
-class _VariantFieldClassWithUnsignedSelector(_VariantFieldClassWithSelector):
-    _NAME = 'Variant (with unsigned selector)'
-    _borrow_option_by_name_ptr = staticmethod(
+class _VariantFieldClassWithUnsignedSelectorConst(_VariantFieldClassWithSelectorConst):
+    _NAME = 'Const Variant (with unsigned selector)'
+    _borrow_option_ptr_by_name = staticmethod(
         native_bt.field_class_variant_with_selector_unsigned_borrow_option_by_name_const
     )
-    _borrow_member_by_index_ptr = staticmethod(
+    _borrow_option_ptr_by_index = staticmethod(
         native_bt.field_class_variant_with_selector_unsigned_borrow_option_by_index_const
     )
     _append_option = staticmethod(
         native_bt.field_class_variant_with_selector_unsigned_append_option
     )
-    _option_type = _VariantFieldClassWithUnsignedSelectorOption
-    _as_option_ptr = staticmethod(_option_type._as_option_ptr)
+    _variant_option_pycls = _VariantFieldClassWithUnsignedSelectorOptionConst
+    _as_option_ptr = staticmethod(_variant_option_pycls._as_option_ptr)
 
 
-class _VariantFieldClassWithSignedSelector(_VariantFieldClassWithSelector):
-    _NAME = 'Variant (with signed selector)'
-    _borrow_option_by_name_ptr = staticmethod(
+class _VariantFieldClassWithUnsignedSelector(
+    _VariantFieldClassWithUnsignedSelectorConst, _VariantFieldClassWithSelector
+):
+    _NAME = 'Variant (with unsigned selector)'
+    _variant_option_pycls = _VariantFieldClassWithUnsignedSelectorOption
+    _as_option_ptr = staticmethod(_variant_option_pycls._as_option_ptr)
+
+
+class _VariantFieldClassWithSignedSelectorConst(_VariantFieldClassWithSelectorConst):
+    _NAME = 'Const Variant (with signed selector)'
+    _borrow_option_ptr_by_name = staticmethod(
         native_bt.field_class_variant_with_selector_signed_borrow_option_by_name_const
     )
-    _borrow_member_by_index_ptr = staticmethod(
+    _borrow_option_ptr_by_index = staticmethod(
         native_bt.field_class_variant_with_selector_signed_borrow_option_by_index_const
     )
     _append_option = staticmethod(
         native_bt.field_class_variant_with_selector_signed_append_option
     )
-    _option_type = _VariantFieldClassWithSignedSelectorOption
-    _as_option_ptr = staticmethod(_option_type._as_option_ptr)
+    _variant_option_pycls = _VariantFieldClassWithSignedSelectorOptionConst
+    _as_option_ptr = staticmethod(_variant_option_pycls._as_option_ptr)
+
+
+class _VariantFieldClassWithSignedSelector(
+    _VariantFieldClassWithSignedSelectorConst, _VariantFieldClassWithSelector
+):
+    _NAME = 'Variant (with signed selector)'
+    _variant_option_pycls = _VariantFieldClassWithSignedSelectorOption
+    _as_option_ptr = staticmethod(_variant_option_pycls._as_option_ptr)
 
 
-class _ArrayFieldClass(_FieldClass):
+class _ArrayFieldClassConst(_FieldClassConst):
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_const_ptr_and_get_ref
+    )
+    _borrow_element_field_class = staticmethod(
+        native_bt.field_class_array_borrow_element_field_class_const
+    )
+
     @property
     def element_field_class(self):
-        elem_fc_ptr = native_bt.field_class_array_borrow_element_field_class_const(
-            self._ptr
-        )
-        return _create_field_class_from_ptr_and_get_ref(elem_fc_ptr)
+        elem_fc_ptr = self._borrow_element_field_class(self._ptr)
+        return self._create_field_class_from_ptr_and_get_ref(elem_fc_ptr)
 
 
-class _StaticArrayFieldClass(_ArrayFieldClass):
+class _ArrayFieldClass(_ArrayFieldClassConst, _FieldClass):
+    _create_field_class_from_ptr_and_get_ref = staticmethod(
+        _create_field_class_from_ptr_and_get_ref
+    )
+    _borrow_element_field_class = staticmethod(
+        native_bt.field_class_array_borrow_element_field_class
+    )
+
+
+class _StaticArrayFieldClassConst(_ArrayFieldClassConst):
+    _NAME = 'Const static array'
+
     @property
     def length(self):
         return native_bt.field_class_array_static_get_length(self._ptr)
 
 
-class _DynamicArrayFieldClass(_ArrayFieldClass):
+class _StaticArrayFieldClass(_StaticArrayFieldClassConst, _ArrayFieldClass):
+    _NAME = 'Static array'
+
+
+class _DynamicArrayFieldClassConst(_ArrayFieldClassConst):
+    _NAME = 'Const dynamic array'
+
     @property
     def length_field_path(self):
         ptr = native_bt.field_class_array_dynamic_borrow_length_field_path_const(
@@ -686,6 +898,28 @@ class _DynamicArrayFieldClass(_ArrayFieldClass):
         return bt2_field_path._FieldPath._create_from_ptr_and_get_ref(ptr)
 
 
+class _DynamicArrayFieldClass(_DynamicArrayFieldClassConst, _ArrayFieldClass):
+    _NAME = 'Dynamic Array'
+
+
+_FIELD_CLASS_TYPE_TO_CONST_OBJ = {
+    native_bt.FIELD_CLASS_TYPE_BOOL: _BoolFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_REAL: _RealFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_UNSIGNED_ENUMERATION: _UnsignedEnumerationFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_SIGNED_ENUMERATION: _SignedEnumerationFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_STRING: _StringFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_STRUCTURE: _StructureFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_STATIC_ARRAY: _StaticArrayFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_DYNAMIC_ARRAY: _DynamicArrayFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_OPTION: _OptionFieldClassConst,
+    native_bt.FIELD_CLASS_TYPE_VARIANT_WITHOUT_SELECTOR: _VariantFieldClassWithoutSelectorConst,
+    native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_UNSIGNED_SELECTOR: _VariantFieldClassWithUnsignedSelectorConst,
+    native_bt.FIELD_CLASS_TYPE_VARIANT_WITH_SIGNED_SELECTOR: _VariantFieldClassWithSignedSelectorConst,
+}
+
 _FIELD_CLASS_TYPE_TO_OBJ = {
     native_bt.FIELD_CLASS_TYPE_BOOL: _BoolFieldClass,
     native_bt.FIELD_CLASS_TYPE_BIT_ARRAY: _BitArrayFieldClass,
index 6e3ab761513e054e8caa23f0ebd4e0cd48aad501..cdf18879672414f3f1902949c889a2ce0e05376b 100644 (file)
@@ -32,7 +32,7 @@ def _create_from_ptr(ptr):
     return _MESSAGE_TYPE_TO_CLS[msg_type]._create_from_ptr(ptr)
 
 
-class _Message(object._SharedObject):
+class _MessageConst(object._SharedObject):
     _get_ref = staticmethod(native_bt.message_get_ref)
     _put_ref = staticmethod(native_bt.message_put_ref)
 
@@ -44,6 +44,10 @@ class _Message(object._SharedObject):
             )
 
 
+class _Message(_MessageConst):
+    pass
+
+
 class _MessageWithDefaultClockSnapshot:
     def _get_default_clock_snapshot(self, borrow_clock_snapshot_ptr):
         snapshot_ptr = borrow_clock_snapshot_ptr(self._ptr)
@@ -53,26 +57,36 @@ class _MessageWithDefaultClockSnapshot:
         )
 
 
-class _EventMessage(_Message, _MessageWithDefaultClockSnapshot):
-    _borrow_default_clock_snapshot_ptr = staticmethod(
+class _EventMessageConst(_MessageConst, _MessageWithDefaultClockSnapshot):
+    _borrow_default_clock_snapshot = staticmethod(
         native_bt.message_event_borrow_default_clock_snapshot_const
     )
+    _borrow_event = staticmethod(native_bt.message_event_borrow_event_const)
+    _event_pycls = property(lambda _: bt2_event._EventConst)
 
     @property
     def default_clock_snapshot(self):
         self._check_has_default_clock_class(self.event.stream.cls.default_clock_class)
-        return self._get_default_clock_snapshot(self._borrow_default_clock_snapshot_ptr)
+        return self._get_default_clock_snapshot(self._borrow_default_clock_snapshot)
 
     @property
     def event(self):
-        event_ptr = native_bt.message_event_borrow_event(self._ptr)
+        event_ptr = self._borrow_event(self._ptr)
         assert event_ptr is not None
-        return bt2_event._Event._create_from_ptr_and_get_ref(
+        return self._event_pycls._create_from_ptr_and_get_ref(
             event_ptr, self._ptr, self._get_ref, self._put_ref
         )
 
 
-class _PacketMessage(_Message, _MessageWithDefaultClockSnapshot):
+class _EventMessage(_EventMessageConst, _Message):
+    _borrow_event = staticmethod(native_bt.message_event_borrow_event)
+    _stream_pycls = property(lambda _: bt2_stream._Stream)
+    _event_pycls = property(lambda _: bt2_event._Event)
+
+
+class _PacketMessageConst(_MessageConst, _MessageWithDefaultClockSnapshot):
+    _packet_pycls = bt2_packet._PacketConst
+
     @property
     def default_clock_snapshot(self):
         self._check_has_default_clock_class(self.packet.stream.cls.default_clock_class)
@@ -80,31 +94,47 @@ class _PacketMessage(_Message, _MessageWithDefaultClockSnapshot):
 
     @property
     def packet(self):
-        packet_ptr = self._borrow_packet_ptr(self._ptr)
+        packet_ptr = self._borrow_packet(self._ptr)
         assert packet_ptr is not None
-        return bt2_packet._Packet._create_from_ptr_and_get_ref(packet_ptr)
+        return self._packet_pycls._create_from_ptr_and_get_ref(packet_ptr)
 
 
-class _PacketBeginningMessage(_PacketMessage):
-    _borrow_packet_ptr = staticmethod(native_bt.message_packet_beginning_borrow_packet)
+class _PacketMessage(_PacketMessageConst, _Message):
+    _packet_pycls = bt2_packet._Packet
+
+
+class _PacketBeginningMessageConst(_PacketMessageConst):
+    _borrow_packet = staticmethod(
+        native_bt.message_packet_beginning_borrow_packet_const
+    )
     _borrow_default_clock_snapshot_ptr = staticmethod(
         native_bt.message_packet_beginning_borrow_default_clock_snapshot_const
     )
 
 
-class _PacketEndMessage(_PacketMessage):
-    _borrow_packet_ptr = staticmethod(native_bt.message_packet_end_borrow_packet)
+class _PacketBeginningMessage(_PacketMessage):
+    _borrow_packet = staticmethod(native_bt.message_packet_beginning_borrow_packet)
+
+
+class _PacketEndMessageConst(_PacketMessageConst):
+    _borrow_packet = staticmethod(native_bt.message_packet_end_borrow_packet_const)
     _borrow_default_clock_snapshot_ptr = staticmethod(
         native_bt.message_packet_end_borrow_default_clock_snapshot_const
     )
 
 
-class _StreamMessage(_Message, _MessageWithDefaultClockSnapshot):
+class _PacketEndMessage(_PacketMessage):
+    _borrow_packet = staticmethod(native_bt.message_packet_end_borrow_packet)
+
+
+class _StreamMessageConst(_MessageConst, _MessageWithDefaultClockSnapshot):
+    _stream_pycls = property(lambda _: bt2_stream._StreamConst)
+
     @property
     def stream(self):
         stream_ptr = self._borrow_stream_ptr(self._ptr)
         assert stream_ptr
-        return bt2_stream._Stream._create_from_ptr_and_get_ref(stream_ptr)
+        return self._stream_pycls._create_from_ptr_and_get_ref(stream_ptr)
 
     @property
     def default_clock_snapshot(self):
@@ -119,34 +149,52 @@ class _StreamMessage(_Message, _MessageWithDefaultClockSnapshot):
             snapshot_ptr, self._ptr, self._get_ref, self._put_ref
         )
 
+
+class _StreamMessage(_StreamMessageConst, _Message):
     def _default_clock_snapshot(self, raw_value):
         utils._check_uint64(raw_value)
         self._set_default_clock_snapshot(self._ptr, raw_value)
 
-    _default_clock_snapshot = property(fset=_default_clock_snapshot)
+    _default_clock_snapshot = property(
+        fget=_StreamMessageConst.default_clock_snapshot.fget,
+        fset=_default_clock_snapshot,
+    )
+    _stream_pycls = property(lambda _: bt2_stream._Stream)
 
 
-class _StreamBeginningMessage(_StreamMessage):
-    _borrow_stream_ptr = staticmethod(native_bt.message_stream_beginning_borrow_stream)
+class _StreamBeginningMessageConst(_StreamMessageConst):
+    _borrow_stream_ptr = staticmethod(
+        native_bt.message_stream_beginning_borrow_stream_const
+    )
     _borrow_default_clock_snapshot_ptr = staticmethod(
         native_bt.message_stream_beginning_borrow_default_clock_snapshot_const
     )
+
+
+class _StreamBeginningMessage(_StreamMessage):
+    _borrow_stream_ptr = staticmethod(native_bt.message_stream_beginning_borrow_stream)
     _set_default_clock_snapshot = staticmethod(
         native_bt.message_stream_beginning_set_default_clock_snapshot
     )
 
 
-class _StreamEndMessage(_StreamMessage):
-    _borrow_stream_ptr = staticmethod(native_bt.message_stream_end_borrow_stream)
+class _StreamEndMessageConst(_StreamMessageConst):
+    _borrow_stream_ptr = staticmethod(native_bt.message_stream_end_borrow_stream_const)
     _borrow_default_clock_snapshot_ptr = staticmethod(
         native_bt.message_stream_end_borrow_default_clock_snapshot_const
     )
+
+
+class _StreamEndMessage(_StreamMessage):
+    _borrow_stream_ptr = staticmethod(native_bt.message_stream_end_borrow_stream)
     _set_default_clock_snapshot = staticmethod(
         native_bt.message_stream_end_set_default_clock_snapshot
     )
 
 
-class _MessageIteratorInactivityMessage(_Message, _MessageWithDefaultClockSnapshot):
+class _MessageIteratorInactivityMessageConst(
+    _MessageConst, _MessageWithDefaultClockSnapshot
+):
     _borrow_default_clock_snapshot_ptr = staticmethod(
         native_bt.message_message_iterator_inactivity_borrow_default_clock_snapshot_const
     )
@@ -158,12 +206,20 @@ class _MessageIteratorInactivityMessage(_Message, _MessageWithDefaultClockSnapsh
         return self._get_default_clock_snapshot(self._borrow_default_clock_snapshot_ptr)
 
 
-class _DiscardedMessage(_Message, _MessageWithDefaultClockSnapshot):
+class _MessageIteratorInactivityMessage(
+    _MessageIteratorInactivityMessageConst, _Message
+):
+    pass
+
+
+class _DiscardedMessageConst(_MessageConst, _MessageWithDefaultClockSnapshot):
+    _stream_pycls = property(lambda _: bt2_stream._StreamConst)
+
     @property
     def stream(self):
         stream_ptr = self._borrow_stream_ptr(self._ptr)
         assert stream_ptr
-        return bt2_stream._Stream._create_from_ptr_and_get_ref(stream_ptr)
+        return self._stream_pycls._create_from_ptr_and_get_ref(stream_ptr)
 
     @property
     def count(self):
@@ -171,12 +227,6 @@ class _DiscardedMessage(_Message, _MessageWithDefaultClockSnapshot):
         if avail is native_bt.PROPERTY_AVAILABILITY_AVAILABLE:
             return count
 
-    def _set_count(self, count):
-        utils._check_uint64(count)
-        self._set_count(self._ptr, count)
-
-    _count = property(fset=_set_count)
-
     def _check_has_default_clock_snapshots(self):
         if not self._has_default_clock_snapshots:
             raise ValueError(
@@ -196,12 +246,21 @@ class _DiscardedMessage(_Message, _MessageWithDefaultClockSnapshot):
         return self._get_default_clock_snapshot(self._borrow_end_clock_snapshot_ptr)
 
 
-class _DiscardedEventsMessage(_DiscardedMessage):
+class _DiscardedMessage(_DiscardedMessageConst, _Message):
+    _stream_pycls = property(lambda _: bt2_stream._Stream)
+
+    def _set_count(self, count):
+        utils._check_uint64(count)
+        self._set_count(self._ptr, count)
+
+    _count = property(fget=_DiscardedMessageConst.count.fget, fset=_set_count)
+
+
+class _DiscardedEventsMessageConst(_DiscardedMessageConst):
     _borrow_stream_ptr = staticmethod(
         native_bt.message_discarded_events_borrow_stream_const
     )
     _get_count = staticmethod(native_bt.message_discarded_events_get_count)
-    _set_count = staticmethod(native_bt.message_discarded_events_set_count)
     _borrow_beginning_clock_snapshot_ptr = staticmethod(
         native_bt.message_discarded_events_borrow_beginning_default_clock_snapshot_const
     )
@@ -214,12 +273,16 @@ class _DiscardedEventsMessage(_DiscardedMessage):
         return self.stream.cls.discarded_events_have_default_clock_snapshots
 
 
-class _DiscardedPacketsMessage(_DiscardedMessage):
+class _DiscardedEventsMessage(_DiscardedMessage):
+    _borrow_stream_ptr = staticmethod(native_bt.message_discarded_events_borrow_stream)
+    _set_count = staticmethod(native_bt.message_discarded_events_set_count)
+
+
+class _DiscardedPacketsMessageConst(_DiscardedMessageConst):
     _borrow_stream_ptr = staticmethod(
         native_bt.message_discarded_packets_borrow_stream_const
     )
     _get_count = staticmethod(native_bt.message_discarded_packets_get_count)
-    _set_count = staticmethod(native_bt.message_discarded_packets_set_count)
     _borrow_beginning_clock_snapshot_ptr = staticmethod(
         native_bt.message_discarded_packets_borrow_beginning_default_clock_snapshot_const
     )
@@ -232,6 +295,11 @@ class _DiscardedPacketsMessage(_DiscardedMessage):
         return self.stream.cls.discarded_packets_have_default_clock_snapshots
 
 
+class _DiscardedPacketsMessage(_DiscardedPacketsMessageConst, _DiscardedMessage):
+    _borrow_stream_ptr = staticmethod(native_bt.message_discarded_packets_borrow_stream)
+    _set_count = staticmethod(native_bt.message_discarded_packets_set_count)
+
+
 _MESSAGE_TYPE_TO_CLS = {
     native_bt.MESSAGE_TYPE_EVENT: _EventMessage,
     native_bt.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: _MessageIteratorInactivityMessage,
@@ -242,3 +310,14 @@ _MESSAGE_TYPE_TO_CLS = {
     native_bt.MESSAGE_TYPE_DISCARDED_EVENTS: _DiscardedEventsMessage,
     native_bt.MESSAGE_TYPE_DISCARDED_PACKETS: _DiscardedPacketsMessage,
 }
+
+_MESSAGE_TYPE_TO_CLS = {
+    native_bt.MESSAGE_TYPE_EVENT: _EventMessageConst,
+    native_bt.MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY: _MessageIteratorInactivityMessageConst,
+    native_bt.MESSAGE_TYPE_STREAM_BEGINNING: _StreamBeginningMessageConst,
+    native_bt.MESSAGE_TYPE_STREAM_END: _StreamEndMessageConst,
+    native_bt.MESSAGE_TYPE_PACKET_BEGINNING: _PacketBeginningMessageConst,
+    native_bt.MESSAGE_TYPE_PACKET_END: _PacketEndMessageConst,
+    native_bt.MESSAGE_TYPE_DISCARDED_EVENTS: _DiscardedEventsMessageConst,
+    native_bt.MESSAGE_TYPE_DISCARDED_PACKETS: _DiscardedPacketsMessageConst,
+}
index 09bff7a4fa50cffe4b87f813c34eacec11d229e9..d28beb25a30c6cb9d3f710c8d7d8b77d47e10ff2 100644 (file)
@@ -146,7 +146,7 @@ class _UserMessageIterator(_MessageIterator):
         except Exception:
             raise
 
-        utils._check_type(msg, bt2_message._Message)
+        utils._check_type(msg, bt2_message._MessageConst)
 
         # The reference we return will be given to the message array.
         # However, the `msg` Python object may stay alive, if the user has kept
index a14196969a24bc2dd2bd02ae2016e270a9d6ba2f..04ec688889a8c6541c45cf338109c5b696197908 100644 (file)
@@ -25,23 +25,36 @@ from bt2 import field as bt2_field
 from bt2 import stream as bt2_stream
 
 
-class _Packet(object._SharedObject):
+class _PacketConst(object._SharedObject):
     _get_ref = staticmethod(native_bt.packet_get_ref)
     _put_ref = staticmethod(native_bt.packet_put_ref)
+    _borrow_stream_ptr = staticmethod(native_bt.packet_borrow_stream_const)
+    _borrow_context_field_ptr = staticmethod(
+        native_bt.packet_borrow_context_field_const
+    )
+    _stream_pycls = property(lambda _: bt2_stream._StreamConst)
+    _create_field_from_ptr = staticmethod(bt2_field._create_field_from_const_ptr)
 
     @property
     def stream(self):
-        stream_ptr = native_bt.packet_borrow_stream(self._ptr)
+        stream_ptr = self._borrow_stream_ptr(self._ptr)
         assert stream_ptr is not None
-        return bt2_stream._Stream._create_from_ptr_and_get_ref(stream_ptr)
+        return self._stream_pycls._create_from_ptr_and_get_ref(stream_ptr)
 
     @property
     def context_field(self):
-        field_ptr = native_bt.packet_borrow_context_field(self._ptr)
+        field_ptr = self._borrow_context_field_ptr(self._ptr)
 
         if field_ptr is None:
             return
 
-        return bt2_field._create_field_from_ptr(
+        return self._create_field_from_ptr(
             field_ptr, self._ptr, self._get_ref, self._put_ref
         )
+
+
+class _Packet(_PacketConst):
+    _borrow_stream_ptr = staticmethod(native_bt.packet_borrow_stream)
+    _borrow_context_field_ptr = staticmethod(native_bt.packet_borrow_context_field)
+    _stream_pycls = property(lambda _: bt2_stream._Stream)
+    _create_field_from_ptr = staticmethod(bt2_field._create_field_from_ptr)
index 264d5477f45fc948253db6abb702f3d071003c18..fe2af8621a0421487a47de84e5f19d1ebf8081d1 100644 (file)
@@ -29,46 +29,58 @@ from bt2 import value as bt2_value
 import bt2
 
 
-class _Stream(bt2_object._SharedObject):
+class _StreamConst(bt2_object._SharedObject):
     _get_ref = staticmethod(native_bt.stream_get_ref)
     _put_ref = staticmethod(native_bt.stream_put_ref)
+    _borrow_class_ptr = staticmethod(native_bt.stream_borrow_class_const)
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.stream_borrow_user_attributes_const
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
+    _borrow_trace_ptr = staticmethod(native_bt.stream_borrow_trace_const)
+    _stream_class_pycls = bt2_stream_class._StreamClassConst
+    _trace_pycls = bt2_trace._TraceConst
 
     @property
     def cls(self):
-        stream_class_ptr = native_bt.stream_borrow_class(self._ptr)
+        stream_class_ptr = self._borrow_class_ptr(self._ptr)
         assert stream_class_ptr is not None
-        return bt2_stream_class._StreamClass._create_from_ptr_and_get_ref(
-            stream_class_ptr
-        )
+        return self._stream_class_pycls._create_from_ptr_and_get_ref(stream_class_ptr)
 
     @property
     def name(self):
         return native_bt.stream_get_name(self._ptr)
 
-    def _name(self, name):
-        utils._check_str(name)
-        native_bt.stream_set_name(self._ptr, name)
-
-    _name = property(fset=_name)
-
     @property
     def user_attributes(self):
-        ptr = native_bt.stream_borrow_user_attributes(self._ptr)
+        ptr = self._borrow_user_attributes_ptr(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.stream_set_user_attributes(self._ptr, value._ptr)
-
-    _user_attributes = property(fset=_user_attributes)
+        return self._create_value_from_ptr_and_get_ref(ptr)
 
     @property
     def id(self):
         id = native_bt.stream_get_id(self._ptr)
         return id if id >= 0 else None
 
+    @property
+    def trace(self):
+        trace_ptr = self._borrow_trace_ptr(self._ptr)
+        assert trace_ptr is not None
+        return self._trace_pycls._create_from_ptr_and_get_ref(trace_ptr)
+
+
+class _Stream(_StreamConst):
+    _borrow_class_ptr = staticmethod(native_bt.stream_borrow_class)
+    _borrow_user_attributes_ptr = staticmethod(native_bt.stream_borrow_user_attributes)
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
+    _borrow_trace_ptr = staticmethod(native_bt.stream_borrow_trace)
+    _stream_class_pycls = bt2_stream_class._StreamClass
+    _trace_pycls = bt2_trace._Trace
+
     def create_packet(self):
         if not self.cls.supports_packets:
             raise ValueError(
@@ -82,8 +94,17 @@ class _Stream(bt2_object._SharedObject):
 
         return bt2_packet._Packet._create_from_ptr(packet_ptr)
 
-    @property
-    def trace(self):
-        trace_ptr = native_bt.stream_borrow_trace(self._ptr)
-        assert trace_ptr is not None
-        return bt2_trace._Trace._create_from_ptr_and_get_ref(trace_ptr)
+    def _user_attributes(self, user_attributes):
+        value = bt2_value.create_value(user_attributes)
+        utils._check_type(value, bt2_value.MapValue)
+        native_bt.stream_set_user_attributes(self._ptr, value._ptr)
+
+    _user_attributes = property(
+        fget=_StreamConst.user_attributes.fget, fset=_user_attributes
+    )
+
+    def _name(self, name):
+        utils._check_str(name)
+        native_bt.stream_set_name(self._ptr, name)
+
+    _name = property(fget=_StreamConst.name.fget, fset=_name)
index 2c33dae8ddfa8d8a11ded5eedaadce48bd646139..8a65fac7f8ba92a2c94c500975001ba79d81cf15 100644 (file)
@@ -29,18 +29,40 @@ from bt2 import value as bt2_value
 import collections.abc
 
 
-class _StreamClass(object._SharedObject, collections.abc.Mapping):
+class _StreamClassConst(object._SharedObject, collections.abc.Mapping):
     _get_ref = staticmethod(native_bt.stream_class_get_ref)
     _put_ref = staticmethod(native_bt.stream_class_put_ref)
+    _borrow_event_class_ptr_by_id = staticmethod(
+        native_bt.stream_class_borrow_event_class_by_id_const
+    )
+    _borrow_event_class_ptr_by_index = staticmethod(
+        native_bt.stream_class_borrow_event_class_by_index_const
+    )
+    _borrow_trace_class_ptr = staticmethod(
+        native_bt.stream_class_borrow_trace_class_const
+    )
+    _borrow_packet_context_field_class_ptr = staticmethod(
+        native_bt.stream_class_borrow_packet_context_field_class_const
+    )
+    _borrow_event_common_context_field_class_ptr = staticmethod(
+        native_bt.stream_class_borrow_event_common_context_field_class_const
+    )
+    _borrow_default_clock_class_ptr = staticmethod(
+        native_bt.stream_class_borrow_default_clock_class_const
+    )
+
+    _event_class_cls = property(lambda _: bt2_event_class._EventClassConst)
+    _trace_class_cls = property(lambda _: bt2_trace_class._TraceClassConst)
+    _clock_class_cls = property(lambda _: bt2_clock_class._ClockClassConst)
 
     def __getitem__(self, key):
         utils._check_int64(key)
-        ec_ptr = native_bt.stream_class_borrow_event_class_by_id(self._ptr, key)
+        ec_ptr = self._borrow_event_class_ptr_by_id(self._ptr, key)
 
         if ec_ptr is None:
             raise KeyError(key)
 
-        return bt2_event_class._EventClass._create_from_ptr_and_get_ref(ec_ptr)
+        return self._event_class_cls._create_from_ptr_and_get_ref(ec_ptr)
 
     def __len__(self):
         count = native_bt.stream_class_get_event_class_count(self._ptr)
@@ -49,9 +71,7 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
     def __iter__(self):
         for idx in range(len(self)):
-            ec_ptr = native_bt.stream_class_borrow_event_class_by_index_const(
-                self._ptr, idx
-            )
+            ec_ptr = self._borrow_event_class_ptr_by_index(self._ptr, idx)
             assert ec_ptr is not None
 
             id = native_bt.event_class_get_id(ec_ptr)
@@ -59,6 +79,124 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
             yield id
 
+    @property
+    def trace_class(self):
+        tc_ptr = self._borrow_trace_class_ptr(self._ptr)
+
+        if tc_ptr is not None:
+            return self._trace_class_cls._create_from_ptr_and_get_ref(tc_ptr)
+
+    @property
+    def user_attributes(self):
+        ptr = native_bt.stream_class_borrow_user_attributes(self._ptr)
+        assert ptr is not None
+        return bt2_value._create_from_ptr_and_get_ref(ptr)
+
+    @property
+    def name(self):
+        return native_bt.stream_class_get_name(self._ptr)
+
+    @property
+    def assigns_automatic_event_class_id(self):
+        return native_bt.stream_class_assigns_automatic_event_class_id(self._ptr)
+
+    @property
+    def assigns_automatic_stream_id(self):
+        return native_bt.stream_class_assigns_automatic_stream_id(self._ptr)
+
+    @property
+    def supports_packets(self):
+        return native_bt.stream_class_supports_packets(self._ptr)
+
+    @property
+    def packets_have_beginning_default_clock_snapshot(self):
+        return native_bt.stream_class_packets_have_beginning_default_clock_snapshot(
+            self._ptr
+        )
+
+    @property
+    def packets_have_end_default_clock_snapshot(self):
+        return native_bt.stream_class_packets_have_end_default_clock_snapshot(self._ptr)
+
+    @property
+    def supports_discarded_events(self):
+        return native_bt.stream_class_supports_discarded_events(self._ptr)
+
+    @property
+    def discarded_events_have_default_clock_snapshots(self):
+        return native_bt.stream_class_discarded_events_have_default_clock_snapshots(
+            self._ptr
+        )
+
+    @property
+    def supports_discarded_packets(self):
+        return native_bt.stream_class_supports_discarded_packets(self._ptr)
+
+    @property
+    def discarded_packets_have_default_clock_snapshots(self):
+        return native_bt.stream_class_discarded_packets_have_default_clock_snapshots(
+            self._ptr
+        )
+
+    @property
+    def id(self):
+        id = native_bt.stream_class_get_id(self._ptr)
+
+        if id < 0:
+            return
+
+        return id
+
+    @property
+    def packet_context_field_class(self):
+        fc_ptr = self._borrow_packet_context_field_class_ptr(self._ptr)
+
+        if fc_ptr is None:
+            return
+
+        return bt2_field_class._create_field_class_from_ptr_and_get_ref(fc_ptr)
+
+    @property
+    def event_common_context_field_class(self):
+        fc_ptr = self._borrow_event_common_context_field_class_ptr(self._ptr)
+
+        if fc_ptr is None:
+            return
+
+        return bt2_field_class._create_field_class_from_ptr_and_get_ref(fc_ptr)
+
+    @property
+    def default_clock_class(self):
+        cc_ptr = self._borrow_default_clock_class_ptr(self._ptr)
+        if cc_ptr is None:
+            return
+
+        return self._clock_class_cls._create_from_ptr_and_get_ref(cc_ptr)
+
+
+class _StreamClass(_StreamClassConst):
+    _get_ref = staticmethod(native_bt.stream_class_get_ref)
+    _put_ref = staticmethod(native_bt.stream_class_put_ref)
+    _borrow_event_class_ptr_by_id = staticmethod(
+        native_bt.stream_class_borrow_event_class_by_id
+    )
+    _borrow_event_class_ptr_by_index = staticmethod(
+        native_bt.stream_class_borrow_event_class_by_index
+    )
+    _borrow_trace_class_ptr = staticmethod(native_bt.stream_class_borrow_trace_class)
+    _borrow_packet_context_field_class_ptr = staticmethod(
+        native_bt.stream_class_borrow_packet_context_field_class
+    )
+    _borrow_event_common_context_field_class_ptr = staticmethod(
+        native_bt.stream_class_borrow_event_common_context_field_class
+    )
+    _borrow_default_clock_class_ptr = staticmethod(
+        native_bt.stream_class_borrow_default_clock_class
+    )
+    _event_class_cls = property(lambda s: bt2_event_class._EventClass)
+    _trace_class_cls = property(lambda s: bt2_trace_class._TraceClass)
+    _clock_class_cls = property(lambda s: bt2_clock_class._ClockClass)
+
     def create_event_class(
         self,
         id=None,
@@ -107,19 +245,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
         return event_class
 
-    @property
-    def trace_class(self):
-        tc_ptr = native_bt.stream_class_borrow_trace_class_const(self._ptr)
-
-        if tc_ptr is not None:
-            return bt2_trace_class._TraceClass._create_from_ptr_and_get_ref(tc_ptr)
-
-    @property
-    def user_attributes(self):
-        ptr = native_bt.stream_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)
@@ -127,10 +252,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
     _user_attributes = property(fset=_user_attributes)
 
-    @property
-    def name(self):
-        return native_bt.stream_class_get_name(self._ptr)
-
     def _name(self, name):
         utils._check_str(name)
         status = native_bt.stream_class_set_name(self._ptr, name)
@@ -138,10 +259,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
     _name = property(fset=_name)
 
-    @property
-    def assigns_automatic_event_class_id(self):
-        return native_bt.stream_class_assigns_automatic_event_class_id(self._ptr)
-
     def _assigns_automatic_event_class_id(self, auto_id):
         utils._check_bool(auto_id)
         return native_bt.stream_class_set_assigns_automatic_event_class_id(
@@ -150,10 +267,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
     _assigns_automatic_event_class_id = property(fset=_assigns_automatic_event_class_id)
 
-    @property
-    def assigns_automatic_stream_id(self):
-        return native_bt.stream_class_assigns_automatic_stream_id(self._ptr)
-
     def _assigns_automatic_stream_id(self, auto_id):
         utils._check_bool(auto_id)
         return native_bt.stream_class_set_assigns_automatic_stream_id(
@@ -162,20 +275,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
     _assigns_automatic_stream_id = property(fset=_assigns_automatic_stream_id)
 
-    @property
-    def supports_packets(self):
-        return native_bt.stream_class_supports_packets(self._ptr)
-
-    @property
-    def packets_have_beginning_default_clock_snapshot(self):
-        return native_bt.stream_class_packets_have_beginning_default_clock_snapshot(
-            self._ptr
-        )
-
-    @property
-    def packets_have_end_default_clock_snapshot(self):
-        return native_bt.stream_class_packets_have_end_default_clock_snapshot(self._ptr)
-
     def _set_supports_packets(self, supports, with_begin_cs=False, with_end_cs=False):
         utils._check_bool(supports)
         utils._check_bool(with_begin_cs)
@@ -193,10 +292,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
             self._ptr, supports, with_begin_cs, with_end_cs
         )
 
-    @property
-    def supports_discarded_events(self):
-        return native_bt.stream_class_supports_discarded_events(self._ptr)
-
     def _set_supports_discarded_events(self, supports, with_cs=False):
         utils._check_bool(supports)
         utils._check_bool(with_cs)
@@ -210,15 +305,7 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
             self._ptr, supports, with_cs
         )
 
-    @property
-    def discarded_events_have_default_clock_snapshots(self):
-        return native_bt.stream_class_discarded_events_have_default_clock_snapshots(
-            self._ptr
-        )
-
-    @property
-    def supports_discarded_packets(self):
-        return native_bt.stream_class_supports_discarded_packets(self._ptr)
+    _supports_discarded_events = property(fset=_set_supports_discarded_events)
 
     def _set_supports_discarded_packets(self, supports, with_cs):
         utils._check_bool(supports)
@@ -238,31 +325,7 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
             self._ptr, supports, with_cs
         )
 
-    @property
-    def discarded_packets_have_default_clock_snapshots(self):
-        return native_bt.stream_class_discarded_packets_have_default_clock_snapshots(
-            self._ptr
-        )
-
-    @property
-    def id(self):
-        id = native_bt.stream_class_get_id(self._ptr)
-
-        if id < 0:
-            return
-
-        return id
-
-    @property
-    def packet_context_field_class(self):
-        fc_ptr = native_bt.stream_class_borrow_packet_context_field_class_const(
-            self._ptr
-        )
-
-        if fc_ptr is None:
-            return
-
-        return bt2_field_class._create_field_class_from_ptr_and_get_ref(fc_ptr)
+    _supports_discarded_packets = property(fset=_set_supports_discarded_packets)
 
     def _packet_context_field_class(self, packet_context_field_class):
         if packet_context_field_class is not None:
@@ -282,17 +345,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
     _packet_context_field_class = property(fset=_packet_context_field_class)
 
-    @property
-    def event_common_context_field_class(self):
-        fc_ptr = native_bt.stream_class_borrow_event_common_context_field_class_const(
-            self._ptr
-        )
-
-        if fc_ptr is None:
-            return
-
-        return bt2_field_class._create_field_class_from_ptr_and_get_ref(fc_ptr)
-
     def _event_common_context_field_class(self, event_common_context_field_class):
         if event_common_context_field_class is not None:
             utils._check_type(
@@ -307,14 +359,6 @@ class _StreamClass(object._SharedObject, collections.abc.Mapping):
 
     _event_common_context_field_class = property(fset=_event_common_context_field_class)
 
-    @property
-    def default_clock_class(self):
-        cc_ptr = native_bt.stream_class_borrow_default_clock_class(self._ptr)
-        if cc_ptr is None:
-            return
-
-        return bt2_clock_class._ClockClass._create_from_ptr_and_get_ref(cc_ptr)
-
     def _default_clock_class(self, clock_class):
         utils._check_type(clock_class, bt2_clock_class._ClockClass)
         native_bt.stream_class_set_default_clock_class(self._ptr, clock_class._ptr)
index fcfd16b1948dcf65edf7ebf79da0751934074461..23e5419ca18612fb28067d2f3d94a70f9534cacd 100644 (file)
@@ -31,7 +31,11 @@ import functools
 import uuid as uuidp
 
 
-class _TraceEnvironment(collections.abc.MutableMapping):
+class _TraceEnvironmentConst(collections.abc.Mapping):
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
+
     def __init__(self, trace):
         self._trace = trace
 
@@ -44,21 +48,7 @@ class _TraceEnvironment(collections.abc.MutableMapping):
         if value_ptr is None:
             raise KeyError(key)
 
-        return bt2_value._create_from_ptr_and_get_ref(value_ptr)
-
-    def __setitem__(self, key, value):
-        if isinstance(value, str):
-            set_env_entry_fn = native_bt.trace_set_environment_entry_string
-        elif isinstance(value, int):
-            set_env_entry_fn = native_bt.trace_set_environment_entry_integer
-        else:
-            raise TypeError('expected str or int, got {}'.format(type(value)))
-
-        status = set_env_entry_fn(self._trace._ptr, key, value)
-        utils._handle_func_status(status, "cannot set trace object's environment entry")
-
-    def __delitem__(self, key):
-        raise NotImplementedError
+        return self._create_value_from_ptr_and_get_ref(value_ptr)
 
     def __len__(self):
         count = native_bt.trace_get_environment_entry_count(self._trace._ptr)
@@ -66,7 +56,7 @@ class _TraceEnvironment(collections.abc.MutableMapping):
         return count
 
     def __iter__(self):
-        trace_ptr = self._trace_env._trace._ptr
+        trace_ptr = self._trace._ptr
 
         for idx in range(len(self)):
             borrow_entry_fn = native_bt.trace_borrow_environment_entry_by_index_const
@@ -75,14 +65,43 @@ class _TraceEnvironment(collections.abc.MutableMapping):
             yield entry_name
 
 
-def _trace_destruction_listener_from_native(user_listener, trace_ptr):
-    trace = _Trace._create_from_ptr_and_get_ref(trace_ptr)
-    user_listener(trace)
+class _TraceEnvironment(_TraceEnvironmentConst, collections.abc.MutableMapping):
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
+
+    def __setitem__(self, key, value):
+        if isinstance(value, str):
+            set_env_entry_fn = native_bt.trace_set_environment_entry_string
+        elif isinstance(value, int):
+            set_env_entry_fn = native_bt.trace_set_environment_entry_integer
+        else:
+            raise TypeError('expected str or int, got {}'.format(type(value)))
 
+        status = set_env_entry_fn(self._trace._ptr, key, value)
+        utils._handle_func_status(status, "cannot set trace object's environment entry")
 
-class _Trace(object._SharedObject, collections.abc.Mapping):
+    def __delitem__(self, key):
+        raise NotImplementedError
+
+
+class _TraceConst(object._SharedObject, collections.abc.Mapping):
     _get_ref = staticmethod(native_bt.trace_get_ref)
     _put_ref = staticmethod(native_bt.trace_put_ref)
+    _borrow_stream_ptr_by_id = staticmethod(native_bt.trace_borrow_stream_by_id_const)
+    _borrow_stream_ptr_by_index = staticmethod(
+        native_bt.trace_borrow_stream_by_index_const
+    )
+    _borrow_class_ptr = staticmethod(native_bt.trace_borrow_class_const)
+    _borrow_user_attributes_ptr = staticmethod(
+        native_bt.trace_borrow_user_attributes_const
+    )
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
+    _stream_pycls = property(lambda _: bt2_stream._StreamConst)
+    _trace_class_pycls = property(lambda _: bt2_trace_class._TraceClassConst)
+    _trace_env_pycls = property(lambda _: _TraceEnvironmentConst)
 
     def __len__(self):
         count = native_bt.trace_get_stream_count(self._ptr)
@@ -92,16 +111,16 @@ class _Trace(object._SharedObject, collections.abc.Mapping):
     def __getitem__(self, id):
         utils._check_uint64(id)
 
-        stream_ptr = native_bt.trace_borrow_stream_by_id_const(self._ptr, id)
+        stream_ptr = self._borrow_stream_ptr_by_id(self._ptr, id)
 
         if stream_ptr is None:
             raise KeyError(id)
 
-        return bt2_stream._Stream._create_from_ptr_and_get_ref(stream_ptr)
+        return self._stream_pycls._create_from_ptr_and_get_ref(stream_ptr)
 
     def __iter__(self):
         for idx in range(len(self)):
-            stream_ptr = native_bt.trace_borrow_stream_by_index_const(self._ptr, idx)
+            stream_ptr = self._borrow_stream_ptr_by_index(self._ptr, idx)
             assert stream_ptr is not None
 
             id = native_bt.stream_get_id(stream_ptr)
@@ -111,27 +130,62 @@ class _Trace(object._SharedObject, collections.abc.Mapping):
 
     @property
     def cls(self):
-        trace_class_ptr = native_bt.trace_borrow_class(self._ptr)
+        trace_class_ptr = self._borrow_class_ptr(self._ptr)
         assert trace_class_ptr is not None
-        return bt2_trace_class._TraceClass._create_from_ptr_and_get_ref(trace_class_ptr)
+        return self._trace_class_pycls._create_from_ptr_and_get_ref(trace_class_ptr)
 
     @property
     def user_attributes(self):
-        ptr = native_bt.trace_borrow_user_attributes(self._ptr)
+        ptr = self._borrow_user_attributes_ptr(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.trace_set_user_attributes(self._ptr, value._ptr)
-
-    _user_attributes = property(fset=_user_attributes)
+        return self._create_value_from_ptr_and_get_ref(ptr)
 
     @property
     def name(self):
         return native_bt.trace_get_name(self._ptr)
 
+    @property
+    def uuid(self):
+        uuid_bytes = native_bt.trace_get_uuid(self._ptr)
+        if uuid_bytes is None:
+            return
+
+        return uuidp.UUID(bytes=uuid_bytes)
+
+    @property
+    def environment(self):
+        return self._trace_env_pycls(self)
+
+    def add_destruction_listener(self, listener):
+        '''Add a listener to be called when the trace is destroyed.'''
+        if not callable(listener):
+            raise TypeError("'listener' parameter is not callable")
+
+        fn = native_bt.bt2_trace_add_destruction_listener
+        listener_from_native = functools.partial(
+            _trace_destruction_listener_from_native, listener
+        )
+
+        status, listener_id = fn(self._ptr, listener_from_native)
+        utils._handle_func_status(
+            status, 'cannot add destruction listener to trace object'
+        )
+
+        return utils._ListenerHandle(listener_id, self)
+
+
+class _Trace(_TraceConst):
+    _borrow_stream_ptr_by_id = staticmethod(native_bt.trace_borrow_stream_by_id)
+    _borrow_stream_ptr_by_index = staticmethod(native_bt.trace_borrow_stream_by_index)
+    _borrow_class_ptr = staticmethod(native_bt.trace_borrow_class)
+    _borrow_user_attributes_ptr = staticmethod(native_bt.trace_borrow_user_attributes)
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
+    _stream_pycls = property(lambda _: bt2_stream._Stream)
+    _trace_class_pycls = property(lambda _: bt2_trace_class._TraceClass)
+    _trace_env_pycls = property(lambda _: _TraceEnvironment)
+
     def _name(self, name):
         utils._check_str(name)
         status = native_bt.trace_set_name(self._ptr, name)
@@ -139,13 +193,12 @@ class _Trace(object._SharedObject, collections.abc.Mapping):
 
     _name = property(fset=_name)
 
-    @property
-    def uuid(self):
-        uuid_bytes = native_bt.trace_get_uuid(self._ptr)
-        if uuid_bytes is None:
-            return
+    def _user_attributes(self, user_attributes):
+        value = bt2_value.create_value(user_attributes)
+        utils._check_type(value, bt2_value.MapValue)
+        native_bt.trace_set_user_attributes(self._ptr, value._ptr)
 
-        return uuidp.UUID(bytes=uuid_bytes)
+    _user_attributes = property(fset=_user_attributes)
 
     def _uuid(self, uuid):
         utils._check_type(uuid, uuidp.UUID)
@@ -153,10 +206,6 @@ class _Trace(object._SharedObject, collections.abc.Mapping):
 
     _uuid = property(fset=_uuid)
 
-    @property
-    def environment(self):
-        return _TraceEnvironment(self)
-
     def create_stream(self, stream_class, id=None, name=None, user_attributes=None):
         utils._check_type(stream_class, bt2_stream_class._StreamClass)
 
@@ -191,19 +240,7 @@ class _Trace(object._SharedObject, collections.abc.Mapping):
 
         return stream
 
-    def add_destruction_listener(self, listener):
-        '''Add a listener to be called when the trace is destroyed.'''
-        if not callable(listener):
-            raise TypeError("'listener' parameter is not callable")
-
-        fn = native_bt.bt2_trace_add_destruction_listener
-        listener_from_native = functools.partial(
-            _trace_destruction_listener_from_native, listener
-        )
-
-        status, listener_id = fn(self._ptr, listener_from_native)
-        utils._handle_func_status(
-            status, 'cannot add destruction listener to trace object'
-        )
 
-        return utils._ListenerHandle(listener_id, self)
+def _trace_destruction_listener_from_native(user_listener, trace_ptr):
+    trace = _TraceConst._create_from_ptr_and_get_ref(trace_ptr)
+    user_listener(trace)
index bd39beabdfa5516dad2961e59659ac15b63a985e..94343552b01031238c32dab38e7c23e52fd371f8 100644 (file)
@@ -22,9 +22,6 @@
 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 # THE SOFTWARE.
 
-__all__ = ['_TraceClass']
-
-import bt2
 from bt2 import native_bt, utils, object
 from bt2 import stream_class as bt2_stream_class
 from bt2 import field_class as bt2_field_class
@@ -33,43 +30,33 @@ from bt2 import trace_class as bt2_trace_class
 from bt2 import value as bt2_value
 import collections.abc
 import functools
+import bt2
 
 
 def _trace_class_destruction_listener_from_native(user_listener, trace_class_ptr):
-    trace_class = bt2_trace_class._TraceClass._create_from_ptr_and_get_ref(
-        trace_class_ptr
-    )
+    trace_class = _TraceClass._create_from_ptr_and_get_ref(trace_class_ptr)
     user_listener(trace_class)
 
 
-class _TraceClass(object._SharedObject, collections.abc.Mapping):
+class _TraceClassConst(object._SharedObject, collections.abc.Mapping):
     _get_ref = staticmethod(native_bt.trace_class_get_ref)
     _put_ref = staticmethod(native_bt.trace_class_put_ref)
+    _borrow_stream_class_ptr_by_index = staticmethod(
+        native_bt.trace_class_borrow_stream_class_by_index_const
+    )
+    _borrow_stream_class_ptr_by_id = staticmethod(
+        native_bt.trace_class_borrow_stream_class_by_id_const
+    )
+    _stream_class_pycls = bt2_stream_class._StreamClassConst
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_const_ptr_and_get_ref
+    )
 
-    # Instantiate a trace of this class.
-
-    def __call__(self, name=None, user_attributes=None, uuid=None, environment=None):
-        trace_ptr = native_bt.trace_create(self._ptr)
-
-        if trace_ptr is None:
-            raise bt2._MemoryError('cannot create trace class object')
-
-        trace = bt2_trace._Trace._create_from_ptr(trace_ptr)
-
-        if name is not None:
-            trace._name = name
-
-        if user_attributes is not None:
-            trace._user_attributes = user_attributes
-
-        if uuid is not None:
-            trace._uuid = uuid
-
-        if environment is not None:
-            for key, value in environment.items():
-                trace.environment[key] = value
-
-        return trace
+    @property
+    def user_attributes(self):
+        ptr = native_bt.trace_class_borrow_user_attributes(self._ptr)
+        assert ptr is not None
+        return self._create_value_from_ptr_and_get_ref(ptr)
 
     # Number of stream classes in this trace class.
 
@@ -83,17 +70,15 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping):
     def __getitem__(self, key):
         utils._check_uint64(key)
 
-        sc_ptr = native_bt.trace_class_borrow_stream_class_by_id_const(self._ptr, key)
+        sc_ptr = self._borrow_stream_class_ptr_by_id(self._ptr, key)
         if sc_ptr is None:
             raise KeyError(key)
 
-        return bt2_stream_class._StreamClass._create_from_ptr_and_get_ref(sc_ptr)
+        return self._stream_class_pycls._create_from_ptr_and_get_ref(sc_ptr)
 
     def __iter__(self):
         for idx in range(len(self)):
-            sc_ptr = native_bt.trace_class_borrow_stream_class_by_index_const(
-                self._ptr, idx
-            )
+            sc_ptr = self._borrow_stream_class_ptr_by_index(self._ptr, idx)
             assert sc_ptr is not None
 
             id = native_bt.stream_class_get_id(sc_ptr)
@@ -101,6 +86,67 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping):
 
             yield id
 
+    @property
+    def assigns_automatic_stream_class_id(self):
+        return native_bt.trace_class_assigns_automatic_stream_class_id(self._ptr)
+
+    # Add a listener to be called when the trace class is destroyed.
+
+    def add_destruction_listener(self, listener):
+
+        if not callable(listener):
+            raise TypeError("'listener' parameter is not callable")
+
+        fn = native_bt.bt2_trace_class_add_destruction_listener
+        listener_from_native = functools.partial(
+            _trace_class_destruction_listener_from_native, listener
+        )
+
+        status, listener_id = fn(self._ptr, listener_from_native)
+        utils._handle_func_status(
+            status, 'cannot add destruction listener to trace class object'
+        )
+
+        return utils._ListenerHandle(listener_id, self)
+
+
+class _TraceClass(_TraceClassConst):
+    _borrow_stream_class_ptr_by_index = staticmethod(
+        native_bt.trace_class_borrow_stream_class_by_index
+    )
+    _borrow_stream_class_ptr_by_id = staticmethod(
+        native_bt.trace_class_borrow_stream_class_by_id
+    )
+    _stream_class_pycls = bt2_stream_class._StreamClass
+    _create_value_from_ptr_and_get_ref = staticmethod(
+        bt2_value._create_from_ptr_and_get_ref
+    )
+
+    # Instantiate a trace of this class.
+
+    def __call__(self, name=None, user_attributes=None, uuid=None, environment=None):
+        trace_ptr = native_bt.trace_create(self._ptr)
+
+        if trace_ptr is None:
+            raise bt2._MemoryError('cannot create trace class object')
+
+        trace = bt2_trace._Trace._create_from_ptr(trace_ptr)
+
+        if name is not None:
+            trace._name = name
+
+        if user_attributes is not None:
+            trace._user_attributes = user_attributes
+
+        if uuid is not None:
+            trace._uuid = uuid
+
+        if environment is not None:
+            for key, value in environment.items():
+                trace.environment[key] = value
+
+        return trace
+
     def create_stream_class(
         self,
         id=None,
@@ -176,12 +222,6 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping):
         )
         return sc
 
-    @property
-    def user_attributes(self):
-        ptr = native_bt.trace_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)
@@ -189,10 +229,6 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping):
 
     _user_attributes = property(fset=_user_attributes)
 
-    @property
-    def assigns_automatic_stream_class_id(self):
-        return native_bt.trace_class_assigns_automatic_stream_class_id(self._ptr)
-
     def _assigns_automatic_stream_class_id(self, auto_id):
         utils._check_bool(auto_id)
         return native_bt.trace_class_set_assigns_automatic_stream_class_id(
@@ -391,22 +427,3 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping):
         fc = bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr)
         self._set_field_class_user_attrs(fc, user_attributes)
         return fc
-
-    # Add a listener to be called when the trace class is destroyed.
-
-    def add_destruction_listener(self, listener):
-
-        if not callable(listener):
-            raise TypeError("'listener' parameter is not callable")
-
-        fn = native_bt.bt2_trace_class_add_destruction_listener
-        listener_from_native = functools.partial(
-            _trace_class_destruction_listener_from_native, listener
-        )
-
-        status, listener_id = fn(self._ptr, listener_from_native)
-        utils._handle_func_status(
-            status, 'cannot add destruction listener to trace class object'
-        )
-
-        return utils._ListenerHandle(listener_id, self)
index 208e8b29f253eec99797e31bf6727b664c1316ef..f630c3371df9e412c6a561daae9359ce58cd493d 100644 (file)
@@ -19,6 +19,7 @@
 import unittest
 import uuid
 import bt2
+import utils
 from utils import run_in_component_init, TestOutputPortMessageIterator
 from bt2 import value as bt2_value
 from bt2 import clock_class as bt2_clock_class
@@ -221,6 +222,10 @@ class ClockClassTestCase(unittest.TestCase):
 
         self.assertRaisesInComponentInit(TypeError, f)
 
+    def test_const_user_attributes(self):
+        cc = utils.get_const_event_message().default_clock_snapshot.clock_class
+        self.assertIs(type(cc.user_attributes), bt2_value._MapValueConst)
+
 
 class ClockSnapshotTestCase(unittest.TestCase):
     def setUp(self):
index e4a0f7549e8e813ad3d562d831e2c66f162deb55..9c71c0204e182f0ca8c711d8d9810f7a5e5539ca 100644 (file)
 
 import unittest
 import bt2
+import utils
 from utils import TestOutputPortMessageIterator
 
+from bt2 import field as bt2_field
+from bt2 import stream as bt2_stream
+from bt2 import event_class as bt2_event_class
+from bt2 import clock_snapshot as bt2_clock_snapshot
+
 
 class EventTestCase(unittest.TestCase):
-    def _create_test_event_message(
+    def _create_test_const_event_message(
         self,
         packet_fields_config=None,
         event_fields_config=None,
@@ -158,87 +164,127 @@ class EventTestCase(unittest.TestCase):
         )
 
         for msg in self._msg_iter:
-            if type(msg) is bt2._EventMessage:
+            if type(msg) is bt2._EventMessageConst:
+                self._event_msg = msg
                 return msg
 
-    def test_attr_event_class(self):
-        msg = self._create_test_event_message()
+    def test_const_attr_event_class(self):
+        msg = self._create_test_const_event_message()
         self.assertEqual(msg.event.cls.addr, self.event_class.addr)
+        self.assertIs(type(msg.event.cls), bt2_event_class._EventClassConst)
+
+    def test_attr_event_class(self):
+        msg = utils.get_event_message()
+        self.assertIs(type(msg.event.cls), bt2_event_class._EventClass)
 
-    def test_attr_name(self):
-        msg = self._create_test_event_message()
+    def test_const_attr_name(self):
+        msg = self._create_test_const_event_message()
         self.assertEqual(msg.event.name, self.event_class.name)
 
-    def test_attr_id(self):
-        msg = self._create_test_event_message()
+    def test_const_attr_id(self):
+        msg = self._create_test_const_event_message()
         self.assertEqual(msg.event.id, self.event_class.id)
 
-    def test_get_common_context_field(self):
+    def test_const_get_common_context_field(self):
         def event_fields_config(event):
             event.common_context_field['cpu_id'] = 1
             event.common_context_field['stuff'] = 13.194
 
-        msg = self._create_test_event_message(
+        msg = self._create_test_const_event_message(
             event_fields_config=event_fields_config, with_cc=True
         )
 
         self.assertEqual(msg.event.common_context_field['cpu_id'], 1)
         self.assertEqual(msg.event.common_context_field['stuff'], 13.194)
+        self.assertIs(
+            type(msg.event.common_context_field), bt2_field._StructureFieldConst
+        )
+
+    def test_attr_common_context_field(self):
+        msg = utils.get_event_message()
+        self.assertIs(type(msg.event.common_context_field), bt2_field._StructureField)
 
-    def test_no_common_context_field(self):
-        msg = self._create_test_event_message(with_cc=False)
+    def test_const_no_common_context_field(self):
+        msg = self._create_test_const_event_message(with_cc=False)
         self.assertIsNone(msg.event.common_context_field)
 
-    def test_get_specific_context_field(self):
+    def test_const_get_specific_context_field(self):
         def event_fields_config(event):
             event.specific_context_field['ant'] = -1
             event.specific_context_field['msg'] = 'hellooo'
 
-        msg = self._create_test_event_message(
+        msg = self._create_test_const_event_message(
             event_fields_config=event_fields_config, with_sc=True
         )
 
         self.assertEqual(msg.event.specific_context_field['ant'], -1)
         self.assertEqual(msg.event.specific_context_field['msg'], 'hellooo')
+        self.assertIs(
+            type(msg.event.specific_context_field), bt2_field._StructureFieldConst
+        )
+
+    def test_attr_specific_context_field(self):
+        msg = utils.get_event_message()
+        self.assertIs(type(msg.event.specific_context_field), bt2_field._StructureField)
 
-    def test_no_specific_context_field(self):
-        msg = self._create_test_event_message(with_sc=False)
+    def test_const_no_specific_context_field(self):
+        msg = self._create_test_const_event_message(with_sc=False)
         self.assertIsNone(msg.event.specific_context_field)
 
-    def test_get_event_payload_field(self):
+    def test_const_get_event_payload_field(self):
         def event_fields_config(event):
             event.payload_field['giraffe'] = 1
             event.payload_field['gnu'] = 23
             event.payload_field['mosquito'] = 42
 
-        msg = self._create_test_event_message(
+        msg = self._create_test_const_event_message(
             event_fields_config=event_fields_config, with_ep=True
         )
 
         self.assertEqual(msg.event.payload_field['giraffe'], 1)
         self.assertEqual(msg.event.payload_field['gnu'], 23)
         self.assertEqual(msg.event.payload_field['mosquito'], 42)
+        self.assertIs(type(msg.event.payload_field), bt2_field._StructureFieldConst)
+
+    def test_attr_payload_field(self):
+        msg = utils.get_event_message()
+        self.assertIs(type(msg.event.payload_field), bt2_field._StructureField)
 
-    def test_no_payload_field(self):
-        msg = self._create_test_event_message(with_ep=False)
+    def test_const_no_payload_field(self):
+        msg = self._create_test_const_event_message(with_ep=False)
         self.assertIsNone(msg.event.payload_field)
 
+    def test_const_clock_value(self):
+        msg = self._create_test_const_event_message(with_clockclass=True)
+        self.assertEqual(msg.default_clock_snapshot.value, 789)
+        self.assertIs(
+            type(msg.default_clock_snapshot), bt2_clock_snapshot._ClockSnapshotConst
+        )
+
     def test_clock_value(self):
-        msg = self._create_test_event_message(with_clockclass=True)
+        msg = utils.get_event_message()
         self.assertEqual(msg.default_clock_snapshot.value, 789)
+        self.assertIs(
+            type(msg.default_clock_snapshot), bt2_clock_snapshot._ClockSnapshotConst
+        )
 
-    def test_no_clock_value(self):
-        msg = self._create_test_event_message(with_clockclass=False)
+    def test_const_no_clock_value(self):
+        msg = self._create_test_const_event_message(with_clockclass=False)
         with self.assertRaisesRegex(
             ValueError, 'stream class has no default clock class'
         ):
             msg.default_clock_snapshot
 
-    def test_stream(self):
-        msg = self._create_test_event_message()
+    def test_const_stream(self):
+        msg = self._create_test_const_event_message()
         self.assertEqual(msg.event.stream.addr, self.stream.addr)
+        self.assertIs(type(msg.event.stream), bt2_stream._StreamConst)
 
-    def test_getitem(self):
+    def test_stream(self):
+        msg = utils.get_event_message()
+        self.assertIs(type(msg.event.stream), bt2_stream._Stream)
+
+    def test_const_getitem(self):
         def event_fields_config(event):
             event.payload_field['giraffe'] = 1
             event.payload_field['gnu'] = 23
@@ -252,7 +298,7 @@ class EventTestCase(unittest.TestCase):
             packet.context_field['something'] = 154
             packet.context_field['something_else'] = 17.2
 
-        msg = self._create_test_event_message(
+        msg = self._create_test_const_event_message(
             packet_fields_config=packet_fields_config,
             event_fields_config=event_fields_config,
             with_cc=True,
@@ -264,20 +310,36 @@ class EventTestCase(unittest.TestCase):
 
         # Test event fields
         self.assertEqual(ev['giraffe'], 1)
+        self.assertIs(type(ev['giraffe']), bt2_field._SignedIntegerFieldConst)
         self.assertEqual(ev['gnu'], 23)
         self.assertEqual(ev['mosquito'], 42)
         self.assertEqual(ev['ant'], -1)
+        self.assertIs(type(ev['ant']), bt2_field._SignedIntegerFieldConst)
         self.assertEqual(ev['msg'], 'hellooo')
         self.assertEqual(ev['cpu_id'], 1)
+        self.assertIs(type(ev['cpu_id']), bt2_field._SignedIntegerFieldConst)
         self.assertEqual(ev['stuff'], 13.194)
 
         # Test packet fields
         self.assertEqual(ev['something'], 154)
+        self.assertIs(type(ev['something']), bt2_field._UnsignedIntegerFieldConst)
         self.assertEqual(ev['something_else'], 17.2)
 
         with self.assertRaises(KeyError):
             ev['yes']
 
+    def test_getitem(self):
+        msg = utils.get_event_message()
+        ev = msg.event
+        self.assertEqual(ev['giraffe'], 1)
+        self.assertIs(type(ev['giraffe']), bt2_field._SignedIntegerField)
+        self.assertEqual(ev['ant'], -1)
+        self.assertIs(type(ev['ant']), bt2_field._SignedIntegerField)
+        self.assertEqual(ev['cpu_id'], 1)
+        self.assertIs(type(ev['cpu_id']), bt2_field._SignedIntegerField)
+        self.assertEqual(ev['something'], 154)
+        self.assertIs(type(ev['something']), bt2_field._UnsignedIntegerField)
+
 
 if __name__ == "__main__":
     unittest.main()
index ffc10bc4bdac703635f5c24f442844f78906ec51..131907107ec2de8ccf785c77a5a56ca37a1e8448 100644 (file)
 import unittest
 import bt2
 from utils import get_default_trace_class
+from bt2 import stream_class as bt2_stream_class
+from bt2 import event_class as bt2_event_class
+from bt2 import field_class as bt2_field_class
+from bt2 import value as bt2_value
+from utils import TestOutputPortMessageIterator
+
+
+def _create_const_event_class(tc, stream_class):
+    fc1 = tc.create_structure_field_class()
+    fc2 = tc.create_structure_field_class()
+    event_class = stream_class.create_event_class(
+        payload_field_class=fc1, specific_context_field_class=fc2
+    )
+
+    class MyIter(bt2._UserMessageIterator):
+        def __init__(self, self_port_output):
+
+            trace = tc()
+            stream = trace.create_stream(stream_class)
+            self._msgs = [
+                self._create_stream_beginning_message(stream),
+                self._create_event_message(event_class, stream),
+            ]
+
+        def __next__(self):
+            if len(self._msgs) == 0:
+                raise StopIteration
+
+            return self._msgs.pop(0)
+
+    class MySrc(bt2._UserSourceComponent, message_iterator_class=MyIter):
+        def __init__(self, params, obj):
+            self._add_output_port('out', params)
+
+    graph = bt2.Graph()
+    src_comp = graph.add_component(MySrc, 'my_source', None)
+    msg_iter = TestOutputPortMessageIterator(graph, src_comp.output_ports['out'])
+
+    # Ignore first message, stream beginning
+    _ = next(msg_iter)
+
+    event_msg = next(msg_iter)
+
+    return event_msg.event.cls
 
 
 class EventClassTestCase(unittest.TestCase):
@@ -41,6 +85,7 @@ class EventClassTestCase(unittest.TestCase):
     def test_create_default(self):
         ec = self._stream_class.create_event_class()
 
+        self.assertIs(type(ec), bt2_event_class._EventClass)
         self.assertIsNone(ec.name, 'my_event')
         self.assertTrue(type(ec.id), int)
         self.assertIsNone(ec.specific_context_field_class)
@@ -58,6 +103,16 @@ class EventClassTestCase(unittest.TestCase):
         fc = self._tc.create_structure_field_class()
         ec = self._stream_class.create_event_class(specific_context_field_class=fc)
         self.assertEqual(ec.specific_context_field_class.addr, fc.addr)
+        self.assertIs(
+            type(ec.specific_context_field_class), bt2_field_class._StructureFieldClass
+        )
+
+    def test_const_create_specific_context_field_class(self):
+        ec_const = _create_const_event_class(self._tc, self._stream_class)
+        self.assertIs(
+            type(ec_const.specific_context_field_class),
+            bt2_field_class._StructureFieldClassConst,
+        )
 
     def test_create_invalid_specific_context_field_class(self):
         with self.assertRaises(TypeError):
@@ -67,6 +122,16 @@ class EventClassTestCase(unittest.TestCase):
         fc = self._tc.create_structure_field_class()
         ec = self._stream_class.create_event_class(payload_field_class=fc)
         self.assertEqual(ec.payload_field_class.addr, fc.addr)
+        self.assertIs(
+            type(ec.payload_field_class), bt2_field_class._StructureFieldClass
+        )
+
+    def test_const_create_payload_field_class(self):
+        ec_const = _create_const_event_class(self._tc, self._stream_class)
+        self.assertIs(
+            type(ec_const.payload_field_class),
+            bt2_field_class._StructureFieldClassConst,
+        )
 
     def test_create_invalid_payload_field_class(self):
         with self.assertRaises(TypeError):
@@ -101,6 +166,11 @@ class EventClassTestCase(unittest.TestCase):
     def test_create_user_attributes(self):
         ec = self._stream_class.create_event_class(user_attributes={'salut': 23})
         self.assertEqual(ec.user_attributes, {'salut': 23})
+        self.assertIs(type(ec.user_attributes), bt2_value.MapValue)
+
+    def test_const_create_user_attributes(self):
+        ec_const = _create_const_event_class(self._tc, self._stream_class)
+        self.assertIs(type(ec_const.user_attributes), bt2_value._MapValueConst)
 
     def test_create_invalid_user_attributes(self):
         with self.assertRaises(TypeError):
@@ -113,3 +183,8 @@ class EventClassTestCase(unittest.TestCase):
     def test_stream_class(self):
         ec = self._stream_class.create_event_class()
         self.assertEqual(ec.stream_class.addr, self._stream_class.addr)
+        self.assertIs(type(ec.stream_class), bt2_stream_class._StreamClass)
+
+    def test_const_stream_class(self):
+        ec_const = _create_const_event_class(self._tc, self._stream_class)
+        self.assertIs(type(ec_const.stream_class), bt2_stream_class._StreamClassConst)
index 5a338801245dfad89ac374b0c93d7e6af528a5d9..cdacd7ffa63971e462029877080ef744a58dc58a 100644 (file)
@@ -24,7 +24,7 @@ import copy
 import itertools
 import collections
 import bt2
-from utils import get_default_trace_class
+from utils import get_default_trace_class, TestOutputPortMessageIterator
 
 
 _COMP_BINOPS = (operator.eq, operator.ne)
@@ -63,6 +63,50 @@ def _create_field(tc, field_class):
     return packet.context_field[field_name]
 
 
+# Create a const field of the given field class.
+#
+# The field is part of a dummy stream, itself part of a dummy trace created
+# from trace class `tc`.
+
+
+def _create_const_field(tc, field_class, field_value_setter_fn):
+    field_name = 'const field'
+
+    class MyIter(bt2._UserMessageIterator):
+        def __init__(self, self_port_output):
+            nonlocal field_class
+            nonlocal field_value_setter_fn
+            stream = _create_stream(tc, [(field_name, field_class)])
+            packet = stream.create_packet()
+
+            field_value_setter_fn(packet.context_field[field_name])
+
+            self._msgs = [
+                self._create_stream_beginning_message(stream),
+                self._create_packet_beginning_message(packet),
+            ]
+
+        def __next__(self):
+            if len(self._msgs) == 0:
+                raise StopIteration
+
+            return self._msgs.pop(0)
+
+    class MySrc(bt2._UserSourceComponent, message_iterator_class=MyIter):
+        def __init__(self, params, obj):
+            self._add_output_port('out', params)
+
+    graph = bt2.Graph()
+    src_comp = graph.add_component(MySrc, 'my_source', None)
+    msg_iter = TestOutputPortMessageIterator(graph, src_comp.output_ports['out'])
+
+    # Ignore first message, stream beginning
+    _ = next(msg_iter)
+    packet_beg_msg = next(msg_iter)
+
+    return packet_beg_msg.packet.context_field[field_name]
+
+
 # Create a field of type string.
 #
 # The field is part of a dummy stream, itself part of a dummy trace created
@@ -1124,6 +1168,10 @@ def _inject_numeric_testing_methods(cls):
 
 
 class BoolFieldTestCase(_TestNumericField, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.value = True
+
     def _create_fc(self, tc):
         return tc.create_bool_field_class()
 
@@ -1132,8 +1180,15 @@ class BoolFieldTestCase(_TestNumericField, unittest.TestCase):
         self._def = _create_field(self._tc, self._create_fc(self._tc))
         self._def.value = True
         self._def_value = True
+        self._def_const = _create_const_field(
+            self._tc, self._tc.create_bool_field_class(), self._const_value_setter
+        )
         self._def_new_value = False
 
+    def test_classes(self):
+        self.assertIs(type(self._def), bt2._BoolField)
+        self.assertIs(type(self._def_const), bt2._BoolFieldConst)
+
     def test_assign_true(self):
         raw = True
         self._def.value = raw
@@ -1370,10 +1425,17 @@ _inject_numeric_testing_methods(RealFieldTestCase)
 
 
 class StringFieldTestCase(unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.value = 'Hello, World!'
+
     def setUp(self):
         self._tc = get_default_trace_class()
         self._def_value = 'Hello, World!'
         self._def = _create_string_field(self._tc)
+        self._def_const = _create_const_field(
+            self._tc, self._tc.create_string_field_class(), self._const_value_setter
+        )
         self._def.value = self._def_value
         self._def_new_value = 'Yes!'
 
@@ -1390,6 +1452,9 @@ class StringFieldTestCase(unittest.TestCase):
     def test_eq(self):
         self.assertEqual(self._def, self._def_value)
 
+    def test_const_eq(self):
+        self.assertEqual(self._def_const, self._def_value)
+
     def test_not_eq(self):
         self.assertNotEqual(self._def, 23)
 
@@ -1453,12 +1518,21 @@ class StringFieldTestCase(unittest.TestCase):
     def test_getitem(self):
         self.assertEqual(self._def[5], self._def_value[5])
 
+    def test_const_getitem(self):
+        self.assertEqual(self._def_const[5], self._def_value[5])
+
     def test_append_str(self):
         to_append = 'meow meow meow'
         self._def += to_append
         self._def_value += to_append
         self.assertEqual(self._def, self._def_value)
 
+    def test_const_append_str(self):
+        to_append = 'meow meow meow'
+        with self.assertRaises(TypeError):
+            self._def_const += to_append
+        self.assertEqual(self._def_const, self._def_value)
+
     def test_append_string_field(self):
         field = _create_string_field(self._tc)
         to_append = 'meow meow meow'
@@ -1486,6 +1560,11 @@ class _TestArrayFieldCommon:
         self.assertIs(type(field), bt2._SignedIntegerField)
         self.assertEqual(field, 1847)
 
+    def test_const_getitem(self):
+        field = self._def_const[1]
+        self.assertIs(type(field), bt2._SignedIntegerFieldConst)
+        self.assertEqual(field, 1847)
+
     def test_eq(self):
         field = _create_int_array_field(self._tc, 3)
         field[0] = 45
@@ -1550,10 +1629,18 @@ class _TestArrayFieldCommon:
         with self.assertRaises(IndexError):
             self._def[len(self._def)] = 134679
 
+    def test_const_setitem(self):
+        with self.assertRaises(TypeError):
+            self._def_const[0] = 134679
+
     def test_iter(self):
         for field, value in zip(self._def, (45, 1847, 1948754)):
             self.assertEqual(field, value)
 
+    def test_const_iter(self):
+        for field, value in zip(self._def_const, (45, 1847, 1948754)):
+            self.assertEqual(field, value)
+
     def test_value_int_field(self):
         values = [45646, 145, 12145]
         self._def.value = values
@@ -1599,6 +1686,10 @@ class _TestArrayFieldCommon:
 
 
 class StaticArrayFieldTestCase(_TestArrayFieldCommon, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.value = [45, 1847, 1948754]
+
     def setUp(self):
         self._tc = get_default_trace_class()
         self._def = _create_int_array_field(self._tc, 3)
@@ -1606,6 +1697,13 @@ class StaticArrayFieldTestCase(_TestArrayFieldCommon, unittest.TestCase):
         self._def[1] = 1847
         self._def[2] = 1948754
         self._def_value = [45, 1847, 1948754]
+        self._def_const = _create_const_field(
+            self._tc,
+            self._tc.create_static_array_field_class(
+                self._tc.create_signed_integer_field_class(32), 3
+            ),
+            self._const_value_setter,
+        )
 
     def test_value_wrong_len(self):
         values = [45, 1847]
@@ -1614,6 +1712,10 @@ class StaticArrayFieldTestCase(_TestArrayFieldCommon, unittest.TestCase):
 
 
 class DynamicArrayFieldTestCase(_TestArrayFieldCommon, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.value = [45, 1847, 1948754]
+
     def setUp(self):
         self._tc = get_default_trace_class()
         self._def = _create_dynamic_array(self._tc)
@@ -1621,6 +1723,13 @@ class DynamicArrayFieldTestCase(_TestArrayFieldCommon, unittest.TestCase):
         self._def[1] = 1847
         self._def[2] = 1948754
         self._def_value = [45, 1847, 1948754]
+        self._def_const = _create_const_field(
+            self._tc,
+            self._tc.create_dynamic_array_field_class(
+                self._tc.create_signed_integer_field_class(32)
+            ),
+            self._const_value_setter,
+        )
 
     def test_value_resize(self):
         new_values = [1, 2, 3, 4]
@@ -1632,12 +1741,28 @@ class DynamicArrayFieldTestCase(_TestArrayFieldCommon, unittest.TestCase):
         self._def[3] = 0
         self.assertEqual(len(self._def), 4)
 
+    def test_const_set_length(self):
+        with self.assertRaises(AttributeError):
+            self._def_const.length = 4
+        self.assertEqual(len(self._def), 3)
+
     def test_set_invalid_length(self):
         with self.assertRaises(TypeError):
             self._def.length = 'cheval'
 
 
 class StructureFieldTestCase(unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.value = {
+            'A': -1872,
+            'B': 'salut',
+            'C': 17.5,
+            'D': 16497,
+            'E': {},
+            'F': {'F_1': 52},
+        }
+
     def _create_fc(self, tc):
         fc = tc.create_structure_field_class()
         fc.append_member('A', self._fc0_fn())
@@ -1677,6 +1802,10 @@ class StructureFieldTestCase(unittest.TestCase):
             'F': {'F_1': 52},
         }
 
+        self._def_const = _create_const_field(
+            self._tc, self._create_fc(self._tc), self._const_value_setter
+        )
+
     def _modify_def(self):
         self._def['B'] = 'hola'
 
@@ -1691,9 +1820,56 @@ class StructureFieldTestCase(unittest.TestCase):
         self.assertEqual(len(self._def), len(self._def_value))
 
     def test_getitem(self):
-        field = self._def['A']
-        self.assertIs(type(field), bt2._SignedIntegerField)
-        self.assertEqual(field, -1872)
+        field1 = self._def['A']
+        field2 = self._def['B']
+        field3 = self._def['C']
+        field4 = self._def['D']
+        field5 = self._def['E']
+        field6 = self._def['F']
+
+        self.assertIs(type(field1), bt2._SignedIntegerField)
+        self.assertEqual(field1, -1872)
+
+        self.assertIs(type(field2), bt2._StringField)
+        self.assertEqual(field2, 'salut')
+
+        self.assertIs(type(field3), bt2._RealField)
+        self.assertEqual(field3, 17.5)
+
+        self.assertIs(type(field4), bt2._SignedIntegerField)
+        self.assertEqual(field4, 16497)
+
+        self.assertIs(type(field5), bt2._StructureField)
+        self.assertEqual(field5, {})
+
+        self.assertIs(type(field6), bt2._StructureField)
+        self.assertEqual(field6, {'F_1': 52})
+
+    def test_const_getitem(self):
+        field1 = self._def_const['A']
+        field2 = self._def_const['B']
+        field3 = self._def_const['C']
+        field4 = self._def_const['D']
+        field5 = self._def_const['E']
+        field6 = self._def_const['F']
+
+        self.assertIs(type(field1), bt2._SignedIntegerFieldConst)
+        self.assertEqual(field1, -1872)
+
+        self.assertIs(type(field2), bt2._StringFieldConst)
+        self.assertEqual(field2, 'salut')
+
+        self.assertIs(type(field3), bt2._RealFieldConst)
+        self.assertEqual(field3, 17.5)
+
+        self.assertIs(type(field4), bt2._SignedIntegerFieldConst)
+        self.assertEqual(field4, 16497)
+
+        self.assertIs(type(field5), bt2._StructureFieldConst)
+        self.assertEqual(field5, {})
+
+        self.assertIs(type(field6), bt2._StructureFieldConst)
+        self.assertEqual(field6, {'F_1': 52})
 
     def test_member_at_index_out_of_bounds_after(self):
         with self.assertRaises(IndexError):
@@ -1709,6 +1885,16 @@ class StructureFieldTestCase(unittest.TestCase):
         field['F'] = {'F_1': 52}
         self.assertEqual(self._def, field)
 
+    def test_const_eq(self):
+        field = _create_field(self._tc, self._create_fc(self._tc))
+        field['A'] = -1872
+        field['B'] = 'salut'
+        field['C'] = 17.5
+        field['D'] = 16497
+        field['E'] = {}
+        field['F'] = {'F_1': 52}
+        self.assertEqual(self._def_const, field)
+
     def test_eq_invalid_type(self):
         self.assertNotEqual(self._def, 23)
 
@@ -1772,6 +1958,10 @@ class StructureFieldTestCase(unittest.TestCase):
         self._def['C'] = -18.47
         self.assertEqual(self._def['C'], -18.47)
 
+    def test_const_setitem(self):
+        with self.assertRaises(TypeError):
+            self._def_const['A'] = 134679
+
     def test_setitem_int_field(self):
         int_fc = self._tc.create_signed_integer_field_class(32)
         int_field = _create_field(self._tc, int_fc)
@@ -1804,6 +1994,9 @@ class StructureFieldTestCase(unittest.TestCase):
     def test_member_at_index(self):
         self.assertEqual(self._def.member_at_index(1), 'salut')
 
+    def test_const_member_at_index(self):
+        self.assertEqual(self._def_const.member_at_index(1), 'salut')
+
     def test_iter(self):
         orig_values = {
             'A': -1872,
@@ -1870,6 +2063,10 @@ class StructureFieldTestCase(unittest.TestCase):
 
 
 class OptionFieldTestCase(unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.value = {'opt_field': 'hiboux'}
+
     def _create_fc(self, tc):
         fc = tc.create_option_field_class(tc.create_string_field_class())
         top_fc = tc.create_structure_field_class()
@@ -1880,12 +2077,24 @@ class OptionFieldTestCase(unittest.TestCase):
         self._tc = get_default_trace_class()
         fld = _create_field(self._tc, self._create_fc(self._tc))
         self._def = fld['opt_field']
+        self._def_value = 'hiboux'
+        self._def_const = _create_const_field(
+            self._tc, self._create_fc(self._tc), self._const_value_setter
+        )['opt_field']
 
     def test_value_prop(self):
         self._def.value = 'hiboux'
         self.assertEqual(self._def.field, 'hiboux')
+        self.assertIs(type(self._def), bt2._OptionField)
+        self.assertIs(type(self._def.field), bt2._StringField)
         self.assertTrue(self._def.has_field)
 
+    def test_const_value_prop(self):
+        self.assertEqual(self._def_const.field, 'hiboux')
+        self.assertIs(type(self._def_const), bt2._OptionFieldConst)
+        self.assertIs(type(self._def_const.field), bt2._StringFieldConst)
+        self.assertTrue(self._def_const.has_field)
+
     def test_has_field_prop_true(self):
         self._def.has_field = True
         self.assertTrue(self._def.has_field)
@@ -1912,6 +2121,13 @@ class OptionFieldTestCase(unittest.TestCase):
         field = self._def.field
         self.assertIsNone(field)
 
+    def test_const_field_prop(self):
+        with self.assertRaises(AttributeError):
+            self._def_const.has_field = False
+
+        self.assertEqual(self._def_const, self._def_value)
+        self.assertTrue(self._def_const.has_field)
+
     def test_field_prop_existing_then_none(self):
         self._def.value = 'meow'
         field = self._def.field
@@ -1927,6 +2143,13 @@ class OptionFieldTestCase(unittest.TestCase):
         self._def.value = 'walk'
         self.assertEqual(self._def, field)
 
+    def test_const_eq(self):
+        field = _create_field(self._tc, self._create_fc(self._tc))
+        field = field['opt_field']
+        field.value = 'hiboux'
+        self.assertEqual(self._def_const, field)
+        self.assertEqual(self._def_const, self._def_value)
+
     def test_eq_invalid_type(self):
         self._def.value = 'gerry'
         self.assertNotEqual(self._def, 23)
@@ -1941,6 +2164,11 @@ class OptionFieldTestCase(unittest.TestCase):
 
 
 class VariantFieldTestCase(unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.selected_option_index = 3
+        field.value = 1334
+
     def _create_fc(self, tc):
         ft0 = tc.create_signed_integer_field_class(32)
         ft1 = tc.create_string_field_class()
@@ -1960,6 +2188,15 @@ class VariantFieldTestCase(unittest.TestCase):
         fld = _create_field(self._tc, self._create_fc(self._tc))
         self._def = fld['variant_field']
 
+        self._def_value = 1334
+        self._def_selected_index = 3
+        const_fc = self._create_fc(self._tc)['variant_field']
+
+        fld_const = _create_const_field(
+            self._tc, const_fc.field_class, self._const_value_setter
+        )
+        self._def_const = fld_const
+
     def test_bool_op(self):
         self._def.selected_option_index = 2
         self._def.value = -17.34
@@ -1978,14 +2215,27 @@ class VariantFieldTestCase(unittest.TestCase):
         with self.assertRaises(IndexError):
             self._def.selected_option_index = -1
 
+    def test_const_selected_option_index(self):
+        with self.assertRaises(AttributeError):
+            self._def_const.selected_option_index = 2
+        self.assertEqual(self._def_const.selected_option_index, 3)
+
     def test_selected_option(self):
         self._def.selected_option_index = 2
         self._def.value = -17.34
         self.assertEqual(self._def.selected_option, -17.34)
+        self.assertEqual(type(self._def.selected_option), bt2._RealField)
 
         self._def.selected_option_index = 3
         self._def.value = 1921
         self.assertEqual(self._def.selected_option, 1921)
+        self.assertEqual(type(self._def.selected_option), bt2._SignedIntegerField)
+
+    def test_const_selected_option(self):
+        self.assertEqual(self._def_const.selected_option, 1334)
+        self.assertEqual(
+            type(self._def_const.selected_option), bt2._SignedIntegerFieldConst
+        )
 
     def test_eq(self):
         field = _create_field(self._tc, self._create_fc(self._tc))
@@ -1996,6 +2246,13 @@ class VariantFieldTestCase(unittest.TestCase):
         self._def.value = 1774
         self.assertEqual(self._def, field)
 
+    def test_const_eq(self):
+        field = _create_field(self._tc, self._create_fc(self._tc))
+        field = field['variant_field']
+        field.selected_option_index = 3
+        field.value = 1334
+        self.assertEqual(self._def_const, field)
+
     def test_len(self):
         self.assertEqual(len(self._def), 4)
 
index b1dbd38af9b7ed33cc5b442d7f05dcb96f3a5132..1d883eea061aa78654c1cd84440cf63bf70afee9 100644 (file)
 
 import unittest
 import bt2
-from utils import get_default_trace_class
+from utils import get_default_trace_class, TestOutputPortMessageIterator
+from bt2 import value as bt2_value
+from bt2 import field_class as bt2_field_class
+
+
+def _create_stream(tc, ctx_field_classes):
+    packet_context_fc = tc.create_structure_field_class()
+    for name, fc in ctx_field_classes:
+        packet_context_fc.append_member(name, fc)
+
+    trace = tc()
+    stream_class = tc.create_stream_class(
+        packet_context_field_class=packet_context_fc, supports_packets=True
+    )
+
+    stream = trace.create_stream(stream_class)
+    return stream
+
+
+def _create_const_field_class(tc, field_class, value_setter_fn):
+    field_name = 'const field'
+
+    class MyIter(bt2._UserMessageIterator):
+        def __init__(self, self_port_output):
+            nonlocal field_class
+            nonlocal value_setter_fn
+            stream = _create_stream(tc, [(field_name, field_class)])
+            packet = stream.create_packet()
+
+            value_setter_fn(packet.context_field[field_name])
+
+            self._msgs = [
+                self._create_stream_beginning_message(stream),
+                self._create_packet_beginning_message(packet),
+            ]
+
+        def __next__(self):
+            if len(self._msgs) == 0:
+                raise StopIteration
+
+            return self._msgs.pop(0)
+
+    class MySrc(bt2._UserSourceComponent, message_iterator_class=MyIter):
+        def __init__(self, params, obj):
+            self._add_output_port('out', params)
+
+    graph = bt2.Graph()
+    src_comp = graph.add_component(MySrc, 'my_source', None)
+    msg_iter = TestOutputPortMessageIterator(graph, src_comp.output_ports['out'])
+
+    # Ignore first message, stream beginning
+    _ = next(msg_iter)
+    packet_beg_msg = next(msg_iter)
+
+    return packet_beg_msg.packet.context_field[field_name].cls
 
 
 class _TestFieldClass:
     def test_create_user_attributes(self):
         fc = self._create_default_field_class(user_attributes={'salut': 23})
         self.assertEqual(fc.user_attributes, {'salut': 23})
+        self.assertIs(type(fc.user_attributes), bt2_value.MapValue)
+
+    def test_const_create_user_attributes(self):
+        fc = self._create_default_const_field_class(user_attributes={'salut': 23})
+        self.assertEqual(fc.user_attributes, {'salut': 23})
+        self.assertIs(type(fc.user_attributes), bt2_value._MapValueConst)
 
     def test_create_invalid_user_attributes(self):
         with self.assertRaises(TypeError):
@@ -36,12 +96,22 @@ class _TestFieldClass:
 
 
 class BoolFieldClassTestCase(_TestFieldClass, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field = False
+
     def _create_default_field_class(self, **kwargs):
         tc = get_default_trace_class()
         return tc.create_bool_field_class(**kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_bool_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     def setUp(self):
         self._fc = self._create_default_field_class()
+        self._fc_const = self._create_default_const_field_class()
 
     def test_create_default(self):
         self.assertIsNotNone(self._fc)
@@ -49,6 +119,10 @@ class BoolFieldClassTestCase(_TestFieldClass, unittest.TestCase):
 
 
 class BitArrayFieldClassTestCase(_TestFieldClass, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field = []
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_bit_array_field_class(*args, **kwargs)
@@ -56,6 +130,11 @@ class BitArrayFieldClassTestCase(_TestFieldClass, unittest.TestCase):
     def _create_default_field_class(self, **kwargs):
         return self._create_field_class(17, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_bit_array_field_class(17, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     def setUp(self):
         self._fc = self._create_default_field_class()
 
@@ -131,28 +210,55 @@ class _TestIntegerFieldClassProps:
 class SignedIntegerFieldClassTestCase(
     _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
 ):
+    @staticmethod
+    def _const_value_setter(field):
+        field = -18
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_signed_integer_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_signed_integer_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
 
 class UnsignedIntegerFieldClassTestCase(
     _TestIntegerFieldClassProps, _TestFieldClass, unittest.TestCase
 ):
+    @staticmethod
+    def _const_value_setter(field):
+        field = 18
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_unsigned_integer_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_signed_integer_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
 
 class RealFieldClassTestCase(_TestFieldClass, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field = -18
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_real_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_real_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
     def test_create_default(self):
@@ -182,6 +288,7 @@ class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
     def setUp(self):
         self._spec_set_up()
         self._fc = self._create_default_field_class()
+        self._fc_const = self._create_default_const_field_class()
 
     def test_create_from_invalid_type(self):
         with self.assertRaises(TypeError):
@@ -193,6 +300,10 @@ class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
         self.assertEqual(mapping.label, 'hello')
         self.assertEqual(mapping.ranges, self._ranges1)
 
+    def test_const_add_mapping(self):
+        with self.assertRaises(AttributeError):
+            self._fc_const.add_mapping('hello', self._ranges1)
+
     def test_add_mapping_simple_kwargs(self):
         self._fc.add_mapping(label='hello', ranges=self._ranges1)
         mapping = self._fc['hello']
@@ -229,6 +340,10 @@ class _EnumerationFieldClassTestCase(_TestIntegerFieldClassProps):
         self.assertEqual(self._fc['e'].label, 'e')
         self.assertEqual(self._fc['e'].ranges, self._ranges3)
 
+    def test_const_iadd(self):
+        with self.assertRaises(TypeError):
+            self._fc_const += [('d', self._ranges2), ('e', self._ranges3)]
+
     def test_bool_op(self):
         self.assertFalse(self._fc)
         self._fc.add_mapping('a', self._ranges1)
@@ -282,10 +397,19 @@ class UnsignedEnumerationFieldClassTestCase(
         self._inval_ranges = bt2.SignedIntegerRangeSet([(-8, -5), (48, 1928)])
         self._value_in_range_1_and_3 = 20
 
+    @staticmethod
+    def _const_value_setter(field):
+        field = 0
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_unsigned_enumeration_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_unsigned_enumeration_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
 
@@ -299,18 +423,36 @@ class SignedEnumerationFieldClassTestCase(
         self._inval_ranges = bt2.UnsignedIntegerRangeSet([(8, 16), (48, 99)])
         self._value_in_range_1_and_3 = -7
 
+    @staticmethod
+    def _const_value_setter(field):
+        field = 0
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_signed_enumeration_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_signed_enumeration_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
 
 class StringFieldClassTestCase(_TestFieldClass, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field = 'chaine'
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_string_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_string_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
     def setUp(self):
@@ -325,6 +467,7 @@ class _TestElementContainer:
     def setUp(self):
         self._tc = get_default_trace_class()
         self._fc = self._create_default_field_class()
+        self._fc_const = self._create_default_const_field_class()
 
     def test_create_default(self):
         self.assertIsNotNone(self._fc)
@@ -360,6 +503,24 @@ class _TestElementContainer:
             self._append_element_method(self._fc, 'yes', sub_fc1)
             self._append_element_method(self._fc, 'yes', sub_fc2)
 
+    def test_attr_field_class(self):
+        int_field_class = self._tc.create_signed_integer_field_class(32)
+        self._append_element_method(self._fc, 'int32', int_field_class)
+        field_class = self._fc['int32'].field_class
+
+        self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClass)
+
+    def test_const_attr_field_class(self):
+        int_field_class = self._tc.create_signed_integer_field_class(32)
+        self._append_element_method(self._fc, 'int32', int_field_class)
+        field_class = self._fc['int32'].field_class
+        const_fc = _create_const_field_class(
+            self._tc, self._fc, self._const_value_setter
+        )
+        field_class = const_fc['int32'].field_class
+
+        self.assertIs(type(field_class), bt2_field_class._SignedIntegerFieldClassConst)
+
     def test_iadd(self):
         a_field_class = self._tc.create_real_field_class()
         b_field_class = self._tc.create_signed_integer_field_class(17)
@@ -386,6 +547,11 @@ class _TestElementContainer:
         self.assertEqual(self._fc['e_struct'].field_class.addr, e_field_class.addr)
         self.assertEqual(self._fc['e_struct'].name, 'e_struct')
 
+    def test_const_iadd(self):
+        a_field_class = self._tc.create_real_field_class()
+        with self.assertRaises(TypeError):
+            self._fc_const += a_field_class
+
     def test_bool_op(self):
         self.assertFalse(self._fc)
         self._append_element_method(self._fc, 'a', self._tc.create_string_field_class())
@@ -470,6 +636,8 @@ class _TestElementContainer:
             user_attributes={'salut': 23},
         )
         self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
+        self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
+        self.assertIs(type(self._fc['c'].user_attributes), bt2_value.MapValue)
 
     def test_invalid_user_attributes(self):
         with self.assertRaises(TypeError):
@@ -493,17 +661,57 @@ class StructureFieldClassTestCase(
     _append_element_method = staticmethod(bt2._StructureFieldClass.append_member)
     _at_index_method = staticmethod(bt2._StructureFieldClass.member_at_index)
 
+    @staticmethod
+    def _const_value_setter(field):
+        field.value = {}
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_structure_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_structure_field_class(*args, **kwargs)
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
+    def test_const_member_field_class(self):
+        def _real_value_setter(field):
+            field.value = {'real': 0}
+
+        tc = get_default_trace_class()
+        fc = tc.create_structure_field_class()
+        member_fc = self._tc.create_real_field_class()
+        fc.append_member('real', member_fc)
+        const_fc = _create_const_field_class(tc, fc, _real_value_setter)
+
+        self.assertIs(
+            type(const_fc['real'].field_class), bt2_field_class._RealFieldClassConst
+        )
+
+    def test_member_field_class(self):
+        tc = get_default_trace_class()
+        fc = tc.create_structure_field_class()
+        member_fc = self._tc.create_real_field_class()
+        fc.append_member('real', member_fc)
+
+        self.assertIs(type(fc['real'].field_class), bt2_field_class._RealFieldClass)
+
 
 class OptionFieldClassTestCase(_TestFieldClass, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field.has_field = True
+        field.value = 12
+
     def _create_default_field_class(self, *args, **kwargs):
         return self._tc.create_option_field_class(self._content_fc, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        fc = self._tc.create_option_field_class(self._content_fc, **kwargs)
+        return _create_const_field_class(self._tc, fc, self._const_value_setter)
+
     def setUp(self):
         self._tc = get_default_trace_class()
         self._content_fc = self._tc.create_signed_integer_field_class(23)
@@ -515,6 +723,16 @@ class OptionFieldClassTestCase(_TestFieldClass, unittest.TestCase):
         self.assertIsNone(fc.selector_field_path, None)
         self.assertEqual(len(fc.user_attributes), 0)
 
+    def test_attr_field_class(self):
+        fc = self._create_default_field_class()
+        self.assertIs(type(fc.field_class), bt2_field_class._SignedIntegerFieldClass)
+
+    def test_const_attr_field_class(self):
+        fc = self._create_default_const_field_class()
+        self.assertIs(
+            type(fc.field_class), bt2_field_class._SignedIntegerFieldClassConst
+        )
+
     def _create_field_class_for_field_path_test(self):
         fc = self._create_default_field_class(selector_fc=self._tag_fc)
 
@@ -586,19 +804,54 @@ class VariantFieldClassWithoutSelectorTestCase(
         bt2._VariantFieldClassWithoutSelector.option_at_index
     )
 
+    @staticmethod
+    def _const_value_setter(variant_field):
+        variant_field.selected_option_index = 0
+        variant_field.value = 12
+
     def _create_field_class(self, *args, **kwargs):
         tc = get_default_trace_class()
         return tc.create_variant_field_class(*args, **kwargs)
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        tc = get_default_trace_class()
+        fc = tc.create_variant_field_class(*args, **kwargs)
+        int_field_class = self._tc.create_signed_integer_field_class(32)
+        fc.append_option('int32', int_field_class)
+
+        return _create_const_field_class(tc, fc, self._const_value_setter)
+
     _create_default_field_class = _create_field_class
 
 
 class _VariantFieldClassWithSelectorTestCase:
+    @staticmethod
+    def _const_value_setter(field):
+        field['variant'].selected_option_index = 0
+        field['variant'] = 12
+
     def _create_default_field_class(self, *args, **kwargs):
         return self._tc.create_variant_field_class(
             *args, selector_fc=self._selector_fc, **kwargs
         )
 
+    def _create_default_const_field_class(self, *args, **kwargs):
+        # Create a struct to contain the variant and its selector else we can't
+        # create the non-const field necessary to get the the const field_class
+        struct_fc = self._tc.create_structure_field_class()
+        struct_fc.append_member('selecteux', self._selector_fc)
+        variant_fc = self._tc.create_variant_field_class(
+            *args, selector_fc=self._selector_fc
+        )
+        variant_fc.append_option(
+            'a', self._tc.create_signed_integer_field_class(32), self._ranges1
+        )
+        struct_fc.append_member('variant', variant_fc, **kwargs)
+
+        return _create_const_field_class(self._tc, struct_fc, self._const_value_setter)[
+            'variant'
+        ].field_class
+
     def setUp(self):
         self._tc = get_default_trace_class()
         self._spec_set_up()
@@ -616,6 +869,11 @@ class _VariantFieldClassWithSelectorTestCase:
         self.assertEqual(opt.name, 'str')
         self.assertEqual(opt.ranges.addr, self._ranges1.addr)
 
+    def test_const_append(self):
+        fc_const = self._create_default_const_field_class()
+        with self.assertRaises(AttributeError):
+            fc_const.append_option('str', str_field_class, self._ranges1)
+
     def test_append_element_kwargs(self):
         int_field_class = self._tc.create_signed_integer_field_class(32)
         self._fc.append_option(
@@ -664,6 +922,11 @@ class _VariantFieldClassWithSelectorTestCase:
             user_attributes={'salut': 23},
         )
         self.assertEqual(self._fc['c'].user_attributes, {'salut': 23})
+        self.assertIs(type(self._fc.user_attributes), bt2_value.MapValue)
+
+    def test_const_user_attributes(self):
+        fc_const = self._create_default_const_field_class()
+        self.assertIs(type(fc_const.user_attributes), bt2_value._MapValueConst)
 
     def test_invalid_user_attributes(self):
         with self.assertRaises(TypeError):
@@ -704,6 +967,12 @@ class _VariantFieldClassWithSelectorTestCase:
         self.assertEqual(self._fc['d_enum'].name, 'd_enum')
         self.assertEqual(self._fc['d_enum'].ranges, self._ranges3)
 
+    def test_const_iadd(self):
+        fc_const = self._create_default_const_field_class()
+        a_field_class = self._tc.create_real_field_class()
+        with self.assertRaises(TypeError):
+            fc_const += [('a_float', a_field_class, self._ranges1)]
+
     def test_bool_op(self):
         self.assertFalse(self._fc)
         self._fc.append_option('a', self._tc.create_string_field_class(), self._ranges1)
@@ -726,6 +995,20 @@ class _VariantFieldClassWithSelectorTestCase:
         self.assertEqual(self._fc['b'].name, 'b')
         self.assertEqual(self._fc['b'].ranges.addr, self._ranges2.addr)
 
+    def test_option_field_class(self):
+        a_fc = self._tc.create_signed_integer_field_class(32)
+        self._fc.append_option('a', a_fc, self._ranges1)
+        self.assertIs(
+            type(self._fc['a'].field_class), bt2_field_class._SignedIntegerFieldClass
+        )
+
+    def test_const_option_field_class(self):
+        fc_const = self._create_default_const_field_class()
+        self.assertIs(
+            type(fc_const['a'].field_class),
+            bt2_field_class._SignedIntegerFieldClassConst,
+        )
+
     def test_getitem_invalid_key_type(self):
         with self.assertRaises(TypeError):
             self._fc[0]
@@ -880,7 +1163,32 @@ class VariantFieldClassWithSignedSelectorTestCase(
         self._selector_fc = self._tc.create_signed_integer_field_class()
 
 
-class StaticArrayFieldClassTestCase(unittest.TestCase):
+class _ArrayFieldClassTestCase:
+    def test_attr_element_field_class(self):
+        fc = self._create_array()
+        self.assertIs(
+            type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClass
+        )
+
+    def test_const_attr_element_field_class(self):
+        fc = self._create_const_array()
+        self.assertIs(
+            type(fc.element_field_class), bt2_field_class._SignedIntegerFieldClassConst
+        )
+
+
+class StaticArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field = []
+
+    def _create_array(self):
+        return self._tc.create_static_array_field_class(self._elem_fc, 45)
+
+    def _create_const_array(self):
+        fc = self._tc.create_static_array_field_class(self._elem_fc, 45)
+        return _create_const_field_class(self._tc, fc, self._const_value_setter)
+
     def setUp(self):
         self._tc = get_default_trace_class()
         self._elem_fc = self._tc.create_signed_integer_field_class(23)
@@ -908,7 +1216,18 @@ class StaticArrayFieldClassTestCase(unittest.TestCase):
             )
 
 
-class DynamicArrayFieldClassTestCase(unittest.TestCase):
+class DynamicArrayFieldClassTestCase(_ArrayFieldClassTestCase, unittest.TestCase):
+    @staticmethod
+    def _const_value_setter(field):
+        field = []
+
+    def _create_array(self):
+        return self._tc.create_dynamic_array_field_class(self._elem_fc)
+
+    def _create_const_array(self):
+        fc = self._tc.create_dynamic_array_field_class(self._elem_fc)
+        return _create_const_field_class(self._tc, fc, self._const_value_setter)
+
     def setUp(self):
         self._tc = get_default_trace_class()
         self._elem_fc = self._tc.create_signed_integer_field_class(23)
index 1d3f9da27be726606de2f635ebc2056faa0ba8a2..2ad2ac1f4395b0c8569910d12839558c34eac97a 100644 (file)
@@ -328,16 +328,16 @@ class GraphTestCase(unittest.TestCase):
                 msg = next(comp_self._msg_iter)
 
                 if comp_self._at == 0:
-                    self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+                    self.assertIs(type(msg), bt2._StreamBeginningMessageConst)
                 elif comp_self._at == 1:
-                    self.assertIsInstance(msg, bt2._PacketBeginningMessage)
+                    self.assertIs(type(msg), bt2._PacketBeginningMessageConst)
                 elif comp_self._at >= 2 and comp_self._at <= 6:
-                    self.assertIsInstance(msg, bt2._EventMessage)
+                    self.assertIs(type(msg), bt2._EventMessageConst)
                     self.assertEqual(msg.event.cls.name, 'salut')
                 elif comp_self._at == 7:
-                    self.assertIsInstance(msg, bt2._PacketEndMessage)
+                    self.assertIs(type(msg), bt2._PacketEndMessageConst)
                 elif comp_self._at == 8:
-                    self.assertIsInstance(msg, bt2._StreamEndMessage)
+                    self.assertIs(type(msg), bt2._StreamEndMessageConst)
 
                 comp_self._at += 1
 
@@ -428,11 +428,11 @@ class GraphTestCase(unittest.TestCase):
             def _user_consume(comp_self):
                 msg = next(comp_self._msg_iter)
                 if comp_self._at == 0:
-                    self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+                    self.assertIs(type(msg), bt2._StreamBeginningMessageConst)
                 elif comp_self._at == 1:
-                    self.assertIsInstance(msg, bt2._PacketBeginningMessage)
+                    self.assertIs(type(msg), bt2._PacketBeginningMessageConst)
                 elif comp_self._at == 2:
-                    self.assertIsInstance(msg, bt2._EventMessage)
+                    self.assertIs(type(msg), bt2._EventMessageConst)
                     raise bt2.TryAgain
                 else:
                     pass
@@ -484,11 +484,11 @@ class GraphTestCase(unittest.TestCase):
             def _user_consume(comp_self):
                 msg = next(comp_self._msg_iter)
                 if comp_self._at == 0:
-                    self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+                    self.assertIs(type(msg), bt2._StreamBeginningMessageConst)
                 elif comp_self._at == 1:
-                    self.assertIsInstance(msg, bt2._PacketBeginningMessage)
+                    self.assertIs(type(msg), bt2._PacketBeginningMessageConst)
                 elif comp_self._at == 2:
-                    self.assertIsInstance(msg, bt2._EventMessage)
+                    self.assertIs(type(msg), bt2._EventMessageConst)
                 elif comp_self._at == 3:
                     nonlocal raised_in_sink
                     raised_in_sink = True
index 5a3c2c1d671c6a27ca06cdc9828dcec322bd08b8..b2ad1a426d791ef6b677681dfecd2478ed6a5a62 100644 (file)
 
 import unittest
 import bt2
+import utils
 from utils import TestOutputPortMessageIterator
+from bt2 import clock_snapshot as bt2_clock_snapshot
+from bt2 import event as bt2_event
+from bt2 import event_class as bt2_event_class
+from bt2 import field as bt2_field
+from bt2 import packet as bt2_packet
+from bt2 import stream as bt2_stream
+from bt2 import stream_class as bt2_stream_class
+from bt2 import trace as bt2_trace
+from bt2 import trace_class as bt2_trace_class
 
 
 class AllMessagesTestCase(unittest.TestCase):
@@ -41,14 +51,17 @@ class AllMessagesTestCase(unittest.TestCase):
                             msg = self._create_stream_beginning_message(
                                 test_obj._stream
                             )
+                        test_obj.assertIs(type(msg), bt2._StreamBeginningMessage)
                     elif self._at == 1:
                         msg = self._create_packet_beginning_message(
                             test_obj._packet, self._at
                         )
+                        test_obj.assertIs(type(msg), bt2._PacketBeginningMessage)
                     elif self._at == 2:
                         msg = self._create_event_message(
                             test_obj._event_class, test_obj._packet, self._at
                         )
+                        test_obj.assertIs(type(msg), bt2._EventMessage)
                     elif self._at == 3:
                         msg = self._create_message_iterator_inactivity_message(
                             test_obj._clock_class, self._at
@@ -57,14 +70,17 @@ class AllMessagesTestCase(unittest.TestCase):
                         msg = self._create_discarded_events_message(
                             test_obj._stream, 890, self._at, self._at
                         )
+                        test_obj.assertIs(type(msg), bt2._DiscardedEventsMessage)
                     elif self._at == 5:
                         msg = self._create_packet_end_message(
                             test_obj._packet, self._at
                         )
+                        test_obj.assertIs(type(msg), bt2._PacketEndMessage)
                     elif self._at == 6:
                         msg = self._create_discarded_packets_message(
                             test_obj._stream, 678, self._at, self._at
                         )
+                        test_obj.assertIs(type(msg), bt2._DiscardedPacketsMessage)
                     elif self._at == 7:
                         if self._with_stream_msgs_clock_snapshots:
                             msg = self._create_stream_end_message(
@@ -72,6 +88,7 @@ class AllMessagesTestCase(unittest.TestCase):
                             )
                         else:
                             msg = self._create_stream_end_message(test_obj._stream)
+                        test_obj.assertIs(type(msg), bt2._StreamEndMessage)
                     elif self._at >= 8:
                         raise bt2.Stop
                 else:
@@ -128,7 +145,16 @@ class AllMessagesTestCase(unittest.TestCase):
                 payload_fc = tc.create_structure_field_class()
                 payload_fc += [('my_int', my_int_fc)]
 
-                ec = sc.create_event_class(name='salut', payload_field_class=payload_fc)
+                # Create specific context field class
+                my_int_fc = tc.create_signed_integer_field_class(32)
+                specific_fc = tc.create_structure_field_class()
+                specific_fc += [('my_int', my_int_fc)]
+
+                ec = sc.create_event_class(
+                    name='salut',
+                    payload_field_class=payload_fc,
+                    specific_context_field_class=specific_fc,
+                )
 
                 trace = tc()
                 stream = trace.create_stream(sc)
@@ -154,24 +180,58 @@ class AllMessagesTestCase(unittest.TestCase):
 
         for i, msg in enumerate(self._msg_iter):
             if i == 0:
-                self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+                self.assertIs(type(msg), bt2._StreamBeginningMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
                 self.assertEqual(msg.stream.addr, self._stream.addr)
                 self.assertIsInstance(
                     msg.default_clock_snapshot, bt2._UnknownClockSnapshot
                 )
             elif i == 1:
-                self.assertIsInstance(msg, bt2._PacketBeginningMessage)
+                self.assertIs(type(msg), bt2._PacketBeginningMessageConst)
+                self.assertIs(type(msg.packet), bt2_packet._PacketConst)
+                self.assertIs(
+                    type(msg.default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
                 self.assertEqual(msg.packet.addr, self._packet.addr)
                 self.assertEqual(msg.default_clock_snapshot.value, i)
             elif i == 2:
-                self.assertIsInstance(msg, bt2._EventMessage)
+                self.assertIs(type(msg), bt2._EventMessageConst)
+                self.assertIs(type(msg.event), bt2_event._EventConst)
+                self.assertIs(
+                    type(msg.default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
+                self.assertIs(
+                    type(msg.event.payload_field), bt2_field._StructureFieldConst
+                )
+                self.assertIs(
+                    type(msg.event.payload_field['my_int']),
+                    bt2_field._SignedIntegerFieldConst,
+                )
+
                 self.assertEqual(msg.event.cls.addr, self._event_class.addr)
                 self.assertEqual(msg.default_clock_snapshot.value, i)
             elif i == 3:
-                self.assertIsInstance(msg, bt2._MessageIteratorInactivityMessage)
+                self.assertIs(type(msg), bt2._MessageIteratorInactivityMessageConst)
+                self.assertIs(
+                    type(msg.default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
                 self.assertEqual(msg.default_clock_snapshot.value, i)
             elif i == 4:
-                self.assertIsInstance(msg, bt2._DiscardedEventsMessage)
+                self.assertIs(type(msg), bt2._DiscardedEventsMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
+                self.assertIs(type(msg.stream.cls), bt2_stream_class._StreamClassConst)
+                self.assertIs(
+                    type(msg.beginning_default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
+                self.assertIs(
+                    type(msg.end_default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
+
                 self.assertEqual(msg.stream.addr, self._stream.addr)
                 self.assertEqual(msg.count, 890)
                 self.assertEqual(
@@ -180,11 +240,29 @@ class AllMessagesTestCase(unittest.TestCase):
                 self.assertEqual(msg.beginning_default_clock_snapshot.value, i)
                 self.assertEqual(msg.end_default_clock_snapshot.value, i)
             elif i == 5:
-                self.assertIsInstance(msg, bt2._PacketEndMessage)
+                self.assertIs(type(msg), bt2._PacketEndMessageConst)
+                self.assertIs(type(msg.packet), bt2_packet._PacketConst)
+                self.assertIs(
+                    type(msg.default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
                 self.assertEqual(msg.packet.addr, self._packet.addr)
                 self.assertEqual(msg.default_clock_snapshot.value, i)
             elif i == 6:
-                self.assertIsInstance(msg, bt2._DiscardedPacketsMessage)
+                self.assertIs(type(msg), bt2._DiscardedPacketsMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
+                self.assertIs(type(msg.stream.trace), bt2_trace._TraceConst)
+                self.assertIs(
+                    type(msg.stream.trace.cls), bt2_trace_class._TraceClassConst
+                )
+                self.assertIs(
+                    type(msg.beginning_default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
+                self.assertIs(
+                    type(msg.end_default_clock_snapshot),
+                    bt2_clock_snapshot._ClockSnapshotConst,
+                )
                 self.assertEqual(msg.stream.addr, self._stream.addr)
                 self.assertEqual(msg.count, 678)
                 self.assertEqual(
@@ -193,10 +271,11 @@ class AllMessagesTestCase(unittest.TestCase):
                 self.assertEqual(msg.beginning_default_clock_snapshot.value, i)
                 self.assertEqual(msg.end_default_clock_snapshot.value, i)
             elif i == 7:
-                self.assertIsInstance(msg, bt2._StreamEndMessage)
+                self.assertIs(type(msg), bt2._StreamEndMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
                 self.assertEqual(msg.stream.addr, self._stream.addr)
-                self.assertIsInstance(
-                    msg.default_clock_snapshot, bt2._UnknownClockSnapshot
+                self.assertIs(
+                    type(msg.default_clock_snapshot), bt2._UnknownClockSnapshot
                 )
             else:
                 raise Exception
@@ -210,24 +289,30 @@ class AllMessagesTestCase(unittest.TestCase):
 
         for i, msg in enumerate(self._msg_iter):
             if i == 0:
-                self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+                self.assertIsInstance(msg, bt2._StreamBeginningMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
                 self.assertEqual(msg.stream.addr, self._stream.addr)
                 with self.assertRaisesRegex(
                     ValueError, 'stream class has no default clock class'
                 ):
                     msg.default_clock_snapshot
             elif i == 1:
-                self.assertIsInstance(msg, bt2._PacketBeginningMessage)
+                self.assertIsInstance(msg, bt2._PacketBeginningMessageConst)
+                self.assertIs(type(msg.packet), bt2_packet._PacketConst)
                 self.assertEqual(msg.packet.addr, self._packet.addr)
             elif i == 2:
-                self.assertIsInstance(msg, bt2._EventMessage)
+                self.assertIsInstance(msg, bt2._EventMessageConst)
+                self.assertIs(type(msg.event), bt2_event._EventConst)
+                self.assertIs(type(msg.event.cls), bt2_event_class._EventClassConst)
                 self.assertEqual(msg.event.cls.addr, self._event_class.addr)
                 with self.assertRaisesRegex(
                     ValueError, 'stream class has no default clock class'
                 ):
                     msg.default_clock_snapshot
             elif i == 3:
-                self.assertIsInstance(msg, bt2._DiscardedEventsMessage)
+                self.assertIsInstance(msg, bt2._DiscardedEventsMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
+                self.assertIs(type(msg.stream.cls), bt2_stream_class._StreamClassConst)
                 self.assertEqual(msg.stream.addr, self._stream.addr)
                 self.assertEqual(msg.count, 890)
                 self.assertIsNone(msg.stream.cls.default_clock_class)
@@ -242,10 +327,16 @@ class AllMessagesTestCase(unittest.TestCase):
                 ):
                     msg.end_default_clock_snapshot
             elif i == 4:
-                self.assertIsInstance(msg, bt2._PacketEndMessage)
+                self.assertIsInstance(msg, bt2._PacketEndMessageConst)
                 self.assertEqual(msg.packet.addr, self._packet.addr)
+                self.assertIs(type(msg.packet), bt2_packet._PacketConst)
             elif i == 5:
-                self.assertIsInstance(msg, bt2._DiscardedPacketsMessage)
+                self.assertIsInstance(msg, bt2._DiscardedPacketsMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
+                self.assertIs(type(msg.stream.cls), bt2_stream_class._StreamClassConst)
+                self.assertIs(
+                    type(msg.stream.cls.trace_class), bt2_trace_class._TraceClassConst
+                )
                 self.assertEqual(msg.stream.addr, self._stream.addr)
                 self.assertEqual(msg.count, 678)
                 self.assertIsNone(msg.stream.cls.default_clock_class)
@@ -260,7 +351,8 @@ class AllMessagesTestCase(unittest.TestCase):
                 ):
                     msg.end_default_clock_snapshot
             elif i == 6:
-                self.assertIsInstance(msg, bt2._StreamEndMessage)
+                self.assertIsInstance(msg, bt2._StreamEndMessageConst)
+                self.assertIs(type(msg.stream), bt2_stream._StreamConst)
                 self.assertEqual(msg.stream.addr, self._stream.addr)
                 with self.assertRaisesRegex(
                     ValueError, 'stream class has no default clock class'
@@ -279,9 +371,37 @@ class AllMessagesTestCase(unittest.TestCase):
         msgs = list(self._msg_iter)
 
         msg_stream_beg = msgs[0]
-        self.assertIsInstance(msg_stream_beg, bt2._StreamBeginningMessage)
+        self.assertIsInstance(msg_stream_beg, bt2._StreamBeginningMessageConst)
+        self.assertIs(
+            type(msg_stream_beg.default_clock_snapshot),
+            bt2_clock_snapshot._ClockSnapshotConst,
+        )
         self.assertEqual(msg_stream_beg.default_clock_snapshot.value, 0)
 
         msg_stream_end = msgs[7]
-        self.assertIsInstance(msg_stream_end, bt2._StreamEndMessage)
+        self.assertIsInstance(msg_stream_end, bt2._StreamEndMessageConst)
+        self.assertIs(
+            type(msg_stream_end.default_clock_snapshot),
+            bt2_clock_snapshot._ClockSnapshotConst,
+        )
         self.assertEqual(msg_stream_end.default_clock_snapshot.value, 7)
+
+    def test_stream_beg_msg(self):
+        msg = utils.get_stream_beginning_message()
+        self.assertIs(type(msg.stream), bt2_stream._Stream)
+
+    def test_stream_end_msg(self):
+        msg = utils.get_stream_end_message()
+        self.assertIs(type(msg.stream), bt2_stream._Stream)
+
+    def test_packet_beg_msg(self):
+        msg = utils.get_packet_beginning_message()
+        self.assertIs(type(msg.packet), bt2_packet._Packet)
+
+    def test_packet_end_msg(self):
+        msg = utils.get_packet_end_message()
+        self.assertIs(type(msg.packet), bt2_packet._Packet)
+
+    def test_event_msg(self):
+        msg = utils.get_event_message()
+        self.assertIs(type(msg.event), bt2_event._Event)
index c317ae432f7764a7bfdea06f329d422341c163d2..40adfa60d847fc16e652540b9811114d23d3f833 100644 (file)
@@ -238,15 +238,15 @@ class UserMessageIteratorTestCase(unittest.TestCase):
 
         # Skip beginning messages.
         msg = next(it)
-        self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+        self.assertIs(type(msg), bt2._StreamBeginningMessageConst)
         msg = next(it)
-        self.assertIsInstance(msg, bt2._PacketBeginningMessage)
+        self.assertIs(type(msg), bt2._PacketBeginningMessageConst)
 
         msg_ev1 = next(it)
         msg_ev2 = next(it)
 
-        self.assertIsInstance(msg_ev1, bt2._EventMessage)
-        self.assertIsInstance(msg_ev2, bt2._EventMessage)
+        self.assertIs(type(msg_ev1), bt2._EventMessageConst)
+        self.assertIs(type(msg_ev2), bt2._EventMessageConst)
         self.assertEqual(msg_ev1.addr, msg_ev2.addr)
 
     @staticmethod
@@ -394,14 +394,14 @@ class UserMessageIteratorTestCase(unittest.TestCase):
         msg = None
         MySourceIter, graph = self._setup_seek_beginning_test(MySink)
         graph.run_once()
-        self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+        self.assertIs(type(msg), bt2._StreamBeginningMessageConst)
         graph.run_once()
-        self.assertIsInstance(msg, bt2._PacketBeginningMessage)
+        self.assertIs(type(msg), bt2._PacketBeginningMessageConst)
         do_seek_beginning = True
         graph.run_once()
         do_seek_beginning = False
         graph.run_once()
-        self.assertIsInstance(msg, bt2._StreamBeginningMessage)
+        self.assertIs(type(msg), bt2._StreamBeginningMessageConst)
 
     def test_seek_beginning_user_error(self):
         class MySink(bt2._UserSinkComponent):
index 52d5dc67bbcb9bd355010a85f3fa50507c2a5035..c83ea1481632cbb49d810218e5858301143a925d 100644 (file)
@@ -129,6 +129,54 @@ class PackageTestCase(unittest.TestCase):
     def test_has__DynamicArrayField(self):
         self._assert_in_bt2('_DynamicArrayField')
 
+    def test_has__BoolFieldConst(self):
+        self._assert_in_bt2('_BoolFieldConst')
+
+    def test_has__BitArrayFieldConst(self):
+        self._assert_in_bt2('_BitArrayFieldConst')
+
+    def test_has__IntegerFieldConst(self):
+        self._assert_in_bt2('_IntegerFieldConst')
+
+    def test_has__UnsignedIntegerFieldConst(self):
+        self._assert_in_bt2('_UnsignedIntegerFieldConst')
+
+    def test_has__SignedIntegerFieldConst(self):
+        self._assert_in_bt2('_SignedIntegerFieldConst')
+
+    def test_has__RealFieldConst(self):
+        self._assert_in_bt2('_RealFieldConst')
+
+    def test_has__EnumerationFieldConst(self):
+        self._assert_in_bt2('_EnumerationFieldConst')
+
+    def test_has__UnsignedEnumerationFieldConst(self):
+        self._assert_in_bt2('_UnsignedEnumerationFieldConst')
+
+    def test_has__SignedEnumerationFieldConst(self):
+        self._assert_in_bt2('_SignedEnumerationFieldConst')
+
+    def test_has__StringFieldConst(self):
+        self._assert_in_bt2('_StringFieldConst')
+
+    def test_has__StructureFieldConst(self):
+        self._assert_in_bt2('_StructureFieldConst')
+
+    def test_has__OptionFieldConst(self):
+        self._assert_in_bt2('_VariantFieldConst')
+
+    def test_has__VariantFieldConst(self):
+        self._assert_in_bt2('_VariantFieldConst')
+
+    def test_has__ArrayFieldConst(self):
+        self._assert_in_bt2('_ArrayFieldConst')
+
+    def test_has__StaticArrayFieldConst(self):
+        self._assert_in_bt2('_StaticArrayFieldConst')
+
+    def test_has__DynamicArrayFieldConst(self):
+        self._assert_in_bt2('_DynamicArrayFieldConst')
+
     def test_has_IntegerDisplayBase(self):
         self._assert_in_bt2('IntegerDisplayBase')
 
@@ -192,6 +240,66 @@ class PackageTestCase(unittest.TestCase):
     def test_has__DynamicArrayFieldClass(self):
         self._assert_in_bt2('_DynamicArrayFieldClass')
 
+    def test_has__BoolFieldClassConst(self):
+        self._assert_in_bt2('_BoolFieldClassConst')
+
+    def test_has__BitArrayFieldClassConst(self):
+        self._assert_in_bt2('_BitArrayFieldClassConst')
+
+    def test_has__IntegerFieldClassConst(self):
+        self._assert_in_bt2('_IntegerFieldClassConst')
+
+    def test_has__UnsignedIntegerFieldClassConst(self):
+        self._assert_in_bt2('_UnsignedIntegerFieldClassConst')
+
+    def test_has__SignedIntegerFieldClassConst(self):
+        self._assert_in_bt2('_SignedIntegerFieldClassConst')
+
+    def test_has__RealFieldClassConst(self):
+        self._assert_in_bt2('_RealFieldClassConst')
+
+    def test_has__EnumerationFieldClassConst(self):
+        self._assert_in_bt2('_EnumerationFieldClassConst')
+
+    def test_has__UnsignedEnumerationFieldClassConst(self):
+        self._assert_in_bt2('_UnsignedEnumerationFieldClassConst')
+
+    def test_has__SignedEnumerationFieldClassConst(self):
+        self._assert_in_bt2('_SignedEnumerationFieldClassConst')
+
+    def test_has__StringFieldClassConst(self):
+        self._assert_in_bt2('_StringFieldClassConst')
+
+    def test_has__StructureFieldClassConst(self):
+        self._assert_in_bt2('_StructureFieldClassConst')
+
+    def test_has__OptionFieldClassConst(self):
+        self._assert_in_bt2('_OptionFieldClassConst')
+
+    def test_has__VariantFieldClassConst(self):
+        self._assert_in_bt2('_VariantFieldClassConst')
+
+    def test_has__VariantFieldClassWithoutSelectorConst(self):
+        self._assert_in_bt2('_VariantFieldClassWithoutSelectorConst')
+
+    def test_has__VariantFieldClassWithSelectorConst(self):
+        self._assert_in_bt2('_VariantFieldClassWithSelectorConst')
+
+    def test_has__VariantFieldClassWithUnsignedSelectorConst(self):
+        self._assert_in_bt2('_VariantFieldClassWithUnsignedSelectorConst')
+
+    def test_has__VariantFieldClassWithSignedSelectorConst(self):
+        self._assert_in_bt2('_VariantFieldClassWithSignedSelectorConst')
+
+    def test_has__ArrayFieldClassConst(self):
+        self._assert_in_bt2('_ArrayFieldClassConst')
+
+    def test_has__StaticArrayFieldClassConst(self):
+        self._assert_in_bt2('_StaticArrayFieldClassConst')
+
+    def test_has__DynamicArrayFieldClassConst(self):
+        self._assert_in_bt2('_DynamicArrayFieldClassConst')
+
     def test_has_FieldPathScope(self):
         self._assert_in_bt2('FieldPathScope')
 
@@ -261,6 +369,30 @@ class PackageTestCase(unittest.TestCase):
     def test_has__DiscardedPacketsMessage(self):
         self._assert_in_bt2('_DiscardedPacketsMessage')
 
+    def test_has__EventMessageConst(self):
+        self._assert_in_bt2('_EventMessageConst')
+
+    def test_has__PacketBeginningMessageConst(self):
+        self._assert_in_bt2('_PacketBeginningMessageConst')
+
+    def test_has__PacketEndMessageConst(self):
+        self._assert_in_bt2('_PacketEndMessageConst')
+
+    def test_has__StreamBeginningMessageConst(self):
+        self._assert_in_bt2('_StreamBeginningMessageConst')
+
+    def test_has__StreamEndMessageConst(self):
+        self._assert_in_bt2('_StreamEndMessageConst')
+
+    def test_has__MessageIteratorInactivityMessageConst(self):
+        self._assert_in_bt2('_MessageIteratorInactivityMessageConst')
+
+    def test_has__DiscardedEventsMessageConst(self):
+        self._assert_in_bt2('_DiscardedEventsMessageConst')
+
+    def test_has__DiscardedPacketsMessageConst(self):
+        self._assert_in_bt2('_DiscardedPacketsMessageConst')
+
     def test_has__UserMessageIterator(self):
         self._assert_in_bt2('_UserMessageIterator')
 
index aad07c4441b3d3e8b2706177976f053216812db8..aa1c2d6a619cf989b382a93316921291180dcb92 100644 (file)
 #
 
 import unittest
+import utils
 from utils import run_in_component_init
+from bt2 import stream as bt2_stream
+from bt2 import field as bt2_field
 
 
 class PacketTestCase(unittest.TestCase):
@@ -87,10 +90,20 @@ class PacketTestCase(unittest.TestCase):
     def test_attr_stream(self):
         packet, stream, _ = self._create_packet(with_pc=True)
         self.assertEqual(packet.stream.addr, stream.addr)
+        self.assertIs(type(packet.stream), bt2_stream._Stream)
+
+    def test_const_attr_stream(self):
+        packet = utils.get_const_packet_beginning_message().packet
+        self.assertIs(type(packet.stream), bt2_stream._StreamConst)
 
     def test_context_field(self):
         packet, stream, pc_fc = self._create_packet(with_pc=True)
         self.assertEqual(packet.context_field.cls.addr, pc_fc.addr)
+        self.assertIs(type(packet.context_field), bt2_field._StructureField)
+
+    def test_const_context_field(self):
+        packet = utils.get_const_packet_beginning_message().packet
+        self.assertIs(type(packet.context_field), bt2_field._StructureFieldConst)
 
     def test_no_context_field(self):
         packet, _, _ = self._create_packet(with_pc=False)
index 79e9b0238169e7d65c1190cb427dedab964f0868..d03c27601a30030be79bb2a824fa3691e1f3304c 100644 (file)
 #
 
 import unittest
+import utils
 from utils import run_in_component_init
+from bt2 import trace as bt2_trace
+from bt2 import stream as bt2_stream
+from bt2 import value as bt2_value
+from bt2 import stream_class as bt2_stream_class
 
 
 class StreamTestCase(unittest.TestCase):
@@ -32,6 +37,7 @@ class StreamTestCase(unittest.TestCase):
     def test_create_default(self):
         stream = self._tr.create_stream(self._sc)
         self.assertIsNone(stream.name)
+        self.assertIs(type(stream), bt2_stream._Stream)
         self.assertEqual(len(stream.user_attributes), 0)
 
     def test_name(self):
@@ -45,6 +51,12 @@ class StreamTestCase(unittest.TestCase):
     def test_create_user_attributes(self):
         stream = self._tr.create_stream(self._sc, user_attributes={'salut': 23})
         self.assertEqual(stream.user_attributes, {'salut': 23})
+        self.assertIs(type(stream.user_attributes), bt2_value.MapValue)
+
+    def test_const_user_attributes(self):
+        stream = utils.get_const_stream_beginning_message().stream
+        self.assertEqual(stream.user_attributes, {'salut': 23})
+        self.assertIs(type(stream.user_attributes), bt2_value._MapValueConst)
 
     def test_create_invalid_user_attributes(self):
         with self.assertRaises(TypeError):
@@ -57,10 +69,20 @@ class StreamTestCase(unittest.TestCase):
     def test_stream_class(self):
         stream = self._tr.create_stream(self._sc)
         self.assertEqual(stream.cls, self._sc)
+        self.assertIs(type(stream.cls), bt2_stream_class._StreamClass)
+
+    def test_const_stream_class(self):
+        stream = utils.get_const_stream_beginning_message().stream
+        self.assertIs(type(stream.cls), bt2_stream_class._StreamClassConst)
 
     def test_trace(self):
         stream = self._tr.create_stream(self._sc)
         self.assertEqual(stream.trace.addr, self._tr.addr)
+        self.assertIs(type(stream.trace), bt2_trace._Trace)
+
+    def test_const_trace(self):
+        stream = utils.get_const_stream_beginning_message().stream
+        self.assertIs(type(stream.trace), bt2_trace._TraceConst)
 
     def test_invalid_id(self):
         sc = self._tc.create_stream_class(assigns_automatic_stream_id=False)
index f94be02992e6a7ad1c9a563468d6f532e4f46488..b510fc2b055af5aae7be998489622a8550257f92 100644 (file)
 
 import unittest
 from utils import run_in_component_init
+from bt2 import stream_class as bt2_stream_class
+from bt2 import trace_class as bt2_trace_class
+from bt2 import clock_class as bt2_clock_class
+from bt2 import event_class as bt2_event_class
+from bt2 import field_class as bt2_field_class
 
 
 class StreamClassTestCase(unittest.TestCase):
@@ -33,6 +38,7 @@ class StreamClassTestCase(unittest.TestCase):
     def test_create_default(self):
         sc = self._tc.create_stream_class()
 
+        self.assertIs(type(sc), bt2_stream_class._StreamClass)
         self.assertIsNone(sc.name)
         self.assertIsNone(sc.packet_context_field_class)
         self.assertIsNone(sc.event_common_context_field_class)
@@ -62,6 +68,9 @@ class StreamClassTestCase(unittest.TestCase):
             packet_context_field_class=fc, supports_packets=True
         )
         self.assertEqual(sc.packet_context_field_class, fc)
+        self.assertIs(
+            type(sc.packet_context_field_class), bt2_field_class._StructureFieldClass
+        )
 
     def test_create_invalid_packet_context_field_class(self):
         with self.assertRaises(TypeError):
@@ -77,6 +86,10 @@ class StreamClassTestCase(unittest.TestCase):
         fc = self._tc.create_structure_field_class()
         sc = self._tc.create_stream_class(event_common_context_field_class=fc)
         self.assertEqual(sc.event_common_context_field_class, fc)
+        self.assertIs(
+            type(sc.event_common_context_field_class),
+            bt2_field_class._StructureFieldClass,
+        )
 
     def test_create_invalid_event_common_context_field_class(self):
         with self.assertRaises(TypeError):
@@ -85,6 +98,7 @@ class StreamClassTestCase(unittest.TestCase):
     def test_create_default_clock_class(self):
         sc = self._tc.create_stream_class(default_clock_class=self._cc)
         self.assertEqual(sc.default_clock_class.addr, self._cc.addr)
+        self.assertIs(type(sc.default_clock_class), bt2_clock_class._ClockClass)
 
     def test_create_invalid_default_clock_class(self):
         with self.assertRaises(TypeError):
@@ -307,6 +321,7 @@ class StreamClassTestCase(unittest.TestCase):
     def test_trace_class(self):
         sc = self._tc.create_stream_class()
         self.assertEqual(sc.trace_class.addr, self._tc.addr)
+        self.assertIs(type(sc.trace_class), bt2_trace_class._TraceClass)
 
     def _create_stream_class_with_event_classes(self):
         sc = self._tc.create_stream_class(assigns_automatic_event_class_id=False)
@@ -318,7 +333,9 @@ class StreamClassTestCase(unittest.TestCase):
         sc, ec1, ec2 = self._create_stream_class_with_event_classes()
 
         self.assertEqual(sc[23].addr, ec1.addr)
+        self.assertEqual(type(sc[23]), bt2_event_class._EventClass)
         self.assertEqual(sc[17].addr, ec2.addr)
+        self.assertEqual(type(sc[17]), bt2_event_class._EventClass)
 
     def test_getitem_wrong_key_type(self):
         sc, _, _ = self._create_stream_class_with_event_classes()
index 0cb3b94eb46b6386c640782df03511b803131afd..7fa8d8a56a28fc5d6fb46b96f99324400136b977 100644 (file)
 
 import uuid
 import unittest
+import utils
 from utils import get_default_trace_class
+from bt2 import trace_class as bt2_trace_class
+from bt2 import value as bt2_value
+from bt2 import trace as bt2_trace
+from bt2 import stream as bt2_stream
 
 
 class TraceTestCase(unittest.TestCase):
@@ -39,6 +44,7 @@ class TraceTestCase(unittest.TestCase):
     def test_create_user_attributes(self):
         trace = self._tc(user_attributes={'salut': 23})
         self.assertEqual(trace.user_attributes, {'salut': 23})
+        self.assertIs(type(trace.user_attributes), bt2_value.MapValue)
 
     def test_create_invalid_user_attributes(self):
         with self.assertRaises(TypeError):
@@ -51,6 +57,11 @@ class TraceTestCase(unittest.TestCase):
     def test_attr_trace_class(self):
         trace = self._tc()
         self.assertEqual(trace.cls.addr, self._tc.addr)
+        self.assertIs(type(trace.cls), bt2_trace_class._TraceClass)
+
+    def test_const_attr_trace_class(self):
+        trace = utils.get_const_stream_beginning_message().stream.trace
+        self.assertIs(type(trace.cls), bt2_trace_class._TraceClassConst)
 
     def test_attr_name(self):
         trace = self._tc(name='mein trace')
@@ -62,9 +73,33 @@ class TraceTestCase(unittest.TestCase):
 
     def test_env_get(self):
         trace = self._tc(environment={'hello': 'you', 'foo': -5})
+        self.assertIs(type(trace.environment), bt2_trace._TraceEnvironment)
+        self.assertIs(type(trace.environment['foo']), bt2_value.SignedIntegerValue)
         self.assertEqual(trace.environment['hello'], 'you')
         self.assertEqual(trace.environment['foo'], -5)
 
+    def test_env_iter(self):
+        trace = self._tc(environment={'hello': 'you', 'foo': -5})
+        values = set(trace.environment)
+        self.assertEqual(values, {'hello', 'foo'})
+
+    def test_const_env_get(self):
+        trace = utils.get_const_stream_beginning_message().stream.trace
+        self.assertIs(type(trace.environment), bt2_trace._TraceEnvironmentConst)
+        self.assertIs(
+            type(trace.environment['patate']), bt2_value._SignedIntegerValueConst
+        )
+
+    def test_env_iter(self):
+        trace = utils.get_const_stream_beginning_message().stream.trace
+        values = set(trace.environment)
+        self.assertEqual(values, {'patate'})
+
+    def test_const_env_set(self):
+        trace = utils.get_const_stream_beginning_message().stream.trace
+        with self.assertRaises(TypeError):
+            trace.environment['patate'] = 33
+
     def test_env_get_non_existent(self):
         trace = self._tc(environment={'hello': 'you', 'foo': -5})
 
@@ -95,8 +130,12 @@ class TraceTestCase(unittest.TestCase):
 
     def test_getitem(self):
         trace = self._create_trace_with_some_streams()
-
         self.assertEqual(trace[12].id, 12)
+        self.assertIs(type(trace[12]), bt2_stream._Stream)
+
+    def test_const_getitem(self):
+        trace = utils.get_const_stream_beginning_message().stream.trace
+        self.assertIs(type(trace[0]), bt2_stream._StreamConst)
 
     def test_getitem_invalid_key(self):
         trace = self._create_trace_with_some_streams()
index 168ae86367992d7a61a7ea5837ce7ad0cc0eeb0c..69397c633d08cd414723c268631a351d8c162329 100644 (file)
 #
 
 import unittest
-from utils import run_in_component_init, get_default_trace_class
+from utils import (
+    run_in_component_init,
+    get_default_trace_class,
+    get_const_stream_beginning_message,
+)
+from bt2 import stream_class as bt2_stream_class
+from bt2 import trace_class as bt2_trace_class
 
 
 class TraceClassTestCase(unittest.TestCase):
@@ -39,6 +45,7 @@ class TraceClassTestCase(unittest.TestCase):
         tc = run_in_component_init(f)
 
         self.assertEqual(len(tc), 0)
+        self.assertIs(type(tc), bt2_trace_class._TraceClass)
         self.assertTrue(tc.assigns_automatic_stream_class_id)
         self.assertEqual(len(tc.user_attributes), 0)
 
@@ -72,6 +79,8 @@ class TraceClassTestCase(unittest.TestCase):
         sc1 = tc.create_stream_class()
         sc2 = tc.create_stream_class()
 
+        self.assertIs(type(sc1), bt2_stream_class._StreamClass)
+        self.assertIs(type(sc2), bt2_stream_class._StreamClass)
         self.assertNotEqual(sc1.id, sc2.id)
 
     def test_automatic_stream_class_id_raises(self):
@@ -124,8 +133,13 @@ class TraceClassTestCase(unittest.TestCase):
 
     def test_getitem(self):
         tc, _, _, sc3 = self._create_trace_class_with_some_stream_classes()
+        self.assertIs(type(tc[2018]), bt2_stream_class._StreamClass)
         self.assertEqual(tc[2018].addr, sc3.addr)
 
+    def test_const_getitem(self):
+        const_tc = get_const_stream_beginning_message().stream.trace.cls
+        self.assertIs(type(const_tc[0]), bt2_stream_class._StreamClassConst)
+
     def test_getitem_wrong_key_type(self):
         tc, _, _, _ = self._create_trace_class_with_some_stream_classes()
         with self.assertRaises(TypeError):
@@ -147,12 +161,18 @@ class TraceClassTestCase(unittest.TestCase):
 
         for sc_id, stream_class in tc.items():
             if sc_id == 12:
+                self.assertIs(type(stream_class), bt2_stream_class._StreamClass)
                 self.assertEqual(stream_class.addr, sc1.addr)
             elif sc_id == 54:
                 self.assertEqual(stream_class.addr, sc2.addr)
             elif sc_id == 2018:
                 self.assertEqual(stream_class.addr, sc3.addr)
 
+    def test_const_iter(self):
+        const_tc = get_const_stream_beginning_message().stream.trace.cls
+        const_sc = list(const_tc.values())[0]
+        self.assertIs(type(const_sc), bt2_stream_class._StreamClassConst)
+
     def test_destruction_listener(self):
         def on_trace_class_destruction(trace_class):
             nonlocal trace_class_destroyed
index 7181a1e55eea979875827fc8d10c6adc52451ce6..f9b6546fdb6b17f6936722ec98069c4c7a13259d 100644 (file)
@@ -258,7 +258,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 28)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 8)
+        self.assertEqual(hist[bt2._EventMessageConst], 8)
 
     # Same as the above, but we pass a single spec instead of a spec list.
     def test_iter_specs_not_list(self):
@@ -269,7 +269,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 28)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 8)
+        self.assertEqual(hist[bt2._EventMessageConst], 8)
 
     def test_iter_custom_filter(self):
         src_spec = bt2.ComponentSpec.from_named_plugin_and_component_class(
@@ -280,7 +280,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         )
         msg_iter = bt2.TraceCollectionMessageIterator(src_spec, flt_spec)
         hist = _count_msgs_by_type(msg_iter)
-        self.assertEqual(hist[bt2._EventMessage], 5)
+        self.assertEqual(hist[bt2._EventMessageConst], 5)
 
     def test_iter_intersection(self):
         specs = [
@@ -294,7 +294,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 15)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 3)
+        self.assertEqual(hist[bt2._EventMessageConst], 3)
 
     def test_iter_intersection_params(self):
         # Check that all params used to create the source component are passed
@@ -314,7 +314,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
             specs, stream_intersection_mode=True
         )
 
-        event_msgs = [x for x in msg_iter if type(x) is bt2._EventMessage]
+        event_msgs = [x for x in msg_iter if type(x) is bt2._EventMessageConst]
         self.assertEqual(len(event_msgs), 3)
         self.assertEqual(
             event_msgs[0].default_clock_snapshot.ns_from_origin, 13516309000000071
@@ -335,7 +335,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 56)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 16)
+        self.assertEqual(hist[bt2._EventMessageConst], 16)
 
     def test_iter_no_intersection_begin(self):
         specs = [
@@ -345,7 +345,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         ]
         msg_iter = bt2.TraceCollectionMessageIterator(specs, begin=13515309.000000023)
         hist = _count_msgs_by_type(msg_iter)
-        self.assertEqual(hist[bt2._EventMessage], 6)
+        self.assertEqual(hist[bt2._EventMessageConst], 6)
 
     def test_iter_no_intersection_end(self):
         specs = [
@@ -355,7 +355,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         ]
         msg_iter = bt2.TraceCollectionMessageIterator(specs, end=13515309.000000075)
         hist = _count_msgs_by_type(msg_iter)
-        self.assertEqual(hist[bt2._EventMessage], 5)
+        self.assertEqual(hist[bt2._EventMessageConst], 5)
 
     def test_iter_auto_source_component_spec(self):
         specs = [bt2.AutoSourceComponentSpec(_3EVENTS_INTERSECT_TRACE_PATH)]
@@ -363,21 +363,21 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 28)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 8)
+        self.assertEqual(hist[bt2._EventMessageConst], 8)
 
     def test_iter_auto_source_component_spec_list_of_strings(self):
         msg_iter = bt2.TraceCollectionMessageIterator([_3EVENTS_INTERSECT_TRACE_PATH])
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 28)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 8)
+        self.assertEqual(hist[bt2._EventMessageConst], 8)
 
     def test_iter_auto_source_component_spec_string(self):
         msg_iter = bt2.TraceCollectionMessageIterator(_3EVENTS_INTERSECT_TRACE_PATH)
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 28)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 8)
+        self.assertEqual(hist[bt2._EventMessageConst], 8)
 
     def test_iter_mixed_inputs(self):
         msg_iter = bt2.TraceCollectionMessageIterator(
@@ -392,7 +392,7 @@ class TraceCollectionMessageIteratorTestCase(unittest.TestCase):
         msgs = list(msg_iter)
         self.assertEqual(len(msgs), 76)
         hist = _count_msgs_by_type(msgs)
-        self.assertEqual(hist[bt2._EventMessage], 24)
+        self.assertEqual(hist[bt2._EventMessageConst], 24)
 
     def test_auto_source_component_non_existent(self):
         with self.assertRaisesRegex(
@@ -426,7 +426,7 @@ class TestAutoDiscoverSourceComponentSpecsGrouping(
             bt2.AutoSourceComponentSpec(_AUTO_SOURCE_DISCOVERY_GROUPING_PATH),
         ]
         it = bt2.TraceCollectionMessageIterator(specs)
-        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessage]
+        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst]
 
         self.assertEqual(len(msgs), 8)
 
@@ -456,7 +456,7 @@ class TestAutoDiscoverSourceComponentSpecsParamsObjLogLevel(
             )
         ]
         it = bt2.TraceCollectionMessageIterator(specs)
-        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessage]
+        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst]
 
         self.assertEqual(len(msgs), 2)
 
@@ -508,7 +508,7 @@ class TestAutoDiscoverSourceComponentSpecsParamsObjLogLevel(
             ),
         ]
         it = bt2.TraceCollectionMessageIterator(specs)
-        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessage]
+        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst]
 
         self.assertEqual(len(msgs), 2)
 
@@ -572,7 +572,7 @@ class TestAutoDiscoverSourceComponentSpecsParamsObjLogLevel(
             ),
         ]
         it = bt2.TraceCollectionMessageIterator(specs)
-        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessage]
+        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst]
 
         self.assertEqual(len(msgs), 2)
 
@@ -639,7 +639,7 @@ class TestAutoDiscoverSourceComponentSpecsParamsObjLogLevel(
             ),
         ]
         it = bt2.TraceCollectionMessageIterator(specs)
-        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessage]
+        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst]
 
         self.assertEqual(len(msgs), 2)
 
@@ -700,7 +700,7 @@ class TestAutoDiscoverSourceComponentSpecsParamsObjLogLevel(
             ),
         ]
         it = bt2.TraceCollectionMessageIterator(specs)
-        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessage]
+        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst]
 
         self.assertEqual(len(msgs), 2)
         self.assertEqual(msgs[0].stream.name, "TestSourceA: None")
@@ -714,7 +714,7 @@ class TestAutoDiscoverSourceComponentSpecsParamsObjLogLevel(
             bt2.AutoSourceComponentSpec(self._dir_a, params={'what': 'python-obj'}),
         ]
         it = bt2.TraceCollectionMessageIterator(specs)
-        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessage]
+        msgs = [x for x in it if type(x) is bt2._StreamBeginningMessageConst]
 
         self.assertEqual(len(msgs), 2)
         self.assertEqual(msgs[0].stream.name, "TestSourceA: deore")
index 3e66976114a438d296a612d55da689a4f0183b27..8dfdfd6adc27d142b8881fe2ad1aaa6c33215001 100644 (file)
@@ -59,6 +59,191 @@ def get_default_trace_class():
     return run_in_component_init(f)
 
 
+# Create a pair of list, one containing non-const messages and the other
+# containing const messages
+def _get_all_message_types(with_packet=True):
+    _msgs = None
+
+    class MyIter(bt2._UserMessageIterator):
+        def __init__(self, self_output_port):
+
+            nonlocal _msgs
+            self._at = 0
+            self._msgs = [
+                self._create_stream_beginning_message(
+                    self_output_port.user_data['stream']
+                )
+            ]
+
+            if with_packet:
+                assert self_output_port.user_data['packet']
+                self._msgs.append(
+                    self._create_packet_beginning_message(
+                        self_output_port.user_data['packet']
+                    )
+                )
+
+            default_clock_snapshot = 789
+
+            if with_packet:
+                assert self_output_port.user_data['packet']
+                ev_parent = self_output_port.user_data['packet']
+            else:
+                assert self_output_port.user_data['stream']
+                ev_parent = self_output_port.user_data['stream']
+
+            msg = self._create_event_message(
+                self_output_port.user_data['event_class'],
+                ev_parent,
+                default_clock_snapshot,
+            )
+
+            msg.event.payload_field['giraffe'] = 1
+            msg.event.specific_context_field['ant'] = -1
+            msg.event.common_context_field['cpu_id'] = 1
+            self._msgs.append(msg)
+
+            if with_packet:
+                self._msgs.append(
+                    self._create_packet_end_message(
+                        self_output_port.user_data['packet']
+                    )
+                )
+
+            self._msgs.append(
+                self._create_stream_end_message(self_output_port.user_data['stream'])
+            )
+
+            _msgs = self._msgs
+
+        def __next__(self):
+            if self._at == len(self._msgs):
+                raise bt2.Stop
+
+            msg = self._msgs[self._at]
+            self._at += 1
+            return msg
+
+    class MySrc(bt2._UserSourceComponent, message_iterator_class=MyIter):
+        def __init__(self, params, obj):
+            tc = self._create_trace_class()
+            clock_class = self._create_clock_class(frequency=1000)
+
+            # event common context (stream-class-defined)
+            cc = tc.create_structure_field_class()
+            cc += [('cpu_id', tc.create_signed_integer_field_class(8))]
+
+            # packet context (stream-class-defined)
+            pc = None
+
+            if with_packet:
+                pc = tc.create_structure_field_class()
+                pc += [('something', tc.create_unsigned_integer_field_class(8))]
+
+            stream_class = tc.create_stream_class(
+                default_clock_class=clock_class,
+                event_common_context_field_class=cc,
+                packet_context_field_class=pc,
+                supports_packets=with_packet,
+            )
+
+            # specific context (event-class-defined)
+            sc = tc.create_structure_field_class()
+            sc += [('ant', tc.create_signed_integer_field_class(16))]
+
+            # event payload
+            ep = tc.create_structure_field_class()
+            ep += [('giraffe', tc.create_signed_integer_field_class(32))]
+
+            event_class = stream_class.create_event_class(
+                name='garou', specific_context_field_class=sc, payload_field_class=ep
+            )
+
+            trace = tc(environment={'patate': 12})
+            stream = trace.create_stream(stream_class, user_attributes={'salut': 23})
+
+            if with_packet:
+                packet = stream.create_packet()
+                packet.context_field['something'] = 154
+            else:
+                packet = None
+
+            self._add_output_port(
+                'out',
+                {
+                    'tc': tc,
+                    'stream': stream,
+                    'event_class': event_class,
+                    'trace': trace,
+                    'packet': packet,
+                },
+            )
+
+    _graph = bt2.Graph()
+    _src_comp = _graph.add_component(MySrc, 'my_source')
+    _msg_iter = TestOutputPortMessageIterator(_graph, _src_comp.output_ports['out'])
+
+    const_msgs = list(_msg_iter)
+
+    return _msgs, const_msgs
+
+
+def get_stream_beginning_message():
+    msgs, _ = _get_all_message_types()
+    for m in msgs:
+        if type(m) is bt2._StreamBeginningMessage:
+            return m
+
+
+def get_const_stream_beginning_message():
+    _, const_msgs = _get_all_message_types()
+    for m in const_msgs:
+        if type(m) is bt2._StreamBeginningMessageConst:
+            return m
+
+
+def get_stream_end_message():
+    msgs, _ = _get_all_message_types()
+    for m in msgs:
+        if type(m) is bt2._StreamEndMessage:
+            return m
+
+
+def get_packet_beginning_message():
+    msgs, _ = _get_all_message_types(with_packet=True)
+    for m in msgs:
+        if type(m) is bt2._PacketBeginningMessage:
+            return m
+
+
+def get_const_packet_beginning_message():
+    _, const_msgs = _get_all_message_types(with_packet=True)
+    for m in const_msgs:
+        if type(m) is bt2._PacketBeginningMessageConst:
+            return m
+
+
+def get_packet_end_message():
+    msgs, _ = _get_all_message_types(with_packet=True)
+    for m in msgs:
+        if type(m) is bt2._PacketEndMessage:
+            return m
+
+
+def get_event_message():
+    msgs, _ = _get_all_message_types()
+    for m in msgs:
+        if type(m) is bt2._EventMessage:
+            return m
+
+
+def get_const_event_message():
+    _, const_msgs = _get_all_message_types()
+    for m in const_msgs:
+        if type(m) is bt2._EventMessageConst:
+            return m
+
+
 # Proxy sink component class.
 #
 # This sink accepts a list of a single item as its initialization
This page took 0.131278 seconds and 4 git commands to generate.