From: Philippe Proulx Date: Mon, 12 Aug 2019 02:04:08 +0000 (-0400) Subject: bt2: add boolean field class and field support X-Git-Url: http://git.efficios.com/?p=babeltrace.git;a=commitdiff_plain;h=aae30e61f85f6654c37da7a5da3b22fbbe2dbd5c bt2: add boolean field class and field support This patch adds boolean field class and field support to the Python bindings. A boolean field class has no properties. A boolean field is a numeric field (like Python's `bool` is a numeric type). The `BoolFieldTestCase` test case inherits `_TestNumericField`, making sure the field behaves more or less like the Python `bool` type. `BoolFieldTestCase` is very similar to `BoolValueTestCase`. Just like `BoolValue` objects, you can set the value of a `BoolField` object from a `bool` or `BoolField` object. Signed-off-by: Philippe Proulx Change-Id: Ib6d0723d69709b7f3b459ba173eb7cbea5d8c435 Reviewed-on: https://review.lttng.org/c/babeltrace/+/1896 Tested-by: jenkins Reviewed-by: Francis Deslauriers Reviewed-by: Simon Marchi --- diff --git a/src/bindings/python/bt2/bt2/__init__.py b/src/bindings/python/bt2/bt2/__init__.py index abe119a1..9b23828e 100644 --- a/src/bindings/python/bt2/bt2/__init__.py +++ b/src/bindings/python/bt2/bt2/__init__.py @@ -41,6 +41,7 @@ from bt2.error import _ComponentClassErrorCause from bt2.error import _MessageIteratorErrorCause from bt2.error import _Error from bt2.event_class import EventClassLogLevel +from bt2.field import _BoolField from bt2.field import _IntegerField from bt2.field import _UnsignedIntegerField from bt2.field import _SignedIntegerField @@ -55,6 +56,7 @@ from bt2.field import _ArrayField from bt2.field import _StaticArrayField from bt2.field import _DynamicArrayField from bt2.field_class import IntegerDisplayBase +from bt2.field_class import _BoolFieldClass from bt2.field_class import _IntegerFieldClass from bt2.field_class import _UnsignedIntegerFieldClass from bt2.field_class import _SignedIntegerFieldClass diff --git a/src/bindings/python/bt2/bt2/field.py b/src/bindings/python/bt2/bt2/field.py index eb11107c..2406b90e 100644 --- a/src/bindings/python/bt2/bt2/field.py +++ b/src/bindings/python/bt2/bt2/field.py @@ -71,8 +71,8 @@ class _Field(object._UniqueObject): class _NumericField(_Field): @staticmethod def _extract_value(other): - if isinstance(other, bool): - return other + if isinstance(other, _BoolField) or isinstance(other, bool): + return bool(other) if isinstance(other, numbers.Integral): return int(other) @@ -208,6 +208,36 @@ class _IntegralField(_NumericField, numbers.Integral): return ~self._value +class _BoolField(_IntegralField, _Field): + _NAME = 'Boolean' + + def __bool__(self): + return self._value + + def _value_to_bool(self, value): + if isinstance(value, _BoolField): + value = value._value + + if not isinstance(value, bool): + raise TypeError( + "'{}' object is not a 'bool' or '_BoolField' object".format( + value.__class__ + ) + ) + + return value + + @property + def _value(self): + return bool(native_bt.field_bool_get_value(self._ptr)) + + def _set_value(self, value): + value = self._value_to_bool(value) + native_bt.field_bool_set_value(self._ptr, value) + + value = property(fset=_set_value) + + class _IntegerField(_IntegralField, _Field): pass @@ -591,6 +621,7 @@ class _DynamicArrayField(_ArrayField, _Field): _TYPE_ID_TO_OBJ = { + native_bt.FIELD_CLASS_TYPE_BOOL: _BoolField, native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerField, native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerField, native_bt.FIELD_CLASS_TYPE_REAL: _RealField, diff --git a/src/bindings/python/bt2/bt2/field_class.py b/src/bindings/python/bt2/bt2/field_class.py index 18dbed93..85ba78bb 100644 --- a/src/bindings/python/bt2/bt2/field_class.py +++ b/src/bindings/python/bt2/bt2/field_class.py @@ -50,6 +50,10 @@ class _FieldClass(object._SharedObject): ) +class _BoolFieldClass(_FieldClass): + _NAME = 'Boolean' + + class _IntegerFieldClass(_FieldClass): @property def field_value_range(self): @@ -583,6 +587,7 @@ class _DynamicArrayFieldClass(_ArrayFieldClass): _FIELD_CLASS_TYPE_TO_OBJ = { + native_bt.FIELD_CLASS_TYPE_BOOL: _BoolFieldClass, native_bt.FIELD_CLASS_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerFieldClass, native_bt.FIELD_CLASS_TYPE_SIGNED_INTEGER: _SignedIntegerFieldClass, native_bt.FIELD_CLASS_TYPE_REAL: _RealFieldClass, diff --git a/src/bindings/python/bt2/bt2/trace_class.py b/src/bindings/python/bt2/bt2/trace_class.py index 1643fc8e..db871783 100644 --- a/src/bindings/python/bt2/bt2/trace_class.py +++ b/src/bindings/python/bt2/bt2/trace_class.py @@ -184,15 +184,21 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping): # Field class creation methods. - def _check_create_status(self, ptr, type_name): + def _check_field_class_create_status(self, ptr, type_name): if ptr is None: raise bt2._MemoryError('cannot create {} field class'.format(type_name)) + def create_bool_field_class(self): + field_class_ptr = native_bt.field_class_bool_create(self._ptr) + self._check_field_class_create_status(field_class_ptr, 'boolean') + + return bt2_field_class._BoolFieldClass._create_from_ptr(field_class_ptr) + def _create_integer_field_class( self, create_func, py_cls, type_name, field_value_range, preferred_display_base ): field_class_ptr = create_func(self._ptr) - self._check_create_status(field_class_ptr, type_name) + self._check_field_class_create_status(field_class_ptr, type_name) field_class = py_cls._create_from_ptr(field_class_ptr) @@ -250,7 +256,7 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping): def create_real_field_class(self, is_single_precision=False): field_class_ptr = native_bt.field_class_real_create(self._ptr) - self._check_create_status(field_class_ptr, 'real') + self._check_field_class_create_status(field_class_ptr, 'real') field_class = bt2_field_class._RealFieldClass._create_from_ptr(field_class_ptr) @@ -260,13 +266,13 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping): def create_structure_field_class(self): field_class_ptr = native_bt.field_class_structure_create(self._ptr) - self._check_create_status(field_class_ptr, 'structure') + self._check_field_class_create_status(field_class_ptr, 'structure') return bt2_field_class._StructureFieldClass._create_from_ptr(field_class_ptr) def create_string_field_class(self): field_class_ptr = native_bt.field_class_string_create(self._ptr) - self._check_create_status(field_class_ptr, 'string') + self._check_field_class_create_status(field_class_ptr, 'string') return bt2_field_class._StringFieldClass._create_from_ptr(field_class_ptr) @@ -274,7 +280,7 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping): utils._check_type(elem_fc, bt2_field_class._FieldClass) utils._check_uint64(length) ptr = native_bt.field_class_array_static_create(self._ptr, elem_fc._ptr, length) - self._check_create_status(ptr, 'static array') + self._check_field_class_create_status(ptr, 'static array') return bt2_field_class._StaticArrayFieldClass._create_from_ptr_and_get_ref(ptr) @@ -289,7 +295,7 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping): ptr = native_bt.field_class_array_dynamic_create( self._ptr, elem_fc._ptr, length_fc_ptr ) - self._check_create_status(ptr, 'dynamic array') + self._check_field_class_create_status(ptr, 'dynamic array') return bt2_field_class._DynamicArrayFieldClass._create_from_ptr(ptr) def create_variant_field_class(self, selector_fc=None): @@ -300,7 +306,7 @@ class _TraceClass(object._SharedObject, collections.abc.Mapping): selector_fc_ptr = selector_fc._ptr ptr = native_bt.field_class_variant_create(self._ptr, selector_fc_ptr) - self._check_create_status(ptr, 'variant') + self._check_field_class_create_status(ptr, 'variant') return bt2_field_class._create_field_class_from_ptr_and_get_ref(ptr) # Add a listener to be called when the trace class is destroyed. diff --git a/tests/bindings/python/bt2/test_field.py b/tests/bindings/python/bt2/test_field.py index e1d8fba7..174ae2d9 100644 --- a/tests/bindings/python/bt2/test_field.py +++ b/tests/bindings/python/bt2/test_field.py @@ -1077,6 +1077,52 @@ def _inject_numeric_testing_methods(cls): ) +class BoolFieldTestCase(_TestNumericField, unittest.TestCase): + def _create_fc(self, tc): + return tc.create_bool_field_class() + + def setUp(self): + self._tc = get_default_trace_class() + self._def = _create_field(self._tc, self._create_fc(self._tc)) + self._def.value = True + self._def_value = True + self._def_new_value = False + + def test_assign_true(self): + raw = True + self._def.value = raw + self.assertEqual(self._def, raw) + + def test_assign_false(self): + raw = False + self._def.value = raw + self.assertEqual(self._def, raw) + + def test_assign_field_true(self): + field = _create_field(self._tc, self._create_fc(self._tc)) + raw = True + field.value = raw + self._def.value = field + self.assertEqual(self._def, raw) + + def test_assign_field_false(self): + field = _create_field(self._tc, self._create_fc(self._tc)) + raw = False + field.value = raw + self._def.value = field + self.assertEqual(self._def, raw) + + def test_assign_invalid_type(self): + with self.assertRaises(TypeError): + self._def.value = 17 + + def test_str_op(self): + self.assertEqual(str(self._def), str(self._def_value)) + + +_inject_numeric_testing_methods(BoolFieldTestCase) + + class _TestIntegerFieldCommon(_TestNumericField): def test_assign_true(self): raw = True diff --git a/tests/bindings/python/bt2/test_field_class.py b/tests/bindings/python/bt2/test_field_class.py index 804d7d20..a25d96ea 100644 --- a/tests/bindings/python/bt2/test_field_class.py +++ b/tests/bindings/python/bt2/test_field_class.py @@ -21,6 +21,15 @@ import bt2 from utils import get_default_trace_class +class BoolFieldClassTestCase(unittest.TestCase): + def setUp(self): + tc = get_default_trace_class() + self._fc = tc.create_bool_field_class() + + def test_create_default(self): + self.assertIsNotNone(self._fc) + + class _TestIntegerFieldClassProps: def test_create_default(self): fc = self._create_func() diff --git a/tests/bindings/python/bt2/test_package.py b/tests/bindings/python/bt2/test_package.py index d118462b..836aa0a4 100644 --- a/tests/bindings/python/bt2/test_package.py +++ b/tests/bindings/python/bt2/test_package.py @@ -81,6 +81,9 @@ class PackageTestCase(unittest.TestCase): def test_has_EventClassLogLevel(self): self._assert_in_bt2('EventClassLogLevel') + def test_has__BoolField(self): + self._assert_in_bt2('_BoolField') + def test_has__IntegerField(self): self._assert_in_bt2('_IntegerField') @@ -123,6 +126,9 @@ class PackageTestCase(unittest.TestCase): def test_has_IntegerDisplayBase(self): self._assert_in_bt2('IntegerDisplayBase') + def test_has__BoolFieldClass(self): + self._assert_in_bt2('_BoolFieldClass') + def test_has__IntegerFieldClass(self): self._assert_in_bt2('_IntegerFieldClass')