import bt2
-def _create_from_ptr(ptr):
+def _create_from_ptr_template(ptr, object_map):
if ptr is None:
return
return
typeid = native_bt.value_get_type(ptr)
- return _TYPE_TO_OBJ[typeid]._create_from_ptr(ptr)
+ return object_map[typeid]._create_from_ptr(ptr)
-def _create_from_ptr_and_get_ref(ptr):
+def _create_from_ptr(ptr):
+ return _create_from_ptr_template(ptr, _TYPE_TO_OBJ)
+
+
+def _create_from_const_ptr(ptr):
+ return _create_from_ptr_template(ptr, _TYPE_TO_CONST_OBJ)
+
+
+def _create_from_ptr_and_get_ref_template(ptr, object_map):
if ptr is None or ptr == native_bt.value_null:
return
typeid = native_bt.value_get_type(ptr)
- return _TYPE_TO_OBJ[typeid]._create_from_ptr_and_get_ref(ptr)
+ return object_map[typeid]._create_from_ptr_and_get_ref(ptr)
+
+
+def _create_from_ptr_and_get_ref(ptr):
+ return _create_from_ptr_and_get_ref_template(ptr, _TYPE_TO_OBJ)
+
+
+def _create_from_const_ptr_and_get_ref(ptr):
+ return _create_from_ptr_and_get_ref_template(ptr, _TYPE_TO_CONST_OBJ)
def create_value(value):
)
-class _Value(object._SharedObject, metaclass=abc.ABCMeta):
+class _ValueConst(object._SharedObject, metaclass=abc.ABCMeta):
_get_ref = staticmethod(native_bt.value_get_ref)
_put_ref = staticmethod(native_bt.value_put_ref)
+ _create_value_from_ptr = staticmethod(_create_from_const_ptr)
+ _create_value_from_ptr_and_get_ref = staticmethod(
+ _create_from_const_ptr_and_get_ref
+ )
def __ne__(self, other):
return not (self == other)
)
+class _Value(_ValueConst):
+ _create_value_from_ptr = staticmethod(_create_from_ptr)
+ _create_value_from_ptr_and_get_ref = staticmethod(_create_from_ptr_and_get_ref)
+
+
@functools.total_ordering
-class _NumericValue(_Value):
+class _NumericValueConst(_ValueConst):
@staticmethod
def _extract_value(other):
- if isinstance(other, BoolValue) or isinstance(other, bool):
+ if isinstance(other, _BoolValueConst) or isinstance(other, bool):
return bool(other)
if isinstance(other, numbers.Integral):
return self._extract_value(base) ** self._value
-class _IntegralValue(_NumericValue, numbers.Integral):
+class _NumericValue(_NumericValueConst, _Value):
+ pass
+
+
+class _IntegralValueConst(_NumericValueConst, numbers.Integral):
def __lshift__(self, other):
return self._value << self._extract_value(other)
return ~self._value
-class _RealValue(_NumericValue, numbers.Real):
+class _IntegralValue(_IntegralValueConst, _NumericValue):
pass
-class BoolValue(_IntegralValue):
+class _BoolValueConst(_IntegralValueConst):
+ _NAME = 'Const boolean'
+
+ def __bool__(self):
+ return self._value
+
+ def __repr__(self):
+ return repr(self._value)
+
+ @property
+ def _value(self):
+ value = native_bt.value_bool_get(self._ptr)
+ return value != 0
+
+
+class BoolValue(_BoolValueConst, _IntegralValue):
_NAME = 'Boolean'
def __init__(self, value=None):
self._check_create_status(ptr)
super().__init__(ptr)
- def __bool__(self):
- return self._value
-
- def __repr__(self):
- return repr(self._value)
-
- def _value_to_bool(self, value):
- if isinstance(value, BoolValue):
+ @classmethod
+ def _value_to_bool(cls, value):
+ if isinstance(value, _BoolValueConst):
value = value._value
if not isinstance(value, bool):
raise TypeError(
- "'{}' object is not a 'bool' or 'BoolValue' object".format(
+ "'{}' object is not a 'bool', 'BoolValue', or '_BoolValueConst' object".format(
value.__class__
)
)
return value
- @property
- def _value(self):
- value = native_bt.value_bool_get(self._ptr)
- return value != 0
-
def _set_value(self, value):
native_bt.value_bool_set(self._ptr, self._value_to_bool(value))
value = property(fset=_set_value)
-class _IntegerValue(_IntegralValue):
+class _IntegerValueConst(_IntegralValueConst):
+ @property
+ def _value(self):
+ return self._get_value(self._ptr)
+
+
+class _IntegerValue(_IntegerValueConst, _IntegralValue):
def __init__(self, value=None):
if value is None:
ptr = self._create_default_value()
self._check_create_status(ptr)
super().__init__(ptr)
- 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')
value = int(value)
- self._check_int_range(value)
+ cls._check_int_range(value)
return value
- @property
- def _value(self):
- return self._get_value(self._ptr)
-
def _prop_set_value(self, value):
self._set_value(self._ptr, self._value_to_int(value))
value = property(fset=_prop_set_value)
-class UnsignedIntegerValue(_IntegerValue):
+class _UnsignedIntegerValueConst(_IntegerValueConst):
+ _NAME = 'Const unsigned integer'
+ _get_value = staticmethod(native_bt.value_integer_unsigned_get)
+
+
+class UnsignedIntegerValue(_UnsignedIntegerValueConst, _IntegerValue):
+ _NAME = 'Unsigned integer'
_check_int_range = staticmethod(utils._check_uint64)
_create_default_value = staticmethod(native_bt.value_integer_unsigned_create)
_create_value = staticmethod(native_bt.value_integer_unsigned_create_init)
_set_value = staticmethod(native_bt.value_integer_unsigned_set)
- _get_value = staticmethod(native_bt.value_integer_unsigned_get)
-class SignedIntegerValue(_IntegerValue):
+class _SignedIntegerValueConst(_IntegerValueConst):
+ _NAME = 'Const signed integer'
+ _get_value = staticmethod(native_bt.value_integer_signed_get)
+
+
+class SignedIntegerValue(_SignedIntegerValueConst, _IntegerValue):
+ _NAME = 'Signed integer'
_check_int_range = staticmethod(utils._check_int64)
_create_default_value = staticmethod(native_bt.value_integer_signed_create)
_create_value = staticmethod(native_bt.value_integer_signed_create_init)
_set_value = staticmethod(native_bt.value_integer_signed_set)
- _get_value = staticmethod(native_bt.value_integer_signed_get)
-class RealValue(_RealValue):
+class _RealValueConst(_NumericValueConst, numbers.Real):
+ _NAME = 'Const real number'
+
+ @property
+ def _value(self):
+ return native_bt.value_real_get(self._ptr)
+
+
+class RealValue(_RealValueConst, _NumericValue):
_NAME = 'Real number'
def __init__(self, value=None):
self._check_create_status(ptr)
super().__init__(ptr)
- 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")
return float(value)
- @property
- def _value(self):
- return native_bt.value_real_get(self._ptr)
-
def _set_value(self, value):
native_bt.value_real_set(self._ptr, self._value_to_float(value))
@functools.total_ordering
-class StringValue(collections.abc.Sequence, _Value):
- _NAME = 'String'
+class _StringValueConst(collections.abc.Sequence, _Value):
+ _NAME = 'Const string'
- def __init__(self, value=None):
- if value is None:
- ptr = native_bt.value_string_create()
- else:
- ptr = native_bt.value_string_create_init(self._value_to_str(value))
-
- self._check_create_status(ptr)
- super().__init__(ptr)
-
- def _value_to_str(self, value):
- if isinstance(value, self.__class__):
+ @classmethod
+ def _value_to_str(cls, value):
+ if isinstance(value, _StringValueConst):
value = value._value
utils._check_str(value)
def _value(self):
return native_bt.value_string_get(self._ptr)
- def _set_value(self, value):
- status = native_bt.value_string_set(self._ptr, self._value_to_str(value))
- utils._handle_func_status(status)
-
- value = property(fset=_set_value)
-
def __eq__(self, other):
try:
return self._value == self._value_to_str(other)
def __contains__(self, item):
return self._value_to_str(item) in self._value
+
+class StringValue(_StringValueConst, _Value):
+ _NAME = 'String'
+
+ def __init__(self, value=None):
+ if value is None:
+ ptr = native_bt.value_string_create()
+ else:
+ ptr = native_bt.value_string_create_init(self._value_to_str(value))
+
+ self._check_create_status(ptr)
+ super().__init__(ptr)
+
+ def _set_value(self, value):
+ status = native_bt.value_string_set(self._ptr, self._value_to_str(value))
+ utils._handle_func_status(status)
+
+ value = property(fset=_set_value)
+
def __iadd__(self, value):
curvalue = self._value
curvalue += self._value_to_str(value)
return self
-class _Container:
+class _ContainerConst:
def __bool__(self):
return len(self) != 0
+
+class _Container(_ContainerConst):
def __delitem__(self, index):
raise NotImplementedError
-class ArrayValue(_Container, collections.abc.MutableSequence, _Value):
- _NAME = 'Array'
-
- def __init__(self, value=None):
- ptr = native_bt.value_array_create()
- self._check_create_status(ptr)
- super().__init__(ptr)
-
- # Python will raise a TypeError if there's anything wrong with
- # the iterable protocol.
- if value is not None:
- for elem in value:
- self.append(elem)
+class _ArrayValueConst(_ContainerConst, collections.abc.Sequence, _ValueConst):
+ _NAME = 'Const array'
+ _borrow_element_by_index = staticmethod(
+ native_bt.value_array_borrow_element_by_index_const
+ )
+ _is_const = True
def __eq__(self, other):
if not isinstance(other, collections.abc.Sequence):
def __getitem__(self, index):
self._check_index(index)
- ptr = native_bt.value_array_borrow_element_by_index(self._ptr, index)
+ ptr = self._borrow_element_by_index(self._ptr, index)
assert ptr
- return _create_from_ptr_and_get_ref(ptr)
+ return self._create_value_from_ptr_and_get_ref(ptr)
+
+ def __repr__(self):
+ return '[{}]'.format(', '.join([repr(v) for v in self]))
+
+
+class ArrayValue(_ArrayValueConst, _Container, collections.abc.MutableSequence, _Value):
+ _NAME = 'Array'
+ _borrow_element_by_index = staticmethod(
+ native_bt.value_array_borrow_element_by_index
+ )
+
+ def __init__(self, value=None):
+ ptr = native_bt.value_array_create()
+ self._check_create_status(ptr)
+ super().__init__(ptr)
+
+ # Python will raise a TypeError if there's anything wrong with
+ # the iterable protocol.
+ if value is not None:
+ for elem in value:
+ self.append(elem)
def __setitem__(self, index, value):
self._check_index(index)
return self
- def __repr__(self):
- return '[{}]'.format(', '.join([repr(v) for v in self]))
-
def insert(self, value):
raise NotImplementedError
return str(key)
-class MapValue(_Container, collections.abc.MutableMapping, _Value):
- _NAME = 'Map'
-
- def __init__(self, value=None):
- ptr = native_bt.value_map_create()
- self._check_create_status(ptr)
- super().__init__(ptr)
-
- # Python will raise a TypeError if there's anything wrong with
- # the iterable/mapping protocol.
- if value is not None:
- for key, elem in value.items():
- self[key] = elem
+class _MapValueConst(_ContainerConst, collections.abc.Mapping, _ValueConst):
+ _NAME = 'Const map'
+ _borrow_entry_value_ptr = staticmethod(native_bt.value_map_borrow_entry_value_const)
def __ne__(self, other):
return _Value.__ne__(self, other)
def __getitem__(self, key):
self._check_key(key)
- ptr = native_bt.value_map_borrow_entry_value(self._ptr, key)
+ ptr = self._borrow_entry_value_ptr(self._ptr, key)
assert ptr
- return _create_from_ptr_and_get_ref(ptr)
+ return self._create_value_from_ptr_and_get_ref(ptr)
def __iter__(self):
return _MapValueKeyIterator(self)
+ def __repr__(self):
+ items = ['{}: {}'.format(repr(k), repr(v)) for k, v in self.items()]
+ return '{{{}}}'.format(', '.join(items))
+
+
+class MapValue(_MapValueConst, _Container, collections.abc.MutableMapping, _Value):
+ _NAME = 'Map'
+ _borrow_entry_value_ptr = staticmethod(native_bt.value_map_borrow_entry_value)
+
+ def __init__(self, value=None):
+ ptr = native_bt.value_map_create()
+ self._check_create_status(ptr)
+ super().__init__(ptr)
+
+ # Python will raise a TypeError if there's anything wrong with
+ # the iterable/mapping protocol.
+ if value is not None:
+ for key, elem in value.items():
+ self[key] = elem
+
def __setitem__(self, key, value):
self._check_key_type(key)
value = create_value(value)
status = native_bt.value_map_insert_entry(self._ptr, key, ptr)
utils._handle_func_status(status)
- def __repr__(self):
- items = ['{}: {}'.format(repr(k), repr(v)) for k, v in self.items()]
- return '{{{}}}'.format(', '.join(items))
-
_TYPE_TO_OBJ = {
native_bt.VALUE_TYPE_BOOL: BoolValue,
native_bt.VALUE_TYPE_ARRAY: ArrayValue,
native_bt.VALUE_TYPE_MAP: MapValue,
}
+
+_TYPE_TO_CONST_OBJ = {
+ native_bt.VALUE_TYPE_BOOL: _BoolValueConst,
+ native_bt.VALUE_TYPE_UNSIGNED_INTEGER: _UnsignedIntegerValueConst,
+ native_bt.VALUE_TYPE_SIGNED_INTEGER: _SignedIntegerValueConst,
+ native_bt.VALUE_TYPE_REAL: _RealValueConst,
+ native_bt.VALUE_TYPE_STRING: _StringValueConst,
+ native_bt.VALUE_TYPE_ARRAY: _ArrayValueConst,
+ native_bt.VALUE_TYPE_MAP: _MapValueConst,
+}
bt2.create_value(a)
+def _create_const_value(value):
+ class MySink(bt2._UserSinkComponent):
+ def _user_consume(self):
+ pass
+
+ @classmethod
+ def _user_query(cls, priv_query_exec, obj, params, method_obj):
+ nonlocal value
+ return {'my_value': value}
+
+ res = bt2.QueryExecutor(MySink, 'obj', None).query()
+ return res['my_value']
+
+
class BoolValueTestCase(_TestNumericValue, unittest.TestCase):
def setUp(self):
self._f = bt2.BoolValue(False)
def setUp(self):
self._def_value = 'Hello, World!'
self._def = bt2.StringValue(self._def_value)
+ self._def_const = _create_const_value(self._def_value)
self._def_new_value = 'Yes!'
def tearDown(self):
def test_eq(self):
self.assertEqual(self._def, self._def_value)
- def test_eq(self):
+ def test_const_eq(self):
+ self.assertEqual(self._def_const, self._def_value)
+
+ def test_eq_raw(self):
self.assertNotEqual(self._def, 23)
def test_lt_vstring(self):
def test_getitem(self):
self.assertEqual(self._def[5], self._def_value[5])
- def test_append_str(self):
+ def test_const_getitem(self):
+ self.assertEqual(self._def_const[5], self._def_value[5])
+
+ def test_iadd_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_iadd_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_vstr(self):
to_append = 'meow meow meow'
self._def += bt2.create_value(to_append)
def setUp(self):
self._def_value = [None, False, True, -23, 0, 42, -42.4, 23.17, 'yes']
self._def = bt2.ArrayValue(copy.deepcopy(self._def_value))
+ self._def_const = _create_const_value(copy.deepcopy(self._def_value))
def tearDown(self):
del self._def
def test_eq_int(self):
self.assertNotEqual(self._def, 23)
+ def test_const_eq(self):
+ a1 = _create_const_value([1, 2, 3])
+ a2 = [1, 2, 3]
+ self.assertEqual(a1, a2)
+
def test_eq_diff_len(self):
a1 = bt2.create_value([1, 2, 3])
a2 = bt2.create_value([1, 2])
+ self.assertIs(type(a1), bt2.ArrayValue)
+ self.assertIs(type(a2), bt2.ArrayValue)
self.assertNotEqual(a1, a2)
def test_eq_diff_content_same_len(self):
self._def[2] = None
self.assertIsNone(self._def[2])
+ def test_setitem_none(self):
+ self._def[2] = None
+ self.assertIsNone(self._def[2])
+
def test_setitem_index_wrong_type(self):
with self._assert_type_error():
self._def['yes'] = 23
with self.assertRaises(IndexError):
self._def[len(self._def)] = 23
+ def test_const_setitem(self):
+ with self.assertRaises(TypeError):
+ self._def_const[2] = 19
+
def test_append_none(self):
self._def.append(None)
self.assertIsNone(self._def[len(self._def) - 1])
self._def.append(raw)
self.assertEqual(self._def[len(self._def) - 1], raw)
+ def test_const_append(self):
+ with self.assertRaises(AttributeError):
+ self._def_const.append(12194)
+
def test_append_vint(self):
raw = 145
self._def.append(bt2.create_value(raw))
self.assertEqual(self._def[len(self._def) - 2], raw[1])
self.assertEqual(self._def[len(self._def) - 1], raw[2])
+ def test_const_iadd(self):
+ with self.assertRaises(TypeError):
+ self._def_const += 12194
+
def test_iadd_unknown(self):
class A:
pass
for velem, elem in zip(self._def, self._def_value):
self.assertEqual(velem, elem)
+ def test_const_iter(self):
+ for velem, elem in zip(self._def_const, self._def_value):
+ self.assertEqual(velem, elem)
+
+ def test_const_get_item(self):
+ item1 = self._def_const[0]
+ item2 = self._def_const[2]
+ item3 = self._def_const[5]
+ item4 = self._def_const[7]
+ item5 = self._def_const[8]
+
+ self.assertEqual(item1, None)
+
+ self.assertIs(type(item2), bt2._BoolValueConst)
+ self.assertEqual(item2, True)
+
+ self.assertIs(type(item3), bt2._SignedIntegerValueConst)
+ self.assertEqual(item3, 42)
+
+ self.assertIs(type(item4), bt2._RealValueConst)
+ self.assertEqual(item4, 23.17)
+
+ self.assertIs(type(item5), bt2._StringValueConst)
+ self.assertEqual(item5, 'yes')
+
class MapValueTestCase(_TestCopySimple, unittest.TestCase):
def setUp(self):
'str': 'yes',
}
self._def = bt2.MapValue(copy.deepcopy(self._def_value))
+ self._def_const = _create_const_value(self._def_value)
def tearDown(self):
del self._def
def test_len(self):
self.assertEqual(len(self._def), len(self._def_value))
+ def test_const_eq(self):
+ a1 = _create_const_value({'a': 1, 'b': 2, 'c': 3})
+ a2 = {'a': 1, 'b': 2, 'c': 3}
+ self.assertEqual(a1, a2)
+
def test_eq_int(self):
self.assertNotEqual(self._def, 23)
a2 = bt2.create_value({'a': 1, 'b': 2})
self.assertNotEqual(a1, a2)
+ def test_const_eq_diff_len(self):
+ a1 = _create_const_value({'a': 1, 'b': 2, 'c': 3})
+ a2 = _create_const_value({'a': 1, 'b': 2})
+ self.assertNotEqual(a1, a2)
+
def test_eq_diff_content_same_len(self):
a1 = bt2.create_value({'a': 1, 'b': 2, 'c': 3})
a2 = bt2.create_value({'a': 4, 'b': 2, 'c': 3})
self.assertNotEqual(a1, a2)
+ def test_const_eq_diff_content_same_len(self):
+ a1 = _create_const_value({'a': 1, 'b': 2, 'c': 3})
+ a2 = _create_const_value({'a': 4, 'b': 2, 'c': 3})
+ self.assertNotEqual(a1, a2)
+
def test_eq_same_content_diff_keys(self):
a1 = bt2.create_value({'a': 1, 'b': 2, 'c': 3})
a2 = bt2.create_value({'a': 1, 'k': 2, 'c': 3})
self.assertNotEqual(a1, a2)
+ def test_const_eq_same_content_diff_keys(self):
+ a1 = _create_const_value({'a': 1, 'b': 2, 'c': 3})
+ a2 = _create_const_value({'a': 1, 'k': 2, 'c': 3})
+ self.assertNotEqual(a1, a2)
+
def test_eq_same_content_same_len(self):
raw = {'3': 3, 'True': True, 'array': [1, 2.5, None, {'a': 17.6, 'b': None}]}
a1 = bt2.MapValue(raw)
self.assertEqual(a1, a2)
self.assertEqual(a1, raw)
+ def test_const_eq_same_content_same_len(self):
+ raw = {'3': 3, 'True': True, 'array': [1, 2.5, None, {'a': 17.6, 'b': None}]}
+ a1 = _create_const_value(raw)
+ a2 = _create_const_value(copy.deepcopy(raw))
+ self.assertEqual(a1, a2)
+ self.assertEqual(a1, raw)
+
def test_setitem_int(self):
raw = 19
self._def['pos-int'] = raw
self.assertEqual(self._def['pos-int'], raw)
+ def test_const_setitem_int(self):
+ with self.assertRaises(TypeError):
+ self._def_const['pos-int'] = 19
+
def test_setitem_vint(self):
raw = 19
self._def['pos-int'] = bt2.create_value(raw)
val = self._def_value[vkey]
self.assertEqual(vval, val)
+ def test_const_iter(self):
+ for vkey, vval in self._def_const.items():
+ val = self._def_value[vkey]
+ self.assertEqual(vval, val)
+
+ def test_get_item(self):
+ i = self._def['pos-float']
+ self.assertIs(type(i), bt2.RealValue)
+ self.assertEqual(i, 23.17)
+
+ def test_const_get_item(self):
+ item1 = self._def_const['none']
+ item2 = self._def_const['true']
+ item3 = self._def_const['pos-int']
+ item4 = self._def_const['pos-float']
+ item5 = self._def_const['str']
+
+ self.assertEqual(item1, None)
+
+ self.assertIs(type(item2), bt2._BoolValueConst)
+ self.assertEqual(item2, True)
+
+ self.assertIs(type(item3), bt2._SignedIntegerValueConst)
+ self.assertEqual(item3, 42)
+
+ self.assertIs(type(item4), bt2._RealValueConst)
+ self.assertEqual(item4, 23.17)
+
+ self.assertIs(type(item5), bt2._StringValueConst)
+ self.assertEqual(item5, 'yes')
+
def test_getitem_wrong_key(self):
with self.assertRaises(KeyError):
self._def['kilojoule']