bt2: Rename files to use singular form
authorSimon Marchi <simon.marchi@efficios.com>
Fri, 26 Apr 2019 19:26:51 +0000 (15:26 -0400)
committerJérémie Galarneau <jeremie.galarneau@efficios.com>
Fri, 3 May 2019 22:19:40 +0000 (18:19 -0400)
I am mildly annoyed that most Python files use the singular form of the
concept they are related too (component.py, event.py) but others use the
plural form (fields.py, values.py).

Change this to consistently use the singular.

Change-Id: I1a33c47ec45ef3359025e0a66f01eaefc09fecdf
Signed-off-by: Simon Marchi <simon.marchi@efficios.com>
Reviewed-on: https://review.gerrithub.io/c/eepp/babeltrace/+/452257
Reviewed-by: Philippe Proulx <eeppeliteloop@gmail.com>
Tested-by: Philippe Proulx <eeppeliteloop@gmail.com>
34 files changed:
bindings/python/bt2/Makefile.am
bindings/python/bt2/bt2/__init__.py.in
bindings/python/bt2/bt2/component.py
bindings/python/bt2/bt2/ctf_writer.py
bindings/python/bt2/bt2/event.py
bindings/python/bt2/bt2/event_class.py
bindings/python/bt2/bt2/field.py [new file with mode: 0644]
bindings/python/bt2/bt2/field_class.py
bindings/python/bt2/bt2/fields.py [deleted file]
bindings/python/bt2/bt2/packet.py
bindings/python/bt2/bt2/query_executor.py
bindings/python/bt2/bt2/trace.py
bindings/python/bt2/bt2/value.py [new file with mode: 0644]
bindings/python/bt2/bt2/values.py [deleted file]
tests/bindings/python/bt2/test_component.py
tests/bindings/python/bt2/test_component_class.py
tests/bindings/python/bt2/test_connection.py
tests/bindings/python/bt2/test_event.py
tests/bindings/python/bt2/test_event_class.py
tests/bindings/python/bt2/test_field.py [new file with mode: 0644]
tests/bindings/python/bt2/test_field_class.py
tests/bindings/python/bt2/test_fields.py [deleted file]
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_packet.py
tests/bindings/python/bt2/test_plugin.py
tests/bindings/python/bt2/test_port.py
tests/bindings/python/bt2/test_query_executor.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_value.py [new file with mode: 0644]
tests/bindings/python/bt2/test_values.py [deleted file]

index 4368206192341a805eab41167a9f6f72687ed85e..a1d3b1ae0c461de85cf8659c0e7b9fc1281c63f6 100644 (file)
@@ -41,7 +41,7 @@ STATIC_BINDINGS_DEPS =                                        \
        bt2/ctf_writer.py                               \
        bt2/event_class.py                              \
        bt2/event.py                                    \
-       bt2/fields.py                                   \
+       bt2/field.py                                    \
        bt2/field_class.py                              \
        bt2/graph.py                                    \
        bt2/logging.py                                  \
@@ -58,7 +58,7 @@ STATIC_BINDINGS_DEPS =                                        \
        bt2/trace.py                                    \
        bt2/trace_collection_message_iterator.py        \
        bt2/utils.py                                    \
-       bt2/values.py
+       bt2/value.py
 
 GENERATED_BINDINGS_DEPS =      \
        bt2/__init__.py         \
index 5a098d9424358cfa90b42490269e0710bdc4a2b3..8e26fc73fc8f01eb22d46df80ad870a84d8f7fa4 100644 (file)
@@ -45,16 +45,16 @@ from bt2.event import _Event
 from bt2.event_class import *
 from bt2.field_class import *
 from bt2.field_class import _FieldClass
-from bt2.fields import *
-from bt2.fields import _ArrayField
-from bt2.fields import _EnumerationField
-from bt2.fields import _Field
-from bt2.fields import _FloatingPointNumberField
-from bt2.fields import _IntegerField
-from bt2.fields import _SequenceField
-from bt2.fields import _StringField
-from bt2.fields import _StructureField
-from bt2.fields import _VariantField
+from bt2.field import *
+from bt2.field import _ArrayField
+from bt2.field import _EnumerationField
+from bt2.field import _Field
+from bt2.field import _FloatingPointNumberField
+from bt2.field import _IntegerField
+from bt2.field import _SequenceField
+from bt2.field import _StringField
+from bt2.field import _StructureField
+from bt2.field import _VariantField
 from bt2.graph import *
 from bt2.logging import *
 from bt2.message import *
@@ -77,8 +77,8 @@ from bt2.stream import _Stream
 from bt2.stream_class import *
 from bt2.trace import *
 from bt2.trace_collection_message_iterator import *
-from bt2.values import *
-from bt2.values import _Value
+from bt2.value import *
+from bt2.value import _Value
 
 
 class Error(Exception):
index 34de513244e0c9c3675e158b071bc86ec9ac2417..a82f5267b6d3bb4d10ba8425b61cc7b53c5ac354 100644 (file)
@@ -23,7 +23,7 @@
 from bt2 import native_bt, object, utils
 import bt2.message_iterator
 import collections.abc
-import bt2.values
+import bt2.value
 import traceback
 import bt2.port
 import sys
@@ -428,7 +428,7 @@ class _UserComponentType(type):
         # call user's __init__() method
         if params_ptr is not None:
             native_bt.get(params_ptr)
-            params = bt2.values._create_from_ptr(params_ptr)
+            params = bt2.value._create_from_ptr(params_ptr)
         else:
             params = None
 
@@ -472,7 +472,7 @@ class _UserComponentType(type):
         # bt_component_class_query() returns NULL
         if params_ptr is not None:
             native_bt.get(params_ptr)
-            params = bt2.values._create_from_ptr(params_ptr)
+            params = bt2.value._create_from_ptr(params_ptr)
         else:
             params = None
 
index 225c93b5d56d36d5e43d72000e24847b7043059b..c021ebeb65199bd10c8f6244f272d79effe7a914 100644 (file)
@@ -23,7 +23,7 @@
 from bt2 import native_bt, object, stream, utils
 import uuid as uuidp
 import bt2.event
-import bt2.fields
+import bt2.field
 import abc
 import bt2
 
@@ -211,14 +211,14 @@ class _CtfWriterStream(stream._StreamBase):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @packet_header_field.setter
     def packet_header_field(self, packet_header_field):
         packet_header_field_ptr = None
 
         if packet_header_field is not None:
-            utils._check_type(packet_header_field, bt2.fields._Field)
+            utils._check_type(packet_header_field, bt2.field._Field)
             packet_header_field_ptr = packet_header_field._ptr
 
         ret = native_bt.stream_set_packet_header(self._ptr,
@@ -232,14 +232,14 @@ class _CtfWriterStream(stream._StreamBase):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @packet_context_field.setter
     def packet_context_field(self, packet_context_field):
         packet_context_field_ptr = None
 
         if packet_context_field is not None:
-            utils._check_type(packet_context_field, bt2.fields._Field)
+            utils._check_type(packet_context_field, bt2.field._Field)
             packet_context_field_ptr = packet_context_field._ptr
 
         ret = native_bt.stream_set_packet_context(self._ptr,
index eeb9e47ba3ee20446871c080f3326ec078131492..519c20d88b8af3166d03b44bd2c659ef2630d19c 100644 (file)
@@ -24,7 +24,7 @@ from bt2 import native_bt, object, utils
 import bt2.clock_class
 import bt2.packet
 import bt2.stream
-import bt2.fields
+import bt2.field
 import bt2.clock_snapshot
 import collections
 import numbers
@@ -133,14 +133,14 @@ class _Event(object._Object):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @header_field.setter
     def header_field(self, header_field):
         header_field_ptr = None
 
         if header_field is not None:
-            utils._check_type(header_field, bt2.fields._Field)
+            utils._check_type(header_field, bt2.field._Field)
             header_field_ptr = header_field._ptr
 
         ret = native_bt.event_set_header(self._ptr, header_field_ptr)
@@ -153,14 +153,14 @@ class _Event(object._Object):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @stream_event_context_field.setter
     def stream_event_context_field(self, stream_event_context):
         stream_event_context_ptr = None
 
         if stream_event_context is not None:
-            utils._check_type(stream_event_context, bt2.fields._Field)
+            utils._check_type(stream_event_context, bt2.field._Field)
             stream_event_context_ptr = stream_event_context._ptr
 
         ret = native_bt.event_set_stream_event_context(self._ptr,
@@ -174,14 +174,14 @@ class _Event(object._Object):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @context_field.setter
     def context_field(self, context):
         context_ptr = None
 
         if context is not None:
-            utils._check_type(context, bt2.fields._Field)
+            utils._check_type(context, bt2.field._Field)
             context_ptr = context._ptr
 
         ret = native_bt.event_set_event_context(self._ptr, context_ptr)
@@ -194,14 +194,14 @@ class _Event(object._Object):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @payload_field.setter
     def payload_field(self, payload):
         payload_ptr = None
 
         if payload is not None:
-            utils._check_type(payload, bt2.fields._Field)
+            utils._check_type(payload, bt2.field._Field)
             payload_ptr = payload._ptr
 
         ret = native_bt.event_set_event_payload(self._ptr, payload_ptr)
index 899a670b6576f2c5effc6a3d9c0b932ac39a6e8f..5259f9183667e86228cd86c4b1ae7bc93326f309 100644 (file)
@@ -23,7 +23,7 @@
 from bt2 import native_bt, object, utils
 import bt2.field_class
 import collections.abc
-import bt2.values
+import bt2.value
 import bt2.event
 import copy
 import bt2
diff --git a/bindings/python/bt2/bt2/field.py b/bindings/python/bt2/bt2/field.py
new file mode 100644 (file)
index 0000000..77c5803
--- /dev/null
@@ -0,0 +1,728 @@
+# The MIT License (MIT)
+#
+# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+from bt2 import native_bt, object, utils
+import bt2.field_class
+import collections.abc
+import functools
+import numbers
+import math
+import abc
+import bt2
+
+
+def _get_leaf_field(obj):
+    if type(obj) is not _VariantField:
+        return obj
+
+    return _get_leaf_field(obj.selected_field)
+
+
+def _create_from_ptr(ptr):
+    # recreate the field class wrapper of this field's type (the identity
+    # could be different, but the underlying address should be the
+    # same)
+    field_class_ptr = native_bt.field_get_type(ptr)
+    utils._handle_ptr(field_class_ptr, "cannot get field object's type")
+    field_class = bt2.field_class._create_from_ptr(field_class_ptr)
+    typeid = native_bt.field_class_get_type_id(field_class._ptr)
+    field = _TYPE_ID_TO_OBJ[typeid]._create_from_ptr(ptr)
+    field._field_class = field_class
+    return field
+
+
+class _Field(object._Object, metaclass=abc.ABCMeta):
+    def __copy__(self):
+        ptr = native_bt.field_copy(self._ptr)
+        utils._handle_ptr(ptr, 'cannot copy {} field object'.format(self._NAME.lower()))
+        return _create_from_ptr(ptr)
+
+    def __deepcopy__(self, memo):
+        cpy = self.__copy__()
+        memo[id(self)] = cpy
+        return cpy
+
+    def __eq__(self, other):
+        # special case: two unset fields with the same field class are equal
+        if isinstance(other, _Field):
+            if not self.is_set or not other.is_set:
+                if not self.is_set and not other.is_set and self.field_class == other.field_class:
+                    return True
+                return False
+
+        other = _get_leaf_field(other)
+        return self._spec_eq(other)
+
+    @property
+    def field_class(self):
+        return self._field_class
+
+    @property
+    def is_set(self):
+        is_set = native_bt.field_is_set(self._ptr)
+        return is_set > 0
+
+    def reset(self):
+        ret = native_bt.field_reset(self._ptr)
+        utils._handle_ret(ret, "cannot reset field object's value")
+
+    def _repr(self):
+        raise NotImplementedError
+
+    def __repr__(self):
+        return self._repr() if self.is_set else 'Unset'
+
+
+@functools.total_ordering
+class _NumericField(_Field):
+    @staticmethod
+    def _extract_value(other):
+        if other is True or other is False:
+            return other
+
+        if isinstance(other, numbers.Integral):
+            return int(other)
+
+        if isinstance(other, numbers.Real):
+            return float(other)
+
+        if isinstance(other, numbers.Complex):
+            return complex(other)
+
+        raise TypeError("'{}' object is not a number object".format(other.__class__.__name__))
+
+    def __int__(self):
+        return int(self._value)
+
+    def __float__(self):
+        return float(self._value)
+
+    def _repr(self):
+        return repr(self._value)
+
+    def __lt__(self, other):
+        if not isinstance(other, numbers.Number):
+            raise TypeError('unorderable types: {}() < {}()'.format(self.__class__.__name__,
+                                                                    other.__class__.__name__))
+
+        return self._value < float(other)
+
+    def __le__(self, other):
+        if not isinstance(other, numbers.Number):
+            raise TypeError('unorderable types: {}() <= {}()'.format(self.__class__.__name__,
+                                                                     other.__class__.__name__))
+
+        return self._value <= float(other)
+
+    def _spec_eq(self, other):
+        if not isinstance(other, numbers.Number):
+            return False
+
+        return self._value == complex(other)
+
+    def __rmod__(self, other):
+        return self._extract_value(other) % self._value
+
+    def __mod__(self, other):
+        return self._value % self._extract_value(other)
+
+    def __rfloordiv__(self, other):
+        return self._extract_value(other) // self._value
+
+    def __floordiv__(self, other):
+        return self._value // self._extract_value(other)
+
+    def __round__(self, ndigits=None):
+        if ndigits is None:
+            return round(self._value)
+        else:
+            return round(self._value, ndigits)
+
+    def __ceil__(self):
+        return math.ceil(self._value)
+
+    def __floor__(self):
+        return math.floor(self._value)
+
+    def __trunc__(self):
+        return int(self._value)
+
+    def __abs__(self):
+        return abs(self._value)
+
+    def __add__(self, other):
+        return self._value + self._extract_value(other)
+
+    def __radd__(self, other):
+        return self.__add__(other)
+
+    def __neg__(self):
+        return -self._value
+
+    def __pos__(self):
+        return +self._value
+
+    def __mul__(self, other):
+        return self._value * self._extract_value(other)
+
+    def __rmul__(self, other):
+        return self.__mul__(other)
+
+    def __truediv__(self, other):
+        return self._value / self._extract_value(other)
+
+    def __rtruediv__(self, other):
+        return self._extract_value(other) / self._value
+
+    def __pow__(self, exponent):
+        return self._value ** self._extract_value(exponent)
+
+    def __rpow__(self, base):
+        return self._extract_value(base) ** self._value
+
+    def __iadd__(self, other):
+        self.value = self + other
+        return self
+
+    def __isub__(self, other):
+        self.value = self - other
+        return self
+
+    def __imul__(self, other):
+        self.value = self * other
+        return self
+
+    def __itruediv__(self, other):
+        self.value = self / other
+        return self
+
+    def __ifloordiv__(self, other):
+        self.value = self // other
+        return self
+
+    def __imod__(self, other):
+        self.value = self % other
+        return self
+
+    def __ipow__(self, other):
+        self.value = self ** other
+        return self
+
+
+class _IntegralField(_NumericField, numbers.Integral):
+    def __lshift__(self, other):
+        return self._value << self._extract_value(other)
+
+    def __rlshift__(self, other):
+        return self._extract_value(other) << self._value
+
+    def __rshift__(self, other):
+        return self._value >> self._extract_value(other)
+
+    def __rrshift__(self, other):
+        return self._extract_value(other) >> self._value
+
+    def __and__(self, other):
+        return self._value & self._extract_value(other)
+
+    def __rand__(self, other):
+        return self._extract_value(other) & self._value
+
+    def __xor__(self, other):
+        return self._value ^ self._extract_value(other)
+
+    def __rxor__(self, other):
+        return self._extract_value(other) ^ self._value
+
+    def __or__(self, other):
+        return self._value | self._extract_value(other)
+
+    def __ror__(self, other):
+        return self._extract_value(other) | self._value
+
+    def __invert__(self):
+        return ~self._value
+
+    def __ilshift__(self, other):
+        self.value = self << other
+        return self
+
+    def __irshift__(self, other):
+        self.value = self >> other
+        return self
+
+    def __iand__(self, other):
+        self.value = self & other
+        return self
+
+    def __ixor__(self, other):
+        self.value = self ^ other
+        return self
+
+    def __ior__(self, other):
+        self.value = self | other
+        return self
+
+
+class _RealField(_NumericField, numbers.Real):
+    pass
+
+
+class _IntegerField(_IntegralField):
+    _NAME = 'Integer'
+
+    def _value_to_int(self, value):
+        if not isinstance(value, numbers.Real):
+            raise TypeError('expecting a real number object')
+
+        value = int(value)
+
+        if self.field_class.is_signed:
+            utils._check_int64(value)
+        else:
+            utils._check_uint64(value)
+
+        return value
+
+    @property
+    def _value(self):
+        if self.field_class.is_signed:
+            ret, value = native_bt.field_signed_integer_get_value(self._ptr)
+        else:
+            ret, value = native_bt.field_unsigned_integer_get_value(self._ptr)
+
+        if ret < 0:
+            if not self.is_set:
+                return
+
+            utils._handle_ret(ret, "cannot get integer field's value")
+
+        return value
+
+    def _set_value(self, value):
+        value = self._value_to_int(value)
+
+        if self.field_class.is_signed:
+            ret = native_bt.field_signed_integer_set_value(self._ptr, value)
+        else:
+            ret = native_bt.field_unsigned_integer_set_value(self._ptr, value)
+
+        utils._handle_ret(ret, "cannot set integer field object's value")
+
+    value = property(fset=_set_value)
+
+
+class _FloatingPointNumberField(_RealField):
+    _NAME = 'Floating point number'
+
+    def _value_to_float(self, value):
+        if not isinstance(value, numbers.Real):
+            raise TypeError("expecting a real number object")
+
+        return float(value)
+
+    @property
+    def _value(self):
+        ret, value = native_bt.field_floating_point_get_value(self._ptr)
+
+        if ret < 0:
+            if not self.is_set:
+                return
+
+            utils._handle_ret(ret, "cannot get floating point number field's value")
+
+        return value
+
+    def _set_value(self, value):
+        value = self._value_to_float(value)
+        ret = native_bt.field_floating_point_set_value(self._ptr, value)
+        utils._handle_ret(ret, "cannot set floating point number field object's value")
+
+    value = property(fset=_set_value)
+
+
+class _EnumerationField(_IntegerField):
+    _NAME = 'Enumeration'
+
+    @property
+    def integer_field(self):
+        int_field_ptr = native_bt.field_enumeration_get_container(self._ptr)
+        assert(int_field_ptr)
+        return _create_from_ptr(int_field_ptr)
+
+    def _set_value(self, value):
+        self.integer_field.value = value
+
+    def _repr(self):
+        labels = [repr(v.name) for v in self.mappings]
+        return '{} ({})'.format(self._value, ', '.join(labels))
+
+    value = property(fset=_set_value)
+
+    @property
+    def _value(self):
+        return self.integer_field._value
+
+    @property
+    def mappings(self):
+        iter_ptr = native_bt.field_enumeration_get_mappings(self._ptr)
+        assert(iter_ptr)
+        return bt2.field_class._EnumerationFieldClassMappingIterator(iter_ptr,
+                                                                    self.field_class.is_signed)
+
+
+@functools.total_ordering
+class _StringField(_Field, collections.abc.Sequence):
+    _NAME = 'String'
+
+    def _value_to_str(self, value):
+        if isinstance(value, self.__class__):
+            value = value._value
+
+        if not isinstance(value, str):
+            raise TypeError("expecting a 'str' object")
+
+        return value
+
+    @property
+    def _value(self):
+        value = native_bt.field_string_get_value(self._ptr)
+        return value
+
+    def _set_value(self, value):
+        value = self._value_to_str(value)
+        ret = native_bt.field_string_set_value(self._ptr, value)
+        utils._handle_ret(ret, "cannot set string field object's value")
+
+    value = property(fset=_set_value)
+
+    def _spec_eq(self, other):
+        try:
+            other = self._value_to_str(other)
+        except:
+            return False
+
+        return self._value == other
+
+    def __le__(self, other):
+        return self._value <= self._value_to_str(other)
+
+    def __lt__(self, other):
+        return self._value < self._value_to_str(other)
+
+    def __bool__(self):
+        return bool(self._value)
+
+    def _repr(self):
+        return repr(self._value)
+
+    def __str__(self):
+        return self._value if self.is_set else repr(self)
+
+    def __getitem__(self, index):
+        return self._value[index]
+
+    def __len__(self):
+        return len(self._value)
+
+    def __iadd__(self, value):
+        value = self._value_to_str(value)
+        ret = native_bt.field_string_append(self._ptr, value)
+        utils._handle_ret(ret, "cannot append to string field object's value")
+        return self
+
+
+class _ContainerField(_Field):
+    def __bool__(self):
+        return len(self) != 0
+
+    def __len__(self):
+        count = self._count()
+        assert(count >= 0)
+        return count
+
+    def __delitem__(self, index):
+        raise NotImplementedError
+
+
+class _StructureField(_ContainerField, collections.abc.MutableMapping):
+    _NAME = 'Structure'
+
+    def _count(self):
+        return len(self.field_class)
+
+    def __getitem__(self, key):
+        utils._check_str(key)
+        ptr = native_bt.field_structure_get_field_by_name(self._ptr, key)
+
+        if ptr is None:
+            raise KeyError(key)
+
+        return _create_from_ptr(ptr)
+
+    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 at_index(self, index):
+        utils._check_uint64(index)
+
+        if index >= len(self):
+            raise IndexError
+
+        field_ptr = native_bt.field_structure_get_field_by_index(self._ptr, index)
+        assert(field_ptr)
+        return _create_from_ptr(field_ptr)
+
+    def __iter__(self):
+        # same name iterator
+        return iter(self.field_class)
+
+    def _spec_eq(self, other):
+        try:
+            if len(self) != len(other):
+                return False
+
+            for self_key, self_value in self.items():
+                if self_key not in other:
+                    return False
+
+                other_value = other[self_key]
+
+                if self_value != other_value:
+                    return False
+
+            return True
+        except:
+            return False
+
+    @property
+    def _value(self):
+        return {key: value._value for key, value in self.items()}
+
+    def _set_value(self, values):
+        original_values = self._value
+
+        try:
+            for key, value in values.items():
+                self[key].value = value
+        except:
+            self.value = original_values
+            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))
+
+
+class _VariantField(_Field):
+    _NAME = 'Variant'
+
+    @property
+    def tag_field(self):
+        field_ptr = native_bt.field_variant_get_tag(self._ptr)
+
+        if field_ptr is None:
+            return
+
+        return _create_from_ptr(field_ptr)
+
+    @property
+    def selected_field(self):
+        return self.field()
+
+    def field(self, tag_field=None):
+        if tag_field is None:
+            field_ptr = native_bt.field_variant_get_current_field(self._ptr)
+
+            if field_ptr is None:
+                return
+        else:
+            utils._check_type(tag_field, _EnumerationField)
+            field_ptr = native_bt.field_variant_get_field(self._ptr, tag_field._ptr)
+            utils._handle_ptr(field_ptr, "cannot select variant field object's field")
+
+        return _create_from_ptr(field_ptr)
+
+    def _spec_eq(self, other):
+        return _get_leaf_field(self) == other
+
+    def __bool__(self):
+        return bool(self.selected_field)
+
+    def __str__(self):
+        return str(self.selected_field) if self.is_set else repr(self)
+
+    def _repr(self):
+        return repr(self.selected_field)
+
+    @property
+    def _value(self):
+        if self.selected_field is not None:
+            return self.selected_field._value
+
+    def _set_value(self, value):
+        self.selected_field.value = value
+
+    value = property(fset=_set_value)
+
+
+class _ArraySequenceField(_ContainerField, collections.abc.MutableSequence):
+    def __getitem__(self, index):
+        if not isinstance(index, numbers.Integral):
+            raise TypeError("'{}' is not an integral number object: invalid index".format(index.__class__.__name__))
+
+        index = int(index)
+
+        if index < 0 or index >= len(self):
+            raise IndexError('{} field object index is out of range'.format(self._NAME))
+
+        field_ptr = self._get_field_ptr_at_index(index)
+        assert(field_ptr)
+        return _create_from_ptr(field_ptr)
+
+    def __setitem__(self, index, value):
+        # we can only set numbers and strings
+        if not isinstance(value, (numbers.Number, _StringField, str)):
+            raise TypeError('expecting number or string object')
+
+        # 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
+
+    def _spec_eq(self, other):
+        try:
+            if len(self) != len(other):
+                return False
+
+            for self_field, other_field in zip(self, other):
+                if self_field != other_field:
+                    return False
+
+            return True
+        except:
+            return False
+
+    @property
+    def _value(self):
+        return [field._value for field in self]
+
+    def _repr(self):
+        return '[{}]'.format(', '.join([repr(v) for v in self]))
+
+
+class _ArrayField(_ArraySequenceField):
+    _NAME = 'Array'
+
+    def _count(self):
+        return self.field_class.length
+
+    def _get_field_ptr_at_index(self, index):
+        return native_bt.field_array_get_field(self._ptr, index)
+
+    def _set_value(self, values):
+        if len(self) != len(values):
+            raise ValueError(
+                'expected length of value and array field to match')
+
+        original_values = self._value
+        try:
+            for index, value in enumerate(values):
+                if value is not None:
+                    self[index].value = value
+                else:
+                    self[index].reset()
+        except:
+            self.value = original_values
+            raise
+
+    value = property(fset=_set_value)
+
+
+class _SequenceField(_ArraySequenceField):
+    _NAME = 'Sequence'
+
+    def _count(self):
+        return int(self.length_field)
+
+    @property
+    def length_field(self):
+        field_ptr = native_bt.field_sequence_get_length(self._ptr)
+        if field_ptr is None:
+            return
+        return _create_from_ptr(field_ptr)
+
+    @length_field.setter
+    def length_field(self, length_field):
+        utils._check_type(length_field, _IntegerField)
+        ret = native_bt.field_sequence_set_length(self._ptr, length_field._ptr)
+        utils._handle_ret(ret, "cannot set sequence field object's length field")
+
+    def _get_field_ptr_at_index(self, index):
+        return native_bt.field_sequence_get_field(self._ptr, index)
+
+    def _set_value(self, values):
+        original_length_field = self.length_field
+        if original_length_field is not None:
+            original_values = self._value
+
+        if len(values) != self.length_field:
+            if self.length_field is not None:
+                length_fc = self.length_field.field_class
+            else:
+                length_fc = bt2.IntegerFieldClass(size=64, is_signed=False)
+            self.length_field = length_fc(len(values))
+
+        try:
+            for index, value in enumerate(values):
+                if value is not None:
+                    self[index].value = value
+                else:
+                    self[index].reset()
+        except:
+            if original_length_field is not None:
+                self.length_field = original_length_field
+                self.value = original_values
+            else:
+                self.reset()
+            raise
+
+    value = property(fset=_set_value)
+
+
+_TYPE_ID_TO_OBJ = {
+}
index cd870ce85f033cdbc77044686a041dd53c30cfef..cec7cafba2aa4aa0ef8daaf25cafc0cc49207984 100644 (file)
@@ -22,7 +22,7 @@
 
 from bt2 import native_bt, object, utils
 import collections.abc
-import bt2.fields
+import bt2.field
 import abc
 import bt2
 
@@ -68,10 +68,10 @@ class _FieldClass(object._Object, metaclass=abc.ABCMeta):
         if field_ptr is None:
             raise bt2.CreationError('cannot create {} field object'.format(self._NAME.lower()))
 
-        field = bt2.fields._create_from_ptr(field_ptr)
+        field = bt2.field._create_from_ptr(field_ptr)
 
         if value is not None:
-            if not isinstance(field, (bt2.fields._IntegerField, bt2.fields._FloatingPointNumberField, bt2.fields._StringField)):
+            if not isinstance(field, (bt2.field._IntegerField, bt2.field._FloatingPointNumberField, bt2.field._StringField)):
                 raise bt2.Error('cannot assign an initial value to a {} field object'.format(field._NAME))
 
             field.value = value
diff --git a/bindings/python/bt2/bt2/fields.py b/bindings/python/bt2/bt2/fields.py
deleted file mode 100644 (file)
index 77c5803..0000000
+++ /dev/null
@@ -1,728 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-from bt2 import native_bt, object, utils
-import bt2.field_class
-import collections.abc
-import functools
-import numbers
-import math
-import abc
-import bt2
-
-
-def _get_leaf_field(obj):
-    if type(obj) is not _VariantField:
-        return obj
-
-    return _get_leaf_field(obj.selected_field)
-
-
-def _create_from_ptr(ptr):
-    # recreate the field class wrapper of this field's type (the identity
-    # could be different, but the underlying address should be the
-    # same)
-    field_class_ptr = native_bt.field_get_type(ptr)
-    utils._handle_ptr(field_class_ptr, "cannot get field object's type")
-    field_class = bt2.field_class._create_from_ptr(field_class_ptr)
-    typeid = native_bt.field_class_get_type_id(field_class._ptr)
-    field = _TYPE_ID_TO_OBJ[typeid]._create_from_ptr(ptr)
-    field._field_class = field_class
-    return field
-
-
-class _Field(object._Object, metaclass=abc.ABCMeta):
-    def __copy__(self):
-        ptr = native_bt.field_copy(self._ptr)
-        utils._handle_ptr(ptr, 'cannot copy {} field object'.format(self._NAME.lower()))
-        return _create_from_ptr(ptr)
-
-    def __deepcopy__(self, memo):
-        cpy = self.__copy__()
-        memo[id(self)] = cpy
-        return cpy
-
-    def __eq__(self, other):
-        # special case: two unset fields with the same field class are equal
-        if isinstance(other, _Field):
-            if not self.is_set or not other.is_set:
-                if not self.is_set and not other.is_set and self.field_class == other.field_class:
-                    return True
-                return False
-
-        other = _get_leaf_field(other)
-        return self._spec_eq(other)
-
-    @property
-    def field_class(self):
-        return self._field_class
-
-    @property
-    def is_set(self):
-        is_set = native_bt.field_is_set(self._ptr)
-        return is_set > 0
-
-    def reset(self):
-        ret = native_bt.field_reset(self._ptr)
-        utils._handle_ret(ret, "cannot reset field object's value")
-
-    def _repr(self):
-        raise NotImplementedError
-
-    def __repr__(self):
-        return self._repr() if self.is_set else 'Unset'
-
-
-@functools.total_ordering
-class _NumericField(_Field):
-    @staticmethod
-    def _extract_value(other):
-        if other is True or other is False:
-            return other
-
-        if isinstance(other, numbers.Integral):
-            return int(other)
-
-        if isinstance(other, numbers.Real):
-            return float(other)
-
-        if isinstance(other, numbers.Complex):
-            return complex(other)
-
-        raise TypeError("'{}' object is not a number object".format(other.__class__.__name__))
-
-    def __int__(self):
-        return int(self._value)
-
-    def __float__(self):
-        return float(self._value)
-
-    def _repr(self):
-        return repr(self._value)
-
-    def __lt__(self, other):
-        if not isinstance(other, numbers.Number):
-            raise TypeError('unorderable types: {}() < {}()'.format(self.__class__.__name__,
-                                                                    other.__class__.__name__))
-
-        return self._value < float(other)
-
-    def __le__(self, other):
-        if not isinstance(other, numbers.Number):
-            raise TypeError('unorderable types: {}() <= {}()'.format(self.__class__.__name__,
-                                                                     other.__class__.__name__))
-
-        return self._value <= float(other)
-
-    def _spec_eq(self, other):
-        if not isinstance(other, numbers.Number):
-            return False
-
-        return self._value == complex(other)
-
-    def __rmod__(self, other):
-        return self._extract_value(other) % self._value
-
-    def __mod__(self, other):
-        return self._value % self._extract_value(other)
-
-    def __rfloordiv__(self, other):
-        return self._extract_value(other) // self._value
-
-    def __floordiv__(self, other):
-        return self._value // self._extract_value(other)
-
-    def __round__(self, ndigits=None):
-        if ndigits is None:
-            return round(self._value)
-        else:
-            return round(self._value, ndigits)
-
-    def __ceil__(self):
-        return math.ceil(self._value)
-
-    def __floor__(self):
-        return math.floor(self._value)
-
-    def __trunc__(self):
-        return int(self._value)
-
-    def __abs__(self):
-        return abs(self._value)
-
-    def __add__(self, other):
-        return self._value + self._extract_value(other)
-
-    def __radd__(self, other):
-        return self.__add__(other)
-
-    def __neg__(self):
-        return -self._value
-
-    def __pos__(self):
-        return +self._value
-
-    def __mul__(self, other):
-        return self._value * self._extract_value(other)
-
-    def __rmul__(self, other):
-        return self.__mul__(other)
-
-    def __truediv__(self, other):
-        return self._value / self._extract_value(other)
-
-    def __rtruediv__(self, other):
-        return self._extract_value(other) / self._value
-
-    def __pow__(self, exponent):
-        return self._value ** self._extract_value(exponent)
-
-    def __rpow__(self, base):
-        return self._extract_value(base) ** self._value
-
-    def __iadd__(self, other):
-        self.value = self + other
-        return self
-
-    def __isub__(self, other):
-        self.value = self - other
-        return self
-
-    def __imul__(self, other):
-        self.value = self * other
-        return self
-
-    def __itruediv__(self, other):
-        self.value = self / other
-        return self
-
-    def __ifloordiv__(self, other):
-        self.value = self // other
-        return self
-
-    def __imod__(self, other):
-        self.value = self % other
-        return self
-
-    def __ipow__(self, other):
-        self.value = self ** other
-        return self
-
-
-class _IntegralField(_NumericField, numbers.Integral):
-    def __lshift__(self, other):
-        return self._value << self._extract_value(other)
-
-    def __rlshift__(self, other):
-        return self._extract_value(other) << self._value
-
-    def __rshift__(self, other):
-        return self._value >> self._extract_value(other)
-
-    def __rrshift__(self, other):
-        return self._extract_value(other) >> self._value
-
-    def __and__(self, other):
-        return self._value & self._extract_value(other)
-
-    def __rand__(self, other):
-        return self._extract_value(other) & self._value
-
-    def __xor__(self, other):
-        return self._value ^ self._extract_value(other)
-
-    def __rxor__(self, other):
-        return self._extract_value(other) ^ self._value
-
-    def __or__(self, other):
-        return self._value | self._extract_value(other)
-
-    def __ror__(self, other):
-        return self._extract_value(other) | self._value
-
-    def __invert__(self):
-        return ~self._value
-
-    def __ilshift__(self, other):
-        self.value = self << other
-        return self
-
-    def __irshift__(self, other):
-        self.value = self >> other
-        return self
-
-    def __iand__(self, other):
-        self.value = self & other
-        return self
-
-    def __ixor__(self, other):
-        self.value = self ^ other
-        return self
-
-    def __ior__(self, other):
-        self.value = self | other
-        return self
-
-
-class _RealField(_NumericField, numbers.Real):
-    pass
-
-
-class _IntegerField(_IntegralField):
-    _NAME = 'Integer'
-
-    def _value_to_int(self, value):
-        if not isinstance(value, numbers.Real):
-            raise TypeError('expecting a real number object')
-
-        value = int(value)
-
-        if self.field_class.is_signed:
-            utils._check_int64(value)
-        else:
-            utils._check_uint64(value)
-
-        return value
-
-    @property
-    def _value(self):
-        if self.field_class.is_signed:
-            ret, value = native_bt.field_signed_integer_get_value(self._ptr)
-        else:
-            ret, value = native_bt.field_unsigned_integer_get_value(self._ptr)
-
-        if ret < 0:
-            if not self.is_set:
-                return
-
-            utils._handle_ret(ret, "cannot get integer field's value")
-
-        return value
-
-    def _set_value(self, value):
-        value = self._value_to_int(value)
-
-        if self.field_class.is_signed:
-            ret = native_bt.field_signed_integer_set_value(self._ptr, value)
-        else:
-            ret = native_bt.field_unsigned_integer_set_value(self._ptr, value)
-
-        utils._handle_ret(ret, "cannot set integer field object's value")
-
-    value = property(fset=_set_value)
-
-
-class _FloatingPointNumberField(_RealField):
-    _NAME = 'Floating point number'
-
-    def _value_to_float(self, value):
-        if not isinstance(value, numbers.Real):
-            raise TypeError("expecting a real number object")
-
-        return float(value)
-
-    @property
-    def _value(self):
-        ret, value = native_bt.field_floating_point_get_value(self._ptr)
-
-        if ret < 0:
-            if not self.is_set:
-                return
-
-            utils._handle_ret(ret, "cannot get floating point number field's value")
-
-        return value
-
-    def _set_value(self, value):
-        value = self._value_to_float(value)
-        ret = native_bt.field_floating_point_set_value(self._ptr, value)
-        utils._handle_ret(ret, "cannot set floating point number field object's value")
-
-    value = property(fset=_set_value)
-
-
-class _EnumerationField(_IntegerField):
-    _NAME = 'Enumeration'
-
-    @property
-    def integer_field(self):
-        int_field_ptr = native_bt.field_enumeration_get_container(self._ptr)
-        assert(int_field_ptr)
-        return _create_from_ptr(int_field_ptr)
-
-    def _set_value(self, value):
-        self.integer_field.value = value
-
-    def _repr(self):
-        labels = [repr(v.name) for v in self.mappings]
-        return '{} ({})'.format(self._value, ', '.join(labels))
-
-    value = property(fset=_set_value)
-
-    @property
-    def _value(self):
-        return self.integer_field._value
-
-    @property
-    def mappings(self):
-        iter_ptr = native_bt.field_enumeration_get_mappings(self._ptr)
-        assert(iter_ptr)
-        return bt2.field_class._EnumerationFieldClassMappingIterator(iter_ptr,
-                                                                    self.field_class.is_signed)
-
-
-@functools.total_ordering
-class _StringField(_Field, collections.abc.Sequence):
-    _NAME = 'String'
-
-    def _value_to_str(self, value):
-        if isinstance(value, self.__class__):
-            value = value._value
-
-        if not isinstance(value, str):
-            raise TypeError("expecting a 'str' object")
-
-        return value
-
-    @property
-    def _value(self):
-        value = native_bt.field_string_get_value(self._ptr)
-        return value
-
-    def _set_value(self, value):
-        value = self._value_to_str(value)
-        ret = native_bt.field_string_set_value(self._ptr, value)
-        utils._handle_ret(ret, "cannot set string field object's value")
-
-    value = property(fset=_set_value)
-
-    def _spec_eq(self, other):
-        try:
-            other = self._value_to_str(other)
-        except:
-            return False
-
-        return self._value == other
-
-    def __le__(self, other):
-        return self._value <= self._value_to_str(other)
-
-    def __lt__(self, other):
-        return self._value < self._value_to_str(other)
-
-    def __bool__(self):
-        return bool(self._value)
-
-    def _repr(self):
-        return repr(self._value)
-
-    def __str__(self):
-        return self._value if self.is_set else repr(self)
-
-    def __getitem__(self, index):
-        return self._value[index]
-
-    def __len__(self):
-        return len(self._value)
-
-    def __iadd__(self, value):
-        value = self._value_to_str(value)
-        ret = native_bt.field_string_append(self._ptr, value)
-        utils._handle_ret(ret, "cannot append to string field object's value")
-        return self
-
-
-class _ContainerField(_Field):
-    def __bool__(self):
-        return len(self) != 0
-
-    def __len__(self):
-        count = self._count()
-        assert(count >= 0)
-        return count
-
-    def __delitem__(self, index):
-        raise NotImplementedError
-
-
-class _StructureField(_ContainerField, collections.abc.MutableMapping):
-    _NAME = 'Structure'
-
-    def _count(self):
-        return len(self.field_class)
-
-    def __getitem__(self, key):
-        utils._check_str(key)
-        ptr = native_bt.field_structure_get_field_by_name(self._ptr, key)
-
-        if ptr is None:
-            raise KeyError(key)
-
-        return _create_from_ptr(ptr)
-
-    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 at_index(self, index):
-        utils._check_uint64(index)
-
-        if index >= len(self):
-            raise IndexError
-
-        field_ptr = native_bt.field_structure_get_field_by_index(self._ptr, index)
-        assert(field_ptr)
-        return _create_from_ptr(field_ptr)
-
-    def __iter__(self):
-        # same name iterator
-        return iter(self.field_class)
-
-    def _spec_eq(self, other):
-        try:
-            if len(self) != len(other):
-                return False
-
-            for self_key, self_value in self.items():
-                if self_key not in other:
-                    return False
-
-                other_value = other[self_key]
-
-                if self_value != other_value:
-                    return False
-
-            return True
-        except:
-            return False
-
-    @property
-    def _value(self):
-        return {key: value._value for key, value in self.items()}
-
-    def _set_value(self, values):
-        original_values = self._value
-
-        try:
-            for key, value in values.items():
-                self[key].value = value
-        except:
-            self.value = original_values
-            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))
-
-
-class _VariantField(_Field):
-    _NAME = 'Variant'
-
-    @property
-    def tag_field(self):
-        field_ptr = native_bt.field_variant_get_tag(self._ptr)
-
-        if field_ptr is None:
-            return
-
-        return _create_from_ptr(field_ptr)
-
-    @property
-    def selected_field(self):
-        return self.field()
-
-    def field(self, tag_field=None):
-        if tag_field is None:
-            field_ptr = native_bt.field_variant_get_current_field(self._ptr)
-
-            if field_ptr is None:
-                return
-        else:
-            utils._check_type(tag_field, _EnumerationField)
-            field_ptr = native_bt.field_variant_get_field(self._ptr, tag_field._ptr)
-            utils._handle_ptr(field_ptr, "cannot select variant field object's field")
-
-        return _create_from_ptr(field_ptr)
-
-    def _spec_eq(self, other):
-        return _get_leaf_field(self) == other
-
-    def __bool__(self):
-        return bool(self.selected_field)
-
-    def __str__(self):
-        return str(self.selected_field) if self.is_set else repr(self)
-
-    def _repr(self):
-        return repr(self.selected_field)
-
-    @property
-    def _value(self):
-        if self.selected_field is not None:
-            return self.selected_field._value
-
-    def _set_value(self, value):
-        self.selected_field.value = value
-
-    value = property(fset=_set_value)
-
-
-class _ArraySequenceField(_ContainerField, collections.abc.MutableSequence):
-    def __getitem__(self, index):
-        if not isinstance(index, numbers.Integral):
-            raise TypeError("'{}' is not an integral number object: invalid index".format(index.__class__.__name__))
-
-        index = int(index)
-
-        if index < 0 or index >= len(self):
-            raise IndexError('{} field object index is out of range'.format(self._NAME))
-
-        field_ptr = self._get_field_ptr_at_index(index)
-        assert(field_ptr)
-        return _create_from_ptr(field_ptr)
-
-    def __setitem__(self, index, value):
-        # we can only set numbers and strings
-        if not isinstance(value, (numbers.Number, _StringField, str)):
-            raise TypeError('expecting number or string object')
-
-        # 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
-
-    def _spec_eq(self, other):
-        try:
-            if len(self) != len(other):
-                return False
-
-            for self_field, other_field in zip(self, other):
-                if self_field != other_field:
-                    return False
-
-            return True
-        except:
-            return False
-
-    @property
-    def _value(self):
-        return [field._value for field in self]
-
-    def _repr(self):
-        return '[{}]'.format(', '.join([repr(v) for v in self]))
-
-
-class _ArrayField(_ArraySequenceField):
-    _NAME = 'Array'
-
-    def _count(self):
-        return self.field_class.length
-
-    def _get_field_ptr_at_index(self, index):
-        return native_bt.field_array_get_field(self._ptr, index)
-
-    def _set_value(self, values):
-        if len(self) != len(values):
-            raise ValueError(
-                'expected length of value and array field to match')
-
-        original_values = self._value
-        try:
-            for index, value in enumerate(values):
-                if value is not None:
-                    self[index].value = value
-                else:
-                    self[index].reset()
-        except:
-            self.value = original_values
-            raise
-
-    value = property(fset=_set_value)
-
-
-class _SequenceField(_ArraySequenceField):
-    _NAME = 'Sequence'
-
-    def _count(self):
-        return int(self.length_field)
-
-    @property
-    def length_field(self):
-        field_ptr = native_bt.field_sequence_get_length(self._ptr)
-        if field_ptr is None:
-            return
-        return _create_from_ptr(field_ptr)
-
-    @length_field.setter
-    def length_field(self, length_field):
-        utils._check_type(length_field, _IntegerField)
-        ret = native_bt.field_sequence_set_length(self._ptr, length_field._ptr)
-        utils._handle_ret(ret, "cannot set sequence field object's length field")
-
-    def _get_field_ptr_at_index(self, index):
-        return native_bt.field_sequence_get_field(self._ptr, index)
-
-    def _set_value(self, values):
-        original_length_field = self.length_field
-        if original_length_field is not None:
-            original_values = self._value
-
-        if len(values) != self.length_field:
-            if self.length_field is not None:
-                length_fc = self.length_field.field_class
-            else:
-                length_fc = bt2.IntegerFieldClass(size=64, is_signed=False)
-            self.length_field = length_fc(len(values))
-
-        try:
-            for index, value in enumerate(values):
-                if value is not None:
-                    self[index].value = value
-                else:
-                    self[index].reset()
-        except:
-            if original_length_field is not None:
-                self.length_field = original_length_field
-                self.value = original_values
-            else:
-                self.reset()
-            raise
-
-    value = property(fset=_set_value)
-
-
-_TYPE_ID_TO_OBJ = {
-}
index 84302fa00c1c6e62b078f32a183898e656be4295..6f85a9884e18ea88cf3541957491f4fd32a7b66a 100644 (file)
@@ -21,7 +21,7 @@
 # THE SOFTWARE.
 
 from bt2 import native_bt, object, utils
-import bt2.fields
+import bt2.field
 import bt2.stream
 import copy
 import abc
@@ -42,14 +42,14 @@ class _Packet(object._Object):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @header_field.setter
     def header_field(self, header_field):
         header_field_ptr = None
 
         if header_field is not None:
-            utils._check_type(header_field, bt2.fields._Field)
+            utils._check_type(header_field, bt2.field._Field)
             header_field_ptr = header_field._ptr
 
         ret = native_bt.packet_set_header(self._ptr, header_field_ptr)
@@ -62,14 +62,14 @@ class _Packet(object._Object):
         if field_ptr is None:
             return
 
-        return bt2.fields._create_from_ptr(field_ptr)
+        return bt2.field._create_from_ptr(field_ptr)
 
     @context_field.setter
     def context_field(self, context_field):
         context_field_ptr = None
 
         if context_field is not None:
-            utils._check_type(context_field, bt2.fields._Field)
+            utils._check_type(context_field, bt2.field._Field)
             context_field_ptr = context_field._ptr
 
         ret = native_bt.packet_set_context(self._ptr, context_field_ptr)
index 00644166e20f2f248fc7ba599c3f28ed802547a2..25d77c04aa4c37b71aa90c6bcae814b079329928 100644 (file)
@@ -87,7 +87,7 @@ class QueryExecutor(object._Object):
                                                             object, params_ptr)
         self._handle_status(status, 'cannot query component class')
         assert(result_ptr)
-        return bt2.values._create_from_ptr(result_ptr)
+        return bt2.value._create_from_ptr(result_ptr)
 
     def __eq__(self, other):
         if type(other) is not type(self):
index 31548d6b2c6b9e6c2033db96ddbb7a0d51deac69..33fd8c08d8d2d4151ce71ffbb85caefaf5ac7890 100644 (file)
@@ -23,7 +23,7 @@
 from bt2 import native_bt, object, utils
 import bt2.field_class
 import collections.abc
-import bt2.values
+import bt2.value
 import bt2.stream
 import copy
 import bt2
@@ -139,7 +139,7 @@ class _TraceEnv(collections.abc.MutableMapping):
         if value_ptr is None:
             raise KeyError(key)
 
-        return bt2.values._create_from_ptr(value_ptr)
+        return bt2.value._create_from_ptr(value_ptr)
 
     def __setitem__(self, key, value):
         utils._check_str(key)
diff --git a/bindings/python/bt2/bt2/value.py b/bindings/python/bt2/bt2/value.py
new file mode 100644 (file)
index 0000000..f36d2ea
--- /dev/null
@@ -0,0 +1,736 @@
+# The MIT License (MIT)
+#
+# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+from bt2 import native_bt, object, utils
+import collections.abc
+import functools
+import numbers
+import math
+import abc
+import bt2
+
+
+def _handle_status(status, obj_name):
+    if status >= 0:
+        return
+
+    if status == native_bt.VALUE_STATUS_FROZEN:
+        raise bt2.Frozen('{} value object is frozen'.format(obj_name))
+    elif status == native_bt.VALUE_STATUS_INVAL:
+        # In practice, this should never happen, because arguments
+        # should always be validated in this Python module before
+        # calling the native functions.
+        raise ValueError('unexpected invalid argument')
+    else:
+        # In practice, this should never happen, because arguments
+        # should always be validated in this Python module before
+        # calling the native functions.
+        raise RuntimeError('unexpected error')
+
+
+def _create_from_ptr(ptr):
+    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(ptr)
+
+
+def create_value(value):
+    if value is None:
+        # null value object
+        return
+
+    if isinstance(value, _Value):
+        return value
+
+    if isinstance(value, bool):
+        return BoolValue(value)
+
+    if isinstance(value, int):
+        return IntegerValue(value)
+
+    if isinstance(value, float):
+        return FloatValue(value)
+
+    if isinstance(value, str):
+        return StringValue(value)
+
+    try:
+        return MapValue(value)
+    except:
+        pass
+
+    try:
+        return ArrayValue(value)
+    except:
+        pass
+
+    raise TypeError("cannot create value object from '{}' object".format(value.__class__.__name__))
+
+
+class _Value(object._Object, object._Freezable, metaclass=abc.ABCMeta):
+    def __eq__(self, other):
+        if other is None:
+            # self is never the null value object
+            return False
+
+        # try type-specific comparison first
+        spec_eq = self._spec_eq(other)
+
+        if spec_eq is not None:
+            return spec_eq
+
+        if not isinstance(other, _Value):
+            # not comparing apples to apples
+            return False
+
+        # fall back to native comparison function
+        return native_bt.value_compare(self._ptr, other._ptr)
+
+    def __ne__(self, other):
+        return not (self == other)
+
+    @abc.abstractmethod
+    def _spec_eq(self, other):
+        pass
+
+    def _handle_status(self, status):
+        _handle_status(status, self._NAME)
+
+    def _check_create_status(self, ptr):
+        if ptr is None:
+            raise bt2.CreationError('cannot create {} value object'.format(self._NAME.lower()))
+
+    def _is_frozen(self):
+        return native_bt.value_is_frozen(self._ptr)
+
+    def _freeze(self):
+        status = native_bt.value_freeze(self._ptr)
+        self._handle_status(status)
+
+
+class _BasicCopy:
+    def __copy__(self):
+        return self.__class__(self._value)
+
+    def __deepcopy__(self, memo):
+        copy = self.__copy__()
+        memo[id(self)] = copy
+        return copy
+
+
+@functools.total_ordering
+class _NumericValue(_Value, _BasicCopy):
+    @staticmethod
+    def _extract_value(other):
+        if isinstance(other, _NumericValue):
+            return other._value
+
+        if other is True or other is False:
+            return other
+
+        if isinstance(other, numbers.Integral):
+            return int(other)
+
+        if isinstance(other, numbers.Real):
+            return float(other)
+
+        if isinstance(other, numbers.Complex):
+            return complex(other)
+
+        raise TypeError("'{}' object is not a number object".format(other.__class__.__name__))
+
+    def __int__(self):
+        return int(self._value)
+
+    def __float__(self):
+        return float(self._value)
+
+    def __repr__(self):
+        return repr(self._value)
+
+    def __lt__(self, other):
+        if not isinstance(other, numbers.Number):
+            raise TypeError('unorderable types: {}() < {}()'.format(self.__class__.__name__,
+                                                                    other.__class__.__name__))
+
+        return self._value < float(other)
+
+    def __le__(self, other):
+        if not isinstance(other, numbers.Number):
+            raise TypeError('unorderable types: {}() <= {}()'.format(self.__class__.__name__,
+                                                                     other.__class__.__name__))
+
+        return self._value <= float(other)
+
+    def _spec_eq(self, other):
+        pass
+
+    def __eq__(self, other):
+        if not isinstance(other, numbers.Number):
+            return False
+
+        return self._value == complex(other)
+
+    def __rmod__(self, other):
+        return self._extract_value(other) % self._value
+
+    def __mod__(self, other):
+        return self._value % self._extract_value(other)
+
+    def __rfloordiv__(self, other):
+        return self._extract_value(other) // self._value
+
+    def __floordiv__(self, other):
+        return self._value // self._extract_value(other)
+
+    def __round__(self, ndigits=None):
+        if ndigits is None:
+            return round(self._value)
+        else:
+            return round(self._value, ndigits)
+
+    def __ceil__(self):
+        return math.ceil(self._value)
+
+    def __floor__(self):
+        return math.floor(self._value)
+
+    def __trunc__(self):
+        return int(self._value)
+
+    def __abs__(self):
+        return abs(self._value)
+
+    def __add__(self, other):
+        return self._value + self._extract_value(other)
+
+    def __radd__(self, other):
+        return self.__add__(other)
+
+    def __neg__(self):
+        return -self._value
+
+    def __pos__(self):
+        return +self._value
+
+    def __mul__(self, other):
+        return self._value * self._extract_value(other)
+
+    def __rmul__(self, other):
+        return self.__mul__(other)
+
+    def __truediv__(self, other):
+        return self._value / self._extract_value(other)
+
+    def __rtruediv__(self, other):
+        return self._extract_value(other) / self._value
+
+    def __pow__(self, exponent):
+        return self._value ** self._extract_value(exponent)
+
+    def __rpow__(self, base):
+        return self._extract_value(base) ** self._value
+
+    def __iadd__(self, other):
+        self.value = self + other
+        return self
+
+    def __isub__(self, other):
+        self.value = self - other
+        return self
+
+    def __imul__(self, other):
+        self.value = self * other
+        return self
+
+    def __itruediv__(self, other):
+        self.value = self / other
+        return self
+
+    def __ifloordiv__(self, other):
+        self.value = self // other
+        return self
+
+    def __imod__(self, other):
+        self.value = self % other
+        return self
+
+    def __ipow__(self, other):
+        self.value = self ** other
+        return self
+
+
+class _IntegralValue(_NumericValue, numbers.Integral):
+    def __lshift__(self, other):
+        return self._value << self._extract_value(other)
+
+    def __rlshift__(self, other):
+        return self._extract_value(other) << self._value
+
+    def __rshift__(self, other):
+        return self._value >> self._extract_value(other)
+
+    def __rrshift__(self, other):
+        return self._extract_value(other) >> self._value
+
+    def __and__(self, other):
+        return self._value & self._extract_value(other)
+
+    def __rand__(self, other):
+        return self._extract_value(other) & self._value
+
+    def __xor__(self, other):
+        return self._value ^ self._extract_value(other)
+
+    def __rxor__(self, other):
+        return self._extract_value(other) ^ self._value
+
+    def __or__(self, other):
+        return self._value | self._extract_value(other)
+
+    def __ror__(self, other):
+        return self._extract_value(other) | self._value
+
+    def __invert__(self):
+        return ~self._value
+
+    def __ilshift__(self, other):
+        self.value = self << other
+        return self
+
+    def __irshift__(self, other):
+        self.value = self >> other
+        return self
+
+    def __iand__(self, other):
+        self.value = self & other
+        return self
+
+    def __ixor__(self, other):
+        self.value = self ^ other
+        return self
+
+    def __ior__(self, other):
+        self.value = self | other
+        return self
+
+
+class _RealValue(_NumericValue, numbers.Real):
+    pass
+
+
+class BoolValue(_Value, _BasicCopy):
+    _NAME = 'Boolean'
+
+    def __init__(self, value=None):
+        if value is None:
+            ptr = native_bt.value_bool_create()
+        else:
+            ptr = native_bt.value_bool_create_init(self._value_to_bool(value))
+
+        self._check_create_status(ptr)
+        super().__init__(ptr)
+
+    def _spec_eq(self, other):
+        if isinstance(other, numbers.Number):
+            return self._value == bool(other)
+
+    def __bool__(self):
+        return self._value
+
+    def __repr__(self):
+        return repr(self._value)
+
+    def _value_to_bool(self, value):
+        if isinstance(value, BoolValue):
+            value = value._value
+
+        if not isinstance(value, bool):
+            raise TypeError("'{}' object is not a 'bool' or 'BoolValue' object".format(value.__class__))
+
+        return int(value)
+
+    @property
+    def _value(self):
+        status, value = native_bt.value_bool_get(self._ptr)
+        assert(status == native_bt.VALUE_STATUS_OK)
+        return value > 0
+
+    def _set_value(self, value):
+        status = native_bt.value_bool_set(self._ptr, self._value_to_bool(value))
+        self._handle_status(status)
+
+    value = property(fset=_set_value)
+
+
+class IntegerValue(_IntegralValue):
+    _NAME = 'Integer'
+
+    def __init__(self, value=None):
+        if value is None:
+            ptr = native_bt.value_integer_create()
+        else:
+            ptr = native_bt.value_integer_create_init(self._value_to_int(value))
+
+        self._check_create_status(ptr)
+        super().__init__(ptr)
+
+    def _value_to_int(self, value):
+        if not isinstance(value, numbers.Real):
+            raise TypeError('expecting a number object')
+
+        value = int(value)
+        utils._check_int64(value)
+        return value
+
+    @property
+    def _value(self):
+        status, value = native_bt.value_integer_get(self._ptr)
+        assert(status == native_bt.VALUE_STATUS_OK)
+        return value
+
+    def _set_value(self, value):
+        status = native_bt.value_integer_set(self._ptr, self._value_to_int(value))
+        self._handle_status(status)
+
+    value = property(fset=_set_value)
+
+
+class FloatValue(_RealValue):
+    _NAME = 'Floating point number'
+
+    def __init__(self, value=None):
+        if value is None:
+            ptr = native_bt.value_float_create()
+        else:
+            value = self._value_to_float(value)
+            ptr = native_bt.value_float_create_init(value)
+
+        self._check_create_status(ptr)
+        super().__init__(ptr)
+
+    def _value_to_float(self, value):
+        if not isinstance(value, numbers.Real):
+            raise TypeError("expecting a real number object")
+
+        return float(value)
+
+    @property
+    def _value(self):
+        status, value = native_bt.value_float_get(self._ptr)
+        assert(status == native_bt.VALUE_STATUS_OK)
+        return value
+
+    def _set_value(self, value):
+        value = self._value_to_float(value)
+        status = native_bt.value_float_set(self._ptr, value)
+        self._handle_status(status)
+
+    value = property(fset=_set_value)
+
+
+@functools.total_ordering
+class StringValue(_BasicCopy, collections.abc.Sequence, _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 _value_to_str(self, value):
+        if isinstance(value, self.__class__):
+            value = value._value
+
+        utils._check_str(value)
+        return value
+
+    @property
+    def _value(self):
+        status, value = native_bt.value_string_get(self._ptr)
+        assert(status == native_bt.VALUE_STATUS_OK)
+        return value
+
+    def _set_value(self, value):
+        status = native_bt.value_string_set(self._ptr, self._value_to_str(value))
+        self._handle_status(status)
+
+    value = property(fset=_set_value)
+
+    def _spec_eq(self, other):
+        try:
+            return self._value == self._value_to_str(other)
+        except:
+            return
+
+    def __le__(self, other):
+        return self._value <= self._value_to_str(other)
+
+    def __lt__(self, other):
+        return self._value < self._value_to_str(other)
+
+    def __bool__(self):
+        return bool(self._value)
+
+    def __repr__(self):
+        repr(self._value)
+
+    def __str__(self):
+        return self._value
+
+    def __getitem__(self, index):
+        return self._value[index]
+
+    def __len__(self):
+        return len(self._value)
+
+    def __iadd__(self, value):
+        curvalue = self._value
+        curvalue += self._value_to_str(value)
+        self.value = curvalue
+        return self
+
+
+class _Container:
+    def __bool__(self):
+        return len(self) != 0
+
+    def __copy__(self):
+        return self.__class__(self)
+
+    def __deepcopy__(self, memo):
+        ptr = native_bt.value_copy(self._ptr)
+
+        if ptr is None:
+            raise RuntimeError('unexpected error: cannot deep-copy {} value object'.format(self._NAME))
+
+        copy = self.__class__._create_from_ptr(ptr)
+        memo[id(self)] = copy
+        return copy
+
+    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)
+
+    def _spec_eq(self, other):
+        try:
+            if len(self) != len(other):
+                # early mismatch
+                return False
+
+            for self_elem, other_elem in zip(self, other):
+                if self_elem != other_elem:
+                    return False
+
+            return True
+        except:
+            return
+
+    def __len__(self):
+        size = native_bt.value_array_size(self._ptr)
+        assert(size >= 0)
+        return size
+
+    def _check_index(self, index):
+        # TODO: support slices also
+        if not isinstance(index, numbers.Integral):
+            raise TypeError("'{}' object is not an integral number object: invalid index".format(index.__class__.__name__))
+
+        index = int(index)
+
+        if index < 0 or index >= len(self):
+            raise IndexError('array value object index is out of range')
+
+    def __getitem__(self, index):
+        self._check_index(index)
+        ptr = native_bt.value_array_get(self._ptr, index)
+        assert(ptr)
+        return _create_from_ptr(ptr)
+
+    def __setitem__(self, index, value):
+        self._check_index(index)
+        value = create_value(value)
+
+        if value is None:
+            ptr = native_bt.value_null
+        else:
+            ptr = value._ptr
+
+        status = native_bt.value_array_set(self._ptr, index, ptr)
+        self._handle_status(status)
+
+    def append(self, value):
+        value = create_value(value)
+
+        if value is None:
+            ptr = native_bt.value_null
+        else:
+            ptr = value._ptr
+
+        status = native_bt.value_array_append(self._ptr, ptr)
+        self._handle_status(status)
+
+    def __iadd__(self, iterable):
+        # Python will raise a TypeError if there's anything wrong with
+        # the iterable protocol.
+        for elem in iterable:
+            self.append(elem)
+
+        return self
+
+    def __repr__(self):
+        return '[{}]'.format(', '.join([repr(v) for v in self]))
+
+    def insert(self, value):
+        raise NotImplementedError
+
+
+class _MapValueKeyIterator(collections.abc.Iterator):
+    def __init__(self, map_obj):
+        self._map_obj = map_obj
+        self._at = 0
+        keys_ptr = native_bt.value_map_get_keys_private(map_obj._ptr)
+
+        if keys_ptr is None:
+            raise RuntimeError('unexpected error: cannot get map value object keys')
+
+        self._keys = _create_from_ptr(keys_ptr)
+
+    def __next__(self):
+        if self._at == len(self._map_obj):
+            raise StopIteration
+
+        key = self._keys[self._at]
+        self._at += 1
+        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
+
+    def __eq__(self, other):
+        return _Value.__eq__(self, other)
+
+    def __ne__(self, other):
+        return _Value.__ne__(self, other)
+
+    def _spec_eq(self, other):
+        try:
+            if len(self) != len(other):
+                # early mismatch
+                return False
+
+            for self_key in self:
+                if self_key not in other:
+                    return False
+
+                self_value = self[self_key]
+                other_value = other[self_key]
+
+                if self_value != other_value:
+                    return False
+
+            return True
+        except:
+            return
+
+    def __len__(self):
+        size = native_bt.value_map_size(self._ptr)
+        assert(size >= 0)
+        return size
+
+    def __contains__(self, key):
+        self._check_key_type(key)
+        return native_bt.value_map_has_key(self._ptr, key)
+
+    def _check_key_type(self, key):
+        utils._check_str(key)
+
+    def _check_key(self, key):
+        if key not in self:
+            raise KeyError(key)
+
+    def __getitem__(self, key):
+        self._check_key(key)
+        ptr = native_bt.value_map_get(self._ptr, key)
+        assert(ptr)
+        return _create_from_ptr(ptr)
+
+    def __iter__(self):
+        return _MapValueKeyIterator(self)
+
+    def __setitem__(self, key, value):
+        self._check_key_type(key)
+        value = create_value(value)
+
+        if value is None:
+            ptr = native_bt.value_null
+        else:
+            ptr = value._ptr
+
+        status = native_bt.value_map_insert(self._ptr, key, ptr)
+        self._handle_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_INTEGER: IntegerValue,
+    native_bt.VALUE_TYPE_REAL: FloatValue,
+    native_bt.VALUE_TYPE_STRING: StringValue,
+    native_bt.VALUE_TYPE_ARRAY: ArrayValue,
+    native_bt.VALUE_TYPE_MAP: MapValue,
+}
diff --git a/bindings/python/bt2/bt2/values.py b/bindings/python/bt2/bt2/values.py
deleted file mode 100644 (file)
index f36d2ea..0000000
+++ /dev/null
@@ -1,736 +0,0 @@
-# The MIT License (MIT)
-#
-# Copyright (c) 2017 Philippe Proulx <pproulx@efficios.com>
-#
-# Permission is hereby granted, free of charge, to any person obtaining a copy
-# of this software and associated documentation files (the "Software"), to deal
-# in the Software without restriction, including without limitation the rights
-# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-# copies of the Software, and to permit persons to whom the Software is
-# furnished to do so, subject to the following conditions:
-#
-# The above copyright notice and this permission notice shall be included in
-# all copies or substantial portions of the Software.
-#
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-# THE SOFTWARE.
-
-from bt2 import native_bt, object, utils
-import collections.abc
-import functools
-import numbers
-import math
-import abc
-import bt2
-
-
-def _handle_status(status, obj_name):
-    if status >= 0:
-        return
-
-    if status == native_bt.VALUE_STATUS_FROZEN:
-        raise bt2.Frozen('{} value object is frozen'.format(obj_name))
-    elif status == native_bt.VALUE_STATUS_INVAL:
-        # In practice, this should never happen, because arguments
-        # should always be validated in this Python module before
-        # calling the native functions.
-        raise ValueError('unexpected invalid argument')
-    else:
-        # In practice, this should never happen, because arguments
-        # should always be validated in this Python module before
-        # calling the native functions.
-        raise RuntimeError('unexpected error')
-
-
-def _create_from_ptr(ptr):
-    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(ptr)
-
-
-def create_value(value):
-    if value is None:
-        # null value object
-        return
-
-    if isinstance(value, _Value):
-        return value
-
-    if isinstance(value, bool):
-        return BoolValue(value)
-
-    if isinstance(value, int):
-        return IntegerValue(value)
-
-    if isinstance(value, float):
-        return FloatValue(value)
-
-    if isinstance(value, str):
-        return StringValue(value)
-
-    try:
-        return MapValue(value)
-    except:
-        pass
-
-    try:
-        return ArrayValue(value)
-    except:
-        pass
-
-    raise TypeError("cannot create value object from '{}' object".format(value.__class__.__name__))
-
-
-class _Value(object._Object, object._Freezable, metaclass=abc.ABCMeta):
-    def __eq__(self, other):
-        if other is None:
-            # self is never the null value object
-            return False
-
-        # try type-specific comparison first
-        spec_eq = self._spec_eq(other)
-
-        if spec_eq is not None:
-            return spec_eq
-
-        if not isinstance(other, _Value):
-            # not comparing apples to apples
-            return False
-
-        # fall back to native comparison function
-        return native_bt.value_compare(self._ptr, other._ptr)
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    @abc.abstractmethod
-    def _spec_eq(self, other):
-        pass
-
-    def _handle_status(self, status):
-        _handle_status(status, self._NAME)
-
-    def _check_create_status(self, ptr):
-        if ptr is None:
-            raise bt2.CreationError('cannot create {} value object'.format(self._NAME.lower()))
-
-    def _is_frozen(self):
-        return native_bt.value_is_frozen(self._ptr)
-
-    def _freeze(self):
-        status = native_bt.value_freeze(self._ptr)
-        self._handle_status(status)
-
-
-class _BasicCopy:
-    def __copy__(self):
-        return self.__class__(self._value)
-
-    def __deepcopy__(self, memo):
-        copy = self.__copy__()
-        memo[id(self)] = copy
-        return copy
-
-
-@functools.total_ordering
-class _NumericValue(_Value, _BasicCopy):
-    @staticmethod
-    def _extract_value(other):
-        if isinstance(other, _NumericValue):
-            return other._value
-
-        if other is True or other is False:
-            return other
-
-        if isinstance(other, numbers.Integral):
-            return int(other)
-
-        if isinstance(other, numbers.Real):
-            return float(other)
-
-        if isinstance(other, numbers.Complex):
-            return complex(other)
-
-        raise TypeError("'{}' object is not a number object".format(other.__class__.__name__))
-
-    def __int__(self):
-        return int(self._value)
-
-    def __float__(self):
-        return float(self._value)
-
-    def __repr__(self):
-        return repr(self._value)
-
-    def __lt__(self, other):
-        if not isinstance(other, numbers.Number):
-            raise TypeError('unorderable types: {}() < {}()'.format(self.__class__.__name__,
-                                                                    other.__class__.__name__))
-
-        return self._value < float(other)
-
-    def __le__(self, other):
-        if not isinstance(other, numbers.Number):
-            raise TypeError('unorderable types: {}() <= {}()'.format(self.__class__.__name__,
-                                                                     other.__class__.__name__))
-
-        return self._value <= float(other)
-
-    def _spec_eq(self, other):
-        pass
-
-    def __eq__(self, other):
-        if not isinstance(other, numbers.Number):
-            return False
-
-        return self._value == complex(other)
-
-    def __rmod__(self, other):
-        return self._extract_value(other) % self._value
-
-    def __mod__(self, other):
-        return self._value % self._extract_value(other)
-
-    def __rfloordiv__(self, other):
-        return self._extract_value(other) // self._value
-
-    def __floordiv__(self, other):
-        return self._value // self._extract_value(other)
-
-    def __round__(self, ndigits=None):
-        if ndigits is None:
-            return round(self._value)
-        else:
-            return round(self._value, ndigits)
-
-    def __ceil__(self):
-        return math.ceil(self._value)
-
-    def __floor__(self):
-        return math.floor(self._value)
-
-    def __trunc__(self):
-        return int(self._value)
-
-    def __abs__(self):
-        return abs(self._value)
-
-    def __add__(self, other):
-        return self._value + self._extract_value(other)
-
-    def __radd__(self, other):
-        return self.__add__(other)
-
-    def __neg__(self):
-        return -self._value
-
-    def __pos__(self):
-        return +self._value
-
-    def __mul__(self, other):
-        return self._value * self._extract_value(other)
-
-    def __rmul__(self, other):
-        return self.__mul__(other)
-
-    def __truediv__(self, other):
-        return self._value / self._extract_value(other)
-
-    def __rtruediv__(self, other):
-        return self._extract_value(other) / self._value
-
-    def __pow__(self, exponent):
-        return self._value ** self._extract_value(exponent)
-
-    def __rpow__(self, base):
-        return self._extract_value(base) ** self._value
-
-    def __iadd__(self, other):
-        self.value = self + other
-        return self
-
-    def __isub__(self, other):
-        self.value = self - other
-        return self
-
-    def __imul__(self, other):
-        self.value = self * other
-        return self
-
-    def __itruediv__(self, other):
-        self.value = self / other
-        return self
-
-    def __ifloordiv__(self, other):
-        self.value = self // other
-        return self
-
-    def __imod__(self, other):
-        self.value = self % other
-        return self
-
-    def __ipow__(self, other):
-        self.value = self ** other
-        return self
-
-
-class _IntegralValue(_NumericValue, numbers.Integral):
-    def __lshift__(self, other):
-        return self._value << self._extract_value(other)
-
-    def __rlshift__(self, other):
-        return self._extract_value(other) << self._value
-
-    def __rshift__(self, other):
-        return self._value >> self._extract_value(other)
-
-    def __rrshift__(self, other):
-        return self._extract_value(other) >> self._value
-
-    def __and__(self, other):
-        return self._value & self._extract_value(other)
-
-    def __rand__(self, other):
-        return self._extract_value(other) & self._value
-
-    def __xor__(self, other):
-        return self._value ^ self._extract_value(other)
-
-    def __rxor__(self, other):
-        return self._extract_value(other) ^ self._value
-
-    def __or__(self, other):
-        return self._value | self._extract_value(other)
-
-    def __ror__(self, other):
-        return self._extract_value(other) | self._value
-
-    def __invert__(self):
-        return ~self._value
-
-    def __ilshift__(self, other):
-        self.value = self << other
-        return self
-
-    def __irshift__(self, other):
-        self.value = self >> other
-        return self
-
-    def __iand__(self, other):
-        self.value = self & other
-        return self
-
-    def __ixor__(self, other):
-        self.value = self ^ other
-        return self
-
-    def __ior__(self, other):
-        self.value = self | other
-        return self
-
-
-class _RealValue(_NumericValue, numbers.Real):
-    pass
-
-
-class BoolValue(_Value, _BasicCopy):
-    _NAME = 'Boolean'
-
-    def __init__(self, value=None):
-        if value is None:
-            ptr = native_bt.value_bool_create()
-        else:
-            ptr = native_bt.value_bool_create_init(self._value_to_bool(value))
-
-        self._check_create_status(ptr)
-        super().__init__(ptr)
-
-    def _spec_eq(self, other):
-        if isinstance(other, numbers.Number):
-            return self._value == bool(other)
-
-    def __bool__(self):
-        return self._value
-
-    def __repr__(self):
-        return repr(self._value)
-
-    def _value_to_bool(self, value):
-        if isinstance(value, BoolValue):
-            value = value._value
-
-        if not isinstance(value, bool):
-            raise TypeError("'{}' object is not a 'bool' or 'BoolValue' object".format(value.__class__))
-
-        return int(value)
-
-    @property
-    def _value(self):
-        status, value = native_bt.value_bool_get(self._ptr)
-        assert(status == native_bt.VALUE_STATUS_OK)
-        return value > 0
-
-    def _set_value(self, value):
-        status = native_bt.value_bool_set(self._ptr, self._value_to_bool(value))
-        self._handle_status(status)
-
-    value = property(fset=_set_value)
-
-
-class IntegerValue(_IntegralValue):
-    _NAME = 'Integer'
-
-    def __init__(self, value=None):
-        if value is None:
-            ptr = native_bt.value_integer_create()
-        else:
-            ptr = native_bt.value_integer_create_init(self._value_to_int(value))
-
-        self._check_create_status(ptr)
-        super().__init__(ptr)
-
-    def _value_to_int(self, value):
-        if not isinstance(value, numbers.Real):
-            raise TypeError('expecting a number object')
-
-        value = int(value)
-        utils._check_int64(value)
-        return value
-
-    @property
-    def _value(self):
-        status, value = native_bt.value_integer_get(self._ptr)
-        assert(status == native_bt.VALUE_STATUS_OK)
-        return value
-
-    def _set_value(self, value):
-        status = native_bt.value_integer_set(self._ptr, self._value_to_int(value))
-        self._handle_status(status)
-
-    value = property(fset=_set_value)
-
-
-class FloatValue(_RealValue):
-    _NAME = 'Floating point number'
-
-    def __init__(self, value=None):
-        if value is None:
-            ptr = native_bt.value_float_create()
-        else:
-            value = self._value_to_float(value)
-            ptr = native_bt.value_float_create_init(value)
-
-        self._check_create_status(ptr)
-        super().__init__(ptr)
-
-    def _value_to_float(self, value):
-        if not isinstance(value, numbers.Real):
-            raise TypeError("expecting a real number object")
-
-        return float(value)
-
-    @property
-    def _value(self):
-        status, value = native_bt.value_float_get(self._ptr)
-        assert(status == native_bt.VALUE_STATUS_OK)
-        return value
-
-    def _set_value(self, value):
-        value = self._value_to_float(value)
-        status = native_bt.value_float_set(self._ptr, value)
-        self._handle_status(status)
-
-    value = property(fset=_set_value)
-
-
-@functools.total_ordering
-class StringValue(_BasicCopy, collections.abc.Sequence, _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 _value_to_str(self, value):
-        if isinstance(value, self.__class__):
-            value = value._value
-
-        utils._check_str(value)
-        return value
-
-    @property
-    def _value(self):
-        status, value = native_bt.value_string_get(self._ptr)
-        assert(status == native_bt.VALUE_STATUS_OK)
-        return value
-
-    def _set_value(self, value):
-        status = native_bt.value_string_set(self._ptr, self._value_to_str(value))
-        self._handle_status(status)
-
-    value = property(fset=_set_value)
-
-    def _spec_eq(self, other):
-        try:
-            return self._value == self._value_to_str(other)
-        except:
-            return
-
-    def __le__(self, other):
-        return self._value <= self._value_to_str(other)
-
-    def __lt__(self, other):
-        return self._value < self._value_to_str(other)
-
-    def __bool__(self):
-        return bool(self._value)
-
-    def __repr__(self):
-        repr(self._value)
-
-    def __str__(self):
-        return self._value
-
-    def __getitem__(self, index):
-        return self._value[index]
-
-    def __len__(self):
-        return len(self._value)
-
-    def __iadd__(self, value):
-        curvalue = self._value
-        curvalue += self._value_to_str(value)
-        self.value = curvalue
-        return self
-
-
-class _Container:
-    def __bool__(self):
-        return len(self) != 0
-
-    def __copy__(self):
-        return self.__class__(self)
-
-    def __deepcopy__(self, memo):
-        ptr = native_bt.value_copy(self._ptr)
-
-        if ptr is None:
-            raise RuntimeError('unexpected error: cannot deep-copy {} value object'.format(self._NAME))
-
-        copy = self.__class__._create_from_ptr(ptr)
-        memo[id(self)] = copy
-        return copy
-
-    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)
-
-    def _spec_eq(self, other):
-        try:
-            if len(self) != len(other):
-                # early mismatch
-                return False
-
-            for self_elem, other_elem in zip(self, other):
-                if self_elem != other_elem:
-                    return False
-
-            return True
-        except:
-            return
-
-    def __len__(self):
-        size = native_bt.value_array_size(self._ptr)
-        assert(size >= 0)
-        return size
-
-    def _check_index(self, index):
-        # TODO: support slices also
-        if not isinstance(index, numbers.Integral):
-            raise TypeError("'{}' object is not an integral number object: invalid index".format(index.__class__.__name__))
-
-        index = int(index)
-
-        if index < 0 or index >= len(self):
-            raise IndexError('array value object index is out of range')
-
-    def __getitem__(self, index):
-        self._check_index(index)
-        ptr = native_bt.value_array_get(self._ptr, index)
-        assert(ptr)
-        return _create_from_ptr(ptr)
-
-    def __setitem__(self, index, value):
-        self._check_index(index)
-        value = create_value(value)
-
-        if value is None:
-            ptr = native_bt.value_null
-        else:
-            ptr = value._ptr
-
-        status = native_bt.value_array_set(self._ptr, index, ptr)
-        self._handle_status(status)
-
-    def append(self, value):
-        value = create_value(value)
-
-        if value is None:
-            ptr = native_bt.value_null
-        else:
-            ptr = value._ptr
-
-        status = native_bt.value_array_append(self._ptr, ptr)
-        self._handle_status(status)
-
-    def __iadd__(self, iterable):
-        # Python will raise a TypeError if there's anything wrong with
-        # the iterable protocol.
-        for elem in iterable:
-            self.append(elem)
-
-        return self
-
-    def __repr__(self):
-        return '[{}]'.format(', '.join([repr(v) for v in self]))
-
-    def insert(self, value):
-        raise NotImplementedError
-
-
-class _MapValueKeyIterator(collections.abc.Iterator):
-    def __init__(self, map_obj):
-        self._map_obj = map_obj
-        self._at = 0
-        keys_ptr = native_bt.value_map_get_keys_private(map_obj._ptr)
-
-        if keys_ptr is None:
-            raise RuntimeError('unexpected error: cannot get map value object keys')
-
-        self._keys = _create_from_ptr(keys_ptr)
-
-    def __next__(self):
-        if self._at == len(self._map_obj):
-            raise StopIteration
-
-        key = self._keys[self._at]
-        self._at += 1
-        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
-
-    def __eq__(self, other):
-        return _Value.__eq__(self, other)
-
-    def __ne__(self, other):
-        return _Value.__ne__(self, other)
-
-    def _spec_eq(self, other):
-        try:
-            if len(self) != len(other):
-                # early mismatch
-                return False
-
-            for self_key in self:
-                if self_key not in other:
-                    return False
-
-                self_value = self[self_key]
-                other_value = other[self_key]
-
-                if self_value != other_value:
-                    return False
-
-            return True
-        except:
-            return
-
-    def __len__(self):
-        size = native_bt.value_map_size(self._ptr)
-        assert(size >= 0)
-        return size
-
-    def __contains__(self, key):
-        self._check_key_type(key)
-        return native_bt.value_map_has_key(self._ptr, key)
-
-    def _check_key_type(self, key):
-        utils._check_str(key)
-
-    def _check_key(self, key):
-        if key not in self:
-            raise KeyError(key)
-
-    def __getitem__(self, key):
-        self._check_key(key)
-        ptr = native_bt.value_map_get(self._ptr, key)
-        assert(ptr)
-        return _create_from_ptr(ptr)
-
-    def __iter__(self):
-        return _MapValueKeyIterator(self)
-
-    def __setitem__(self, key, value):
-        self._check_key_type(key)
-        value = create_value(value)
-
-        if value is None:
-            ptr = native_bt.value_null
-        else:
-            ptr = value._ptr
-
-        status = native_bt.value_map_insert(self._ptr, key, ptr)
-        self._handle_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_INTEGER: IntegerValue,
-    native_bt.VALUE_TYPE_REAL: FloatValue,
-    native_bt.VALUE_TYPE_STRING: StringValue,
-    native_bt.VALUE_TYPE_ARRAY: ArrayValue,
-    native_bt.VALUE_TYPE_MAP: MapValue,
-}
index ae8f9b08e0acbbd1b1487d3615849a3351e2a283..77d346b62c7cdea1024b84623029470d9c4cd6fb 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index a4b7e05d4c8f1968493f19421039f6987e6d3310..a9cb9fe95d084548bcff3457fffd0fb2d87dafa8 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index 163e067e44df3d0f47e3d687c6fe63abfa65a203..1ff932835bf332011e5939fce7a3154e42b06171 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index 21329b5b2e84cf04fd3ea99cb3960d2b6e797cb5..d15517789e5c8a02b7b8f7aa396fc9b04a7e1991 100644 (file)
@@ -1,5 +1,5 @@
 from collections import OrderedDict
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index bd8636338d5f3e5700f5fbeec728d0261d4455ec..153a21d4b5df27664fa5d4fce08f65a012ce6046 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
diff --git a/tests/bindings/python/bt2/test_field.py b/tests/bindings/python/bt2/test_field.py
new file mode 100644 (file)
index 0000000..97d5a4f
--- /dev/null
@@ -0,0 +1,1675 @@
+from functools import partial, partialmethod
+import operator
+import unittest
+import numbers
+import math
+import copy
+import itertools
+import bt2
+
+
+class _TestCopySimple:
+    def test_copy(self):
+        cpy = copy.copy(self._def)
+        self.assertIsNot(cpy, self._def)
+        self.assertNotEqual(cpy.addr, self._def.addr)
+        self.assertEqual(cpy, self._def)
+
+    def test_deepcopy(self):
+        cpy = copy.deepcopy(self._def)
+        self.assertIsNot(cpy, self._def)
+        self.assertNotEqual(cpy.addr, self._def.addr)
+        self.assertEqual(cpy, self._def)
+
+
+_COMP_BINOPS = (
+    operator.eq,
+    operator.ne,
+)
+
+
+class _TestNumericField(_TestCopySimple):
+    def _binop(self, op, rhs):
+        rexc = None
+        rvexc = None
+        comp_value = rhs
+
+        if isinstance(rhs, (bt2.field._IntegerField, bt2.field._FloatingPointNumberField)):
+            comp_value = copy.copy(rhs)
+
+        try:
+            r = op(self._def, rhs)
+        except Exception as e:
+            rexc = e
+
+        try:
+            rv = op(self._def_value, comp_value)
+        except Exception as e:
+            rvexc = e
+
+        if rexc is not None or rvexc is not None:
+            # at least one of the operations raised an exception: in
+            # this case both operations should have raised the same
+            # type of exception (division by zero, bit shift with a
+            # floating point number operand, etc.)
+            self.assertIs(type(rexc), type(rvexc))
+            return None, None
+
+        return r, rv
+
+    def _unaryop(self, op):
+        rexc = None
+        rvexc = None
+
+        try:
+            r = op(self._def)
+        except Exception as e:
+            rexc = e
+
+        try:
+            rv = op(self._def_value)
+        except Exception as e:
+            rvexc = e
+
+        if rexc is not None or rvexc is not None:
+            # at least one of the operations raised an exception: in
+            # this case both operations should have raised the same
+            # type of exception (division by zero, bit shift with a
+            # floating point number operand, etc.)
+            self.assertIs(type(rexc), type(rvexc))
+            return None, None
+
+        return r, rv
+
+    def _test_unaryop_type(self, op):
+        r, rv = self._unaryop(op)
+
+        if r is None:
+            return
+
+        self.assertIsInstance(r, type(rv))
+
+    def _test_unaryop_value(self, op):
+        r, rv = self._unaryop(op)
+
+        if r is None:
+            return
+
+        self.assertEqual(r, rv)
+
+    def _test_unaryop_addr_same(self, op):
+        addr_before = self._def.addr
+        self._unaryop(op)
+        self.assertEqual(self._def.addr, addr_before)
+
+    def _test_unaryop_value_same(self, op):
+        value_before = copy.copy(self._def_value)
+        self._unaryop(op)
+        self.assertEqual(self._def, value_before)
+
+    def _test_binop_type(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        if op in _COMP_BINOPS:
+            # __eq__() and __ne__() always return a 'bool' object
+            self.assertIsInstance(r, bool)
+        else:
+            self.assertIsInstance(r, type(rv))
+
+    def _test_binop_value(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        self.assertEqual(r, rv)
+
+    def _test_binop_lhs_addr_same(self, op, rhs):
+        addr_before = self._def.addr
+        r, rv = self._binop(op, rhs)
+        self.assertEqual(self._def.addr, addr_before)
+
+    def _test_binop_lhs_value_same(self, op, rhs):
+        value_before = copy.copy(self._def)
+        r, rv = self._binop(op, rhs)
+        self.assertEqual(self._def, value_before)
+
+    def _test_binop_invalid_unknown(self, op):
+        if op in _COMP_BINOPS:
+            self.skipTest('not testing')
+
+        class A:
+            pass
+
+        with self.assertRaises(TypeError):
+            op(self._def, A())
+
+    def _test_binop_invalid_none(self, op):
+        if op in _COMP_BINOPS:
+            self.skipTest('not testing')
+
+        with self.assertRaises(TypeError):
+            op(self._def, None)
+
+    def _test_ibinop_value(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        # The inplace operators are special for field objects because
+        # they do not return a new, immutable object like it's the case
+        # for Python numbers. In Python, `a += 2`, where `a` is a number
+        # object, assigns a new number object reference to `a`, dropping
+        # the old reference. Since BT's field objects are mutable, we
+        # modify their internal value with the inplace operators. This
+        # means however that we can lose data in the process, for
+        # example:
+        #
+        #     int_value_obj += 3.3
+        #
+        # Here, if `int_value_obj` is a Python `int` with the value 2,
+        # it would be a `float` object after this, holding the value
+        # 5.3. In our case, if `int_value_obj` is an integer field
+        # object, 3.3 is converted to an `int` object (3) and added to
+        # the current value of `int_value_obj`, so after this the value
+        # of the object is 5. This does not compare to 5.3, which is
+        # why we also use the `int()` type here.
+        if isinstance(self._def, bt2.field._IntegerField):
+            rv = int(rv)
+
+        self.assertEqual(r, rv)
+
+    def _test_ibinop_type(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        self.assertIs(r, self._def)
+
+    def _test_ibinop_invalid_unknown(self, op):
+        class A:
+            pass
+
+        with self.assertRaises(TypeError):
+            op(self._def, A())
+
+    def _test_ibinop_invalid_none(self, op):
+        with self.assertRaises(TypeError):
+            op(self._def, None)
+
+    def _test_binop_rhs_false(self, test_cb, op):
+        test_cb(op, False)
+
+    def _test_binop_rhs_true(self, test_cb, op):
+        test_cb(op, True)
+
+    def _test_binop_rhs_pos_int(self, test_cb, op):
+        test_cb(op, 2)
+
+    def _test_binop_rhs_neg_int(self, test_cb, op):
+        test_cb(op, -23)
+
+    def _test_binop_rhs_zero_int(self, test_cb, op):
+        test_cb(op, 0)
+
+    def _test_binop_rhs_pos_vint(self, test_cb, op):
+        test_cb(op, bt2.create_value(2))
+
+    def _test_binop_rhs_neg_vint(self, test_cb, op):
+        test_cb(op, bt2.create_value(-23))
+
+    def _test_binop_rhs_zero_vint(self, test_cb, op):
+        test_cb(op, bt2.create_value(0))
+
+    def _test_binop_rhs_pos_float(self, test_cb, op):
+        test_cb(op, 2.2)
+
+    def _test_binop_rhs_neg_float(self, test_cb, op):
+        test_cb(op, -23.4)
+
+    def _test_binop_rhs_zero_float(self, test_cb, op):
+        test_cb(op, 0.0)
+
+    def _test_binop_rhs_pos_vfloat(self, test_cb, op):
+        test_cb(op, bt2.create_value(2.2))
+
+    def _test_binop_rhs_neg_vfloat(self, test_cb, op):
+        test_cb(op, bt2.create_value(-23.4))
+
+    def _test_binop_rhs_zero_vfloat(self, test_cb, op):
+        test_cb(op, bt2.create_value(0.0))
+
+    def _test_binop_type_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_type, op)
+
+    def _test_binop_type_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_type, op)
+
+    def _test_binop_type_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_type, op)
+
+    def _test_binop_type_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_type, op)
+
+    def _test_binop_type_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_type, op)
+
+    def _test_binop_type_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_type, op)
+
+    def _test_binop_type_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_type, op)
+
+    def _test_binop_type_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_type, op)
+
+    def _test_binop_type_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_type, op)
+
+    def _test_binop_type_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_type, op)
+
+    def _test_binop_type_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_type, op)
+
+    def _test_binop_type_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_type, op)
+
+    def _test_binop_type_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_type, op)
+
+    def _test_binop_type_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_type, op)
+
+    def _test_binop_value_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_value, op)
+
+    def _test_binop_value_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_value, op)
+
+    def _test_binop_value_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_value, op)
+
+    def _test_binop_value_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_value, op)
+
+    def _test_binop_value_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_value, op)
+
+    def _test_binop_value_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_value, op)
+
+    def _test_binop_value_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_value, op)
+
+    def _test_binop_value_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_value, op)
+
+    def _test_binop_value_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_value, op)
+
+    def _test_binop_value_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_value, op)
+
+    def _test_binop_value_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_value, op)
+
+    def _test_binop_value_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_value, op)
+
+    def _test_binop_value_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_value, op)
+
+    def _test_binop_value_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_value, op)
+
+    def _test_binop_lhs_addr_same_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_value_same_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_value_same, op)
+
+    def _test_ibinop_type_false(self, op):
+        self._test_binop_rhs_false(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_true(self, op):
+        self._test_binop_rhs_true(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_ibinop_type, op)
+
+    def _test_ibinop_value_false(self, op):
+        self._test_binop_rhs_false(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_true(self, op):
+        self._test_binop_rhs_true(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_ibinop_value, op)
+
+    def test_bool_op(self):
+        self.assertEqual(bool(self._def), bool(self._def_value))
+
+    def test_int_op(self):
+        self.assertEqual(int(self._def), int(self._def_value))
+
+    def test_float_op(self):
+        self.assertEqual(float(self._def), float(self._def_value))
+
+    def test_complex_op(self):
+        self.assertEqual(complex(self._def), complex(self._def_value))
+
+    def test_str_op(self):
+        self.assertEqual(str(self._def), str(self._def_value))
+
+    def test_eq_none(self):
+        self.assertFalse(self._def == None)
+
+    def test_ne_none(self):
+        self.assertTrue(self._def != None)
+
+    def test_is_set(self):
+        raw = self._def_value
+        field = self._fc()
+        self.assertFalse(field.is_set)
+        field.value = raw
+        self.assertTrue(field.is_set)
+
+    def test_reset(self):
+        raw = self._def_value
+        field = self._fc()
+        field.value = raw
+        self.assertTrue(field.is_set)
+        field.reset()
+        self.assertFalse(field.is_set)
+        other = self._fc()
+        self.assertEqual(other, field)
+
+
+_BINOPS = (
+    ('lt', operator.lt),
+    ('le', operator.le),
+    ('eq', operator.eq),
+    ('ne', operator.ne),
+    ('ge', operator.ge),
+    ('gt', operator.gt),
+    ('add', operator.add),
+    ('radd', lambda a, b: operator.add(b, a)),
+    ('and', operator.and_),
+    ('rand', lambda a, b: operator.and_(b, a)),
+    ('floordiv', operator.floordiv),
+    ('rfloordiv', lambda a, b: operator.floordiv(b, a)),
+    ('lshift', operator.lshift),
+    ('rlshift', lambda a, b: operator.lshift(b, a)),
+    ('mod', operator.mod),
+    ('rmod', lambda a, b: operator.mod(b, a)),
+    ('mul', operator.mul),
+    ('rmul', lambda a, b: operator.mul(b, a)),
+    ('or', operator.or_),
+    ('ror', lambda a, b: operator.or_(b, a)),
+    ('pow', operator.pow),
+    ('rpow', lambda a, b: operator.pow(b, a)),
+    ('rshift', operator.rshift),
+    ('rrshift', lambda a, b: operator.rshift(b, a)),
+    ('sub', operator.sub),
+    ('rsub', lambda a, b: operator.sub(b, a)),
+    ('truediv', operator.truediv),
+    ('rtruediv', lambda a, b: operator.truediv(b, a)),
+    ('xor', operator.xor),
+    ('rxor', lambda a, b: operator.xor(b, a)),
+)
+
+
+_IBINOPS = (
+    ('iadd', operator.iadd),
+    ('iand', operator.iand),
+    ('ifloordiv', operator.ifloordiv),
+    ('ilshift', operator.ilshift),
+    ('imod', operator.imod),
+    ('imul', operator.imul),
+    ('ior', operator.ior),
+    ('ipow', operator.ipow),
+    ('irshift', operator.irshift),
+    ('isub', operator.isub),
+    ('itruediv', operator.itruediv),
+    ('ixor', operator.ixor),
+)
+
+
+_UNARYOPS = (
+    ('neg', operator.neg),
+    ('pos', operator.pos),
+    ('abs', operator.abs),
+    ('invert', operator.invert),
+    ('round', round),
+    ('round_0', partial(round, ndigits=0)),
+    ('round_1', partial(round, ndigits=1)),
+    ('round_2', partial(round, ndigits=2)),
+    ('round_3', partial(round, ndigits=3)),
+    ('ceil', math.ceil),
+    ('floor', math.floor),
+    ('trunc', math.trunc),
+)
+
+
+def _inject_numeric_testing_methods(cls):
+    def test_binop_name(suffix):
+        return 'test_binop_{}_{}'.format(name, suffix)
+
+    def test_ibinop_name(suffix):
+        return 'test_ibinop_{}_{}'.format(name, suffix)
+
+    def test_unaryop_name(suffix):
+        return 'test_unaryop_{}_{}'.format(name, suffix)
+
+    # inject testing methods for each binary operation
+    for name, binop in _BINOPS:
+        setattr(cls, test_binop_name('invalid_unknown'), partialmethod(_TestNumericField._test_binop_invalid_unknown, op=binop))
+        setattr(cls, test_binop_name('invalid_none'), partialmethod(_TestNumericField._test_binop_invalid_none, op=binop))
+        setattr(cls, test_binop_name('type_true'), partialmethod(_TestNumericField._test_binop_type_true, op=binop))
+        setattr(cls, test_binop_name('type_pos_int'), partialmethod(_TestNumericField._test_binop_type_pos_int, op=binop))
+        setattr(cls, test_binop_name('type_pos_vint'), partialmethod(_TestNumericField._test_binop_type_pos_vint, op=binop))
+        setattr(cls, test_binop_name('value_true'), partialmethod(_TestNumericField._test_binop_value_true, op=binop))
+        setattr(cls, test_binop_name('value_pos_int'), partialmethod(_TestNumericField._test_binop_value_pos_int, op=binop))
+        setattr(cls, test_binop_name('value_pos_vint'), partialmethod(_TestNumericField._test_binop_value_pos_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_true'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_true, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_int'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_int, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_vint'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_true'), partialmethod(_TestNumericField._test_binop_lhs_value_same_true, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_int'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_int, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_vint'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_vint, op=binop))
+        setattr(cls, test_binop_name('type_neg_int'), partialmethod(_TestNumericField._test_binop_type_neg_int, op=binop))
+        setattr(cls, test_binop_name('type_neg_vint'), partialmethod(_TestNumericField._test_binop_type_neg_vint, op=binop))
+        setattr(cls, test_binop_name('value_neg_int'), partialmethod(_TestNumericField._test_binop_value_neg_int, op=binop))
+        setattr(cls, test_binop_name('value_neg_vint'), partialmethod(_TestNumericField._test_binop_value_neg_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_int'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_int, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_vint'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_int'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_int, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_vint'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_vint, op=binop))
+        setattr(cls, test_binop_name('type_false'), partialmethod(_TestNumericField._test_binop_type_false, op=binop))
+        setattr(cls, test_binop_name('type_zero_int'), partialmethod(_TestNumericField._test_binop_type_zero_int, op=binop))
+        setattr(cls, test_binop_name('type_zero_vint'), partialmethod(_TestNumericField._test_binop_type_zero_vint, op=binop))
+        setattr(cls, test_binop_name('value_false'), partialmethod(_TestNumericField._test_binop_value_false, op=binop))
+        setattr(cls, test_binop_name('value_zero_int'), partialmethod(_TestNumericField._test_binop_value_zero_int, op=binop))
+        setattr(cls, test_binop_name('value_zero_vint'), partialmethod(_TestNumericField._test_binop_value_zero_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_false'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_false, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_int'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_int, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_vint'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_false'), partialmethod(_TestNumericField._test_binop_lhs_value_same_false, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_int'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_int, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_vint'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_vint, op=binop))
+        setattr(cls, test_binop_name('type_pos_float'), partialmethod(_TestNumericField._test_binop_type_pos_float, op=binop))
+        setattr(cls, test_binop_name('type_neg_float'), partialmethod(_TestNumericField._test_binop_type_neg_float, op=binop))
+        setattr(cls, test_binop_name('type_pos_vfloat'), partialmethod(_TestNumericField._test_binop_type_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('type_neg_vfloat'), partialmethod(_TestNumericField._test_binop_type_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('value_pos_float'), partialmethod(_TestNumericField._test_binop_value_pos_float, op=binop))
+        setattr(cls, test_binop_name('value_neg_float'), partialmethod(_TestNumericField._test_binop_value_neg_float, op=binop))
+        setattr(cls, test_binop_name('value_pos_vfloat'), partialmethod(_TestNumericField._test_binop_value_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('value_neg_vfloat'), partialmethod(_TestNumericField._test_binop_value_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_float'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_float, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_float'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_float, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_float'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_float, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_float'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_float, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('type_zero_float'), partialmethod(_TestNumericField._test_binop_type_zero_float, op=binop))
+        setattr(cls, test_binop_name('type_zero_vfloat'), partialmethod(_TestNumericField._test_binop_type_zero_vfloat, op=binop))
+        setattr(cls, test_binop_name('value_zero_float'), partialmethod(_TestNumericField._test_binop_value_zero_float, op=binop))
+        setattr(cls, test_binop_name('value_zero_vfloat'), partialmethod(_TestNumericField._test_binop_value_zero_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_float'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_float, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_float'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_float, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_vfloat, op=binop))
+
+    # inject testing methods for each unary operation
+    for name, unaryop in _UNARYOPS:
+        setattr(cls, test_unaryop_name('type'), partialmethod(_TestNumericField._test_unaryop_type, op=unaryop))
+        setattr(cls, test_unaryop_name('value'), partialmethod(_TestNumericField._test_unaryop_value, op=unaryop))
+        setattr(cls, test_unaryop_name('addr_same'), partialmethod(_TestNumericField._test_unaryop_addr_same, op=unaryop))
+        setattr(cls, test_unaryop_name('value_same'), partialmethod(_TestNumericField._test_unaryop_value_same, op=unaryop))
+
+    # inject testing methods for each inplace binary operation
+    for name, ibinop in _IBINOPS:
+        setattr(cls, test_ibinop_name('invalid_unknown'), partialmethod(_TestNumericField._test_ibinop_invalid_unknown, op=ibinop))
+        setattr(cls, test_ibinop_name('invalid_none'), partialmethod(_TestNumericField._test_ibinop_invalid_none, op=ibinop))
+        setattr(cls, test_ibinop_name('type_true'), partialmethod(_TestNumericField._test_ibinop_type_true, op=ibinop))
+        setattr(cls, test_ibinop_name('value_true'), partialmethod(_TestNumericField._test_ibinop_value_true, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_int'), partialmethod(_TestNumericField._test_ibinop_type_pos_int, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_vint'), partialmethod(_TestNumericField._test_ibinop_type_pos_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_int'), partialmethod(_TestNumericField._test_ibinop_value_pos_int, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_vint'), partialmethod(_TestNumericField._test_ibinop_value_pos_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_int'), partialmethod(_TestNumericField._test_ibinop_type_neg_int, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_vint'), partialmethod(_TestNumericField._test_ibinop_type_neg_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_int'), partialmethod(_TestNumericField._test_ibinop_value_neg_int, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_vint'), partialmethod(_TestNumericField._test_ibinop_value_neg_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('type_false'), partialmethod(_TestNumericField._test_ibinop_type_false, op=ibinop))
+        setattr(cls, test_ibinop_name('value_false'), partialmethod(_TestNumericField._test_ibinop_value_false, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_int'), partialmethod(_TestNumericField._test_ibinop_type_zero_int, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_vint'), partialmethod(_TestNumericField._test_ibinop_type_zero_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_int'), partialmethod(_TestNumericField._test_ibinop_value_zero_int, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_vint'), partialmethod(_TestNumericField._test_ibinop_value_zero_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_float'), partialmethod(_TestNumericField._test_ibinop_type_pos_float, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_float'), partialmethod(_TestNumericField._test_ibinop_type_neg_float, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_vfloat'), partialmethod(_TestNumericField._test_ibinop_type_pos_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_vfloat'), partialmethod(_TestNumericField._test_ibinop_type_neg_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_float'), partialmethod(_TestNumericField._test_ibinop_value_pos_float, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_float'), partialmethod(_TestNumericField._test_ibinop_value_neg_float, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_vfloat'), partialmethod(_TestNumericField._test_ibinop_value_pos_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_vfloat'), partialmethod(_TestNumericField._test_ibinop_value_neg_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_float'), partialmethod(_TestNumericField._test_ibinop_type_zero_float, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_vfloat'), partialmethod(_TestNumericField._test_ibinop_type_zero_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_float'), partialmethod(_TestNumericField._test_ibinop_value_zero_float, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_vfloat'), partialmethod(_TestNumericField._test_ibinop_value_zero_vfloat, op=ibinop))
+
+
+class _TestIntegerFieldCommon(_TestNumericField):
+    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_pos_int(self):
+        raw = 477
+        self._def.value = raw
+        self.assertEqual(self._def, raw)
+
+    def test_assign_neg_int(self):
+        raw = -13
+        self._def.value = raw
+        self.assertEqual(self._def, raw)
+
+    def test_assign_int_field(self):
+        raw = 999
+        field = self._fc()
+        field.value = raw
+        self._def.value = field
+        self.assertEqual(self._def, raw)
+
+    def test_assign_float(self):
+        raw = 123.456
+        self._def.value = raw
+        self.assertEqual(self._def, int(raw))
+
+    def test_assign_invalid_type(self):
+        with self.assertRaises(TypeError):
+            self._def.value = 'yes'
+
+    def test_assign_uint(self):
+        fc = bt2.IntegerFieldClass(size=32, is_signed=False)
+        field = fc()
+        raw = 1777
+        field.value = 1777
+        self.assertEqual(field, raw)
+
+    def test_assign_uint_invalid_neg(self):
+        fc = bt2.IntegerFieldClass(size=32, is_signed=False)
+        field = fc()
+
+        with self.assertRaises(ValueError):
+            field.value = -23
+
+    def test_str_op(self):
+        self.assertEqual(str(self._def), str(self._def_value))
+
+    def test_str_op_unset(self):
+        self.assertEqual(str(self._fc()), 'Unset')
+
+
+_inject_numeric_testing_methods(_TestIntegerFieldCommon)
+
+
+@unittest.skip("this is broken")
+class IntegerFieldTestCase(_TestIntegerFieldCommon, unittest.TestCase):
+    def setUp(self):
+        self._fc = bt2.IntegerFieldClass(25, is_signed=True)
+        self._field = self._fc()
+        self._def = self._fc()
+        self._def.value = 17
+        self._def_value = 17
+        self._def_new_value = -101
+
+    def tearDown(self):
+        del self._fc
+        del self._field
+        del self._def
+
+
+@unittest.skip("this is broken")
+class EnumerationFieldTestCase(_TestIntegerFieldCommon, unittest.TestCase):
+    def setUp(self):
+        self._fc = bt2.EnumerationFieldClass(size=32, is_signed=True)
+        self._fc.add_mapping('whole range', -(2 ** 31), (2 ** 31) - 1)
+        self._fc.add_mapping('something', 17)
+        self._fc.add_mapping('speaker', 12, 16)
+        self._fc.add_mapping('can', 18, 2540)
+        self._fc.add_mapping('zip', -45, 1001)
+        self._def = self._fc()
+        self._def.value = 17
+        self._def_value = 17
+        self._def_new_value = -101
+
+    def tearDown(self):
+        del self._fc
+        del self._def
+
+    def test_mappings(self):
+        mappings = (
+            ('whole range', -(2 ** 31), (2 ** 31) - 1),
+            ('something', 17, 17),
+            ('zip', -45, 1001),
+        )
+
+        total = 0
+        index_set = set()
+
+        for fm in self._def.mappings:
+            total += 1
+            for index, mapping in enumerate(mappings):
+                if fm.name == mapping[0] and fm.lower == mapping[1] and fm.upper == mapping[2]:
+                    index_set.add(index)
+
+        self.assertEqual(total, 3)
+        self.assertTrue(0 in index_set and 1 in index_set and 2 in index_set)
+
+    def test_str_op(self):
+        expected_string_found = False
+        s = str(self._def)
+
+        # Establish all permutations of the three expected matches since
+        # the order in which mappings are enumerated is not explicitly part of
+        # the API.
+        for p in itertools.permutations(["'whole range'", "'something'",
+                                         "'zip'"]):
+            candidate = '{} ({})'.format(self._def_value, ', '.join(p))
+            if candidate == s:
+                expected_string_found = True
+                break
+
+        self.assertTrue(expected_string_found)
+
+    def test_str_op_unset(self):
+        self.assertEqual(str(self._fc()), 'Unset')
+
+
+@unittest.skip("this is broken")
+class FloatingPointNumberFieldTestCase(_TestNumericField, unittest.TestCase):
+    def setUp(self):
+        self._fc = bt2.FloatingPointNumberFieldClass()
+        self._field = self._fc()
+        self._def = self._fc()
+        self._def.value = 52.7
+        self._def_value = 52.7
+        self._def_new_value = -17.164857
+
+    def tearDown(self):
+        del self._fc
+        del self._field
+        del self._def
+
+    def _test_invalid_op(self, cb):
+        with self.assertRaises(TypeError):
+            cb()
+
+    def test_assign_true(self):
+        self._def.value = True
+        self.assertTrue(self._def)
+
+    def test_assign_false(self):
+        self._def.value = False
+        self.assertFalse(self._def)
+
+    def test_assign_pos_int(self):
+        raw = 477
+        self._def.value = raw
+        self.assertEqual(self._def, float(raw))
+
+    def test_assign_neg_int(self):
+        raw = -13
+        self._def.value = raw
+        self.assertEqual(self._def, float(raw))
+
+    def test_assign_int_field(self):
+        fc = bt2.IntegerFieldClass(32)
+        field = fc()
+        raw = 999
+        field.value = raw
+        self._def.value = field
+        self.assertEqual(self._def, float(raw))
+
+    def test_assign_float(self):
+        raw = -19.23
+        self._def.value = raw
+        self.assertEqual(self._def, raw)
+
+    def test_assign_float_field(self):
+        fc = bt2.FloatingPointNumberFieldClass(32)
+        field = fc()
+        raw = 101.32
+        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 = 'yes'
+
+    def test_invalid_lshift(self):
+        self._test_invalid_op(lambda: self._def << 23)
+
+    def test_invalid_rshift(self):
+        self._test_invalid_op(lambda: self._def >> 23)
+
+    def test_invalid_and(self):
+        self._test_invalid_op(lambda: self._def & 23)
+
+    def test_invalid_or(self):
+        self._test_invalid_op(lambda: self._def | 23)
+
+    def test_invalid_xor(self):
+        self._test_invalid_op(lambda: self._def ^ 23)
+
+    def test_invalid_invert(self):
+        self._test_invalid_op(lambda: ~self._def)
+
+    def test_str_op(self):
+        self.assertEqual(str(self._def), str(self._def_value))
+
+    def test_str_op_unset(self):
+        self.assertEqual(str(self._fc()), 'Unset')
+
+_inject_numeric_testing_methods(FloatingPointNumberFieldTestCase)
+
+
+@unittest.skip("this is broken")
+class StringFieldTestCase(_TestCopySimple, unittest.TestCase):
+    def setUp(self):
+        self._fc = bt2.StringFieldClass()
+        self._def_value = 'Hello, World!'
+        self._def = self._fc()
+        self._def.value = self._def_value
+        self._def_new_value = 'Yes!'
+
+    def tearDown(self):
+        del self._fc
+        del self._def
+
+    def test_assign_int(self):
+        with self.assertRaises(TypeError):
+            self._def.value = 283
+
+    def test_assign_string_field(self):
+        fc = bt2.StringFieldClass()
+        field = fc()
+        raw = 'zorg'
+        field.value = raw
+        self.assertEqual(field, raw)
+
+    def test_eq(self):
+        self.assertEqual(self._def, self._def_value)
+
+    def test_eq(self):
+        self.assertNotEqual(self._def, 23)
+
+    def test_lt_vstring(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        s2 = self._fc()
+        s2.value = 'bateau'
+        self.assertLess(s1, s2)
+
+    def test_lt_string(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        self.assertLess(s1, 'bateau')
+
+    def test_le_vstring(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        s2 = self._fc()
+        s2.value = 'bateau'
+        self.assertLessEqual(s1, s2)
+
+    def test_le_string(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        self.assertLessEqual(s1, 'bateau')
+
+    def test_gt_vstring(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        s2 = self._fc()
+        s2.value = 'bateau'
+        self.assertGreater(s2, s1)
+
+    def test_gt_string(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        self.assertGreater('bateau', s1)
+
+    def test_ge_vstring(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        s2 = self._fc()
+        s2.value = 'bateau'
+        self.assertGreaterEqual(s2, s1)
+
+    def test_ge_string(self):
+        s1 = self._fc()
+        s1.value = 'allo'
+        self.assertGreaterEqual('bateau', s1)
+
+    def test_bool_op(self):
+        self.assertEqual(bool(self._def), bool(self._def_value))
+
+    def test_str_op(self):
+        self.assertEqual(str(self._def), str(self._def_value))
+
+    def test_str_op_unset(self):
+        self.assertEqual(str(self._fc()), 'Unset')
+
+    def test_len(self):
+        self.assertEqual(len(self._def), len(self._def_value))
+
+    def test_getitem(self):
+        self.assertEqual(self._def[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_append_string_field(self):
+        fc = bt2.StringFieldClass()
+        field = fc()
+        to_append = 'meow meow meow'
+        field.value = to_append
+        self._def += field
+        self._def_value += to_append
+        self.assertEqual(self._def, self._def_value)
+
+    def test_is_set(self):
+        raw = self._def_value
+        field = self._fc()
+        self.assertFalse(field.is_set)
+        field.value = raw
+        self.assertTrue(field.is_set)
+
+    def test_reset(self):
+        raw = self._def_value
+        field = self._fc()
+        field.value = raw
+        self.assertTrue(field.is_set)
+        field.reset()
+        self.assertFalse(field.is_set)
+        other = self._fc()
+        self.assertEqual(other, field)
+
+
+class _TestArraySequenceFieldCommon(_TestCopySimple):
+    def _modify_def(self):
+        self._def[2] = 23
+
+    def test_bool_op_true(self):
+        self.assertTrue(self._def)
+
+    def test_len(self):
+        self.assertEqual(len(self._def), 3)
+
+    def test_getitem(self):
+        field = self._def[1]
+        self.assertIs(type(field), bt2.field._IntegerField)
+        self.assertEqual(field, 1847)
+
+    def test_eq(self):
+        fc = bt2.ArrayFieldClass(self._elem_fc, 3)
+        field = fc()
+        field[0] = 45
+        field[1] = 1847
+        field[2] = 1948754
+        self.assertEqual(self._def, field)
+
+    def test_eq_invalid_type(self):
+        self.assertNotEqual(self._def, 23)
+
+    def test_eq_diff_len(self):
+        fc = bt2.ArrayFieldClass(self._elem_fc, 2)
+        field = fc()
+        field[0] = 45
+        field[1] = 1847
+        self.assertNotEqual(self._def, field)
+
+    def test_eq_diff_content_same_len(self):
+        fc = bt2.ArrayFieldClass(self._elem_fc, 3)
+        field = fc()
+        field[0] = 45
+        field[1] = 1846
+        field[2] = 1948754
+        self.assertNotEqual(self._def, field)
+
+    def test_setitem(self):
+        self._def[2] = 24
+        self.assertEqual(self._def[2], 24)
+
+    def test_setitem_int_field(self):
+        int_field = self._elem_fc()
+        int_field.value = 19487
+        self._def[1] = int_field
+        self.assertEqual(self._def[1], 19487)
+
+    def test_setitem_non_basic_field(self):
+        elem_fc = bt2.StructureFieldClass()
+        array_fc = bt2.ArrayFieldClass(elem_fc, 3)
+        elem_field = elem_fc()
+        array_field = array_fc()
+
+        with self.assertRaises(TypeError):
+            array_field[1] = 23
+
+    def test_setitem_none(self):
+        with self.assertRaises(TypeError):
+            self._def[1] = None
+
+    def test_setitem_index_wrong_type(self):
+        with self.assertRaises(TypeError):
+            self._def['yes'] = 23
+
+    def test_setitem_index_neg(self):
+        with self.assertRaises(IndexError):
+            self._def[-2] = 23
+
+    def test_setitem_index_out_of_range(self):
+        with self.assertRaises(IndexError):
+            self._def[len(self._def)] = 134679
+
+    def test_iter(self):
+        for field, value in zip(self._def, (45, 1847, 1948754)):
+            self.assertEqual(field, value)
+
+    def test_value_int_field(self):
+        values = [45646, 145, 12145]
+        self._def.value = values
+        self.assertEqual(values, self._def)
+
+    def test_value_unset(self):
+        values = [45646, None, 12145]
+        self._def.value = values
+        self.assertFalse(self._def[1].is_set)
+
+    def test_value_rollback(self):
+        values = [45, 1847, 1948754]
+        # value is out of range, should not affect those we set previously
+        with self.assertRaises(bt2.Error):
+            self._def[2].value = 2**60
+        self.assertEqual(values, self._def)
+
+    def test_value_check_sequence(self):
+        values = 42
+        with self.assertRaises(TypeError):
+            self._def.value = values
+
+    def test_value_wrong_type_in_sequence(self):
+        values = [32, 'hello', 11]
+        with self.assertRaises(TypeError):
+            self._def.value = values
+
+    def test_value_complex_type(self):
+        struct_fc = bt2.StructureFieldClass()
+        int_fc = bt2.IntegerFieldClass(32)
+        str_fc = bt2.StringFieldClass()
+        struct_fc.append_field(field_class=int_fc, name='an_int')
+        struct_fc.append_field(field_class=str_fc, name='a_string')
+        struct_fc.append_field(field_class=int_fc, name='another_int')
+        array_fc = bt2.ArrayFieldClass(struct_fc, 3)
+        values = [
+            {
+                'an_int': 42,
+                'a_string': 'hello',
+                'another_int': 66
+            },
+            {
+                'an_int': 1,
+                'a_string': 'goodbye',
+                'another_int': 488
+            },
+            {
+                'an_int': 156,
+                'a_string': 'or not',
+                'another_int': 4648
+            },
+        ]
+
+        array = array_fc()
+        array.value = values
+        self.assertEqual(values, array)
+        values[0]['an_int'] = 'a string'
+        with self.assertRaises(TypeError):
+            array.value = values
+
+    def test_is_set(self):
+        raw = self._def_value
+        field = self._fc()
+        self.assertFalse(field.is_set)
+        field.value = raw
+        self.assertTrue(field.is_set)
+
+    def test_reset(self):
+        raw = self._def_value
+        field = self._fc()
+        field.value = raw
+        self.assertTrue(field.is_set)
+        field.reset()
+        self.assertFalse(field.is_set)
+        other = self._fc()
+        self.assertEqual(other, field)
+
+    def test_str_op(self):
+        s = str(self._def)
+        expected_string = '[{}]'.format(', '.join(
+            [repr(v) for v in self._def_value]))
+        self.assertEqual(expected_string, s)
+
+    def test_str_op_unset(self):
+        self.assertEqual(str(self._fc()), 'Unset')
+
+
+@unittest.skip("this is broken")
+class ArrayFieldTestCase(_TestArraySequenceFieldCommon, unittest.TestCase):
+    def setUp(self):
+        self._elem_fc = bt2.IntegerFieldClass(32)
+        self._fc = bt2.ArrayFieldClass(self._elem_fc, 3)
+        self._def = self._fc()
+        self._def[0] = 45
+        self._def[1] = 1847
+        self._def[2] = 1948754
+        self._def_value = [45, 1847, 1948754]
+
+    def tearDown(self):
+        del self._elem_fc
+        del self._fc
+        del self._def
+
+    def test_value_wrong_len(self):
+        values = [45, 1847]
+        with self.assertRaises(ValueError):
+            self._def.value = values
+
+
+@unittest.skip("this is broken")
+class SequenceFieldTestCase(_TestArraySequenceFieldCommon, unittest.TestCase):
+    def setUp(self):
+        self._elem_fc = bt2.IntegerFieldClass(32)
+        self._fc = bt2.SequenceFieldClass(self._elem_fc, 'the.length')
+        self._def = self._fc()
+        self._length_field = self._elem_fc(3)
+        self._def.length_field = self._length_field
+        self._def[0] = 45
+        self._def[1] = 1847
+        self._def[2] = 1948754
+        self._def_value = [45, 1847, 1948754]
+
+    def tearDown(self):
+        del self._elem_fc
+        del self._fc
+        del self._def
+        del self._length_field
+
+    def test_value_resize(self):
+        new_values = [1, 2, 3, 4]
+        self._def.value = new_values
+        self.assertCountEqual(self._def, new_values)
+
+    def test_value_resize_rollback(self):
+        with self.assertRaises(TypeError):
+            self._def.value = [1, 2, 3, 'unexpected string']
+        self.assertEqual(self._def, self._def_value)
+
+        self._def.reset()
+        with self.assertRaises(TypeError):
+            self._def.value = [1, 2, 3, 'unexpected string']
+        self.assertFalse(self._def.is_set)
+
+
+@unittest.skip("this is broken")
+class StructureFieldTestCase(_TestCopySimple, unittest.TestCase):
+    def setUp(self):
+        self._fc0 = bt2.IntegerFieldClass(32, is_signed=True)
+        self._fc1 = bt2.StringFieldClass()
+        self._fc2 = bt2.FloatingPointNumberFieldClass()
+        self._fc3 = bt2.IntegerFieldClass(17)
+        self._fc = bt2.StructureFieldClass()
+        self._fc.append_field('A', self._fc0)
+        self._fc.append_field('B', self._fc1)
+        self._fc.append_field('C', self._fc2)
+        self._fc.append_field('D', self._fc3)
+        self._def = self._fc()
+        self._def['A'] = -1872
+        self._def['B'] = 'salut'
+        self._def['C'] = 17.5
+        self._def['D'] = 16497
+        self._def_value = {
+            'A': -1872,
+            'B': 'salut',
+            'C': 17.5,
+            'D': 16497
+        }
+
+    def tearDown(self):
+        del self._fc0
+        del self._fc1
+        del self._fc2
+        del self._fc3
+        del self._fc
+        del self._def
+
+    def _modify_def(self):
+        self._def['B'] = 'hola'
+
+    def test_bool_op_true(self):
+        self.assertTrue(self._def)
+
+    def test_bool_op_false(self):
+        fc = bt2.StructureFieldClass()
+        field = fc()
+        self.assertFalse(field)
+
+    def test_len(self):
+        self.assertEqual(len(self._def), 4)
+
+    def test_getitem(self):
+        field = self._def['A']
+        self.assertIs(type(field), bt2.field._IntegerField)
+        self.assertEqual(field, -1872)
+
+    def test_at_index_out_of_bounds_after(self):
+        with self.assertRaises(IndexError):
+            self._def.at_index(len(self._fc))
+
+    def test_eq(self):
+        fc = bt2.StructureFieldClass()
+        fc.append_field('A', self._fc0)
+        fc.append_field('B', self._fc1)
+        fc.append_field('C', self._fc2)
+        fc.append_field('D', self._fc3)
+        field = fc()
+        field['A'] = -1872
+        field['B'] = 'salut'
+        field['C'] = 17.5
+        field['D'] = 16497
+        self.assertEqual(self._def, field)
+
+    def test_eq_invalid_type(self):
+        self.assertNotEqual(self._def, 23)
+
+    def test_eq_diff_len(self):
+        fc = bt2.StructureFieldClass()
+        fc.append_field('A', self._fc0)
+        fc.append_field('B', self._fc1)
+        fc.append_field('C', self._fc2)
+        field = fc()
+        field['A'] = -1872
+        field['B'] = 'salut'
+        field['C'] = 17.5
+        self.assertNotEqual(self._def, field)
+
+    def test_eq_diff_content_same_len(self):
+        fc = bt2.StructureFieldClass()
+        fc.append_field('A', self._fc0)
+        fc.append_field('B', self._fc1)
+        fc.append_field('C', self._fc2)
+        fc.append_field('D', self._fc3)
+        field = fc()
+        field['A'] = -1872
+        field['B'] = 'salut'
+        field['C'] = 17.4
+        field['D'] = 16497
+        self.assertNotEqual(self._def, field)
+
+    def test_eq_same_content_diff_keys(self):
+        fc = bt2.StructureFieldClass()
+        fc.append_field('A', self._fc0)
+        fc.append_field('B', self._fc1)
+        fc.append_field('E', self._fc2)
+        fc.append_field('D', self._fc3)
+        field = fc()
+        field['A'] = -1872
+        field['B'] = 'salut'
+        field['E'] = 17.4
+        field['D'] = 16497
+        self.assertNotEqual(self._def, field)
+
+    def test_setitem(self):
+        self._def['C'] = -18.47
+        self.assertEqual(self._def['C'], -18.47)
+
+    def test_setitem_int_field(self):
+        int_fc = bt2.IntegerFieldClass(16)
+        int_field = int_fc()
+        int_field.value = 19487
+        self._def['D'] = int_field
+        self.assertEqual(self._def['D'], 19487)
+
+    def test_setitem_non_basic_field(self):
+        elem_fc = bt2.StructureFieldClass()
+        elem_field = elem_fc()
+        struct_fc = bt2.StructureFieldClass()
+        struct_fc.append_field('A', elem_fc)
+        struct_field = struct_fc()
+
+        # Will fail on access to .items() of the value
+        with self.assertRaises(AttributeError):
+            struct_field['A'] = 23
+
+    def test_setitem_none(self):
+        with self.assertRaises(TypeError):
+            self._def['C'] = None
+
+    def test_setitem_key_wrong_type(self):
+        with self.assertRaises(TypeError):
+            self._def[3] = 23
+
+    def test_setitem_wrong_key(self):
+        with self.assertRaises(KeyError):
+            self._def['hi'] = 134679
+
+    def test_at_index(self):
+        self.assertEqual(self._def.at_index(1), 'salut')
+
+    def test_iter(self):
+        orig_values = {
+            'A': -1872,
+            'B': 'salut',
+            'C': 17.5,
+            'D': 16497,
+        }
+
+        for vkey, vval in self._def.items():
+            val = orig_values[vkey]
+            self.assertEqual(vval, val)
+
+    def test_value(self):
+        orig_values = {
+            'A': -1872,
+            'B': 'salut',
+            'C': 17.5,
+            'D': 16497,
+        }
+        self.assertEqual(self._def, orig_values)
+
+    def test_set_value(self):
+        int_fc = bt2.IntegerFieldClass(32)
+        str_fc = bt2.StringFieldClass()
+        struct_fc = bt2.StructureFieldClass()
+        struct_fc.append_field(field_class=int_fc, name='an_int')
+        struct_fc.append_field(field_class=str_fc, name='a_string')
+        struct_fc.append_field(field_class=int_fc, name='another_int')
+        values = {
+            'an_int': 42,
+            'a_string': 'hello',
+            'another_int': 66
+        }
+
+        struct = struct_fc()
+        struct.value = values
+        self.assertEqual(values, struct)
+
+        bad_type_values = copy.deepcopy(values)
+        bad_type_values['an_int'] = 'a string'
+        with self.assertRaises(TypeError):
+            struct.value = bad_type_values
+
+        unknown_key_values = copy.deepcopy(values)
+        unknown_key_values['unknown_key'] = 16546
+        with self.assertRaises(KeyError):
+            struct.value = unknown_key_values
+
+    def test_value_rollback(self):
+        int_fc = bt2.IntegerFieldClass(32)
+        str_fc = bt2.StringFieldClass()
+        struct_fc = bt2.StructureFieldClass()
+        struct_fc.append_field(field_class=int_fc, name='an_int')
+        struct_fc.append_field(field_class=str_fc, name='a_string')
+        struct_fc.append_field(field_class=int_fc, name='another_int')
+        values = {
+            'an_int': 42,
+            'a_string': 'hello',
+            'another_int': 66
+        }
+
+    def test_is_set(self):
+        values = {
+            'an_int': 42,
+            'a_string': 'hello',
+            'another_int': 66
+        }
+
+        int_fc = bt2.IntegerFieldClass(32)
+        str_fc = bt2.StringFieldClass()
+        struct_fc = bt2.StructureFieldClass()
+        struct_fc.append_field(field_class=int_fc, name='an_int')
+        struct_fc.append_field(field_class=str_fc, name='a_string')
+        struct_fc.append_field(field_class=int_fc, name='another_int')
+
+        struct = struct_fc()
+        self.assertFalse(struct.is_set)
+        struct.value = values
+        self.assertTrue(struct.is_set)
+
+        struct = struct_fc()
+        struct['an_int'].value = 42
+        self.assertFalse(struct.is_set)
+
+    def test_reset(self):
+        values = {
+            'an_int': 42,
+            'a_string': 'hello',
+            'another_int': 66
+        }
+
+        int_fc = bt2.IntegerFieldClass(32)
+        str_fc = bt2.StringFieldClass()
+        struct_fc = bt2.StructureFieldClass()
+        struct_fc.append_field(field_class=int_fc, name='an_int')
+        struct_fc.append_field(field_class=str_fc, name='a_string')
+        struct_fc.append_field(field_class=int_fc, name='another_int')
+
+        struct = struct_fc()
+        struct.value = values
+        self.assertTrue(struct.is_set)
+        struct.reset()
+        self.assertEqual(struct_fc(), struct)
+
+    def test_str_op(self):
+        expected_string_found = False
+        s = str(self._def)
+        # Establish all permutations of the three expected matches since
+        # the order in which mappings are enumerated is not explicitly part of
+        # the API.
+        for p in itertools.permutations([(k, v) for k, v in self._def.items()]):
+            items = ['{}: {}'.format(repr(k), repr(v)) for k, v in p]
+            candidate = '{{{}}}'.format(', '.join(items))
+            if candidate == s:
+                expected_string_found = True
+                break
+
+        self.assertTrue(expected_string_found)
+
+    def test_str_op_unset(self):
+        self.assertEqual(str(self._fc()), 'Unset')
+
+
+@unittest.skip("this is broken")
+class VariantFieldTestCase(_TestCopySimple, unittest.TestCase):
+    def setUp(self):
+        self._tag_fc = bt2.EnumerationFieldClass(size=32)
+        self._tag_fc.add_mapping('corner', 23)
+        self._tag_fc.add_mapping('zoom', 17, 20)
+        self._tag_fc.add_mapping('mellotron', 1001)
+        self._tag_fc.add_mapping('giorgio', 2000, 3000)
+        self._fc0 = bt2.IntegerFieldClass(32, is_signed=True)
+        self._fc1 = bt2.StringFieldClass()
+        self._fc2 = bt2.FloatingPointNumberFieldClass()
+        self._fc3 = bt2.IntegerFieldClass(17)
+        self._fc = bt2.VariantFieldClass('salut', self._tag_fc)
+        self._fc.append_field('corner', self._fc0)
+        self._fc.append_field('zoom', self._fc1)
+        self._fc.append_field('mellotron', self._fc2)
+        self._fc.append_field('giorgio', self._fc3)
+        self._def = self._fc()
+
+    def tearDown(self):
+        del self._tag_fc
+        del self._fc0
+        del self._fc1
+        del self._fc2
+        del self._fc3
+        del self._fc
+        del self._def
+
+    def test_bool_op_true(self):
+        tag_field = self._tag_fc(1001)
+        self._def.field(tag_field).value = -17.34
+        self.assertTrue(self._def)
+
+    def test_bool_op_false(self):
+        self.assertFalse(self._def)
+
+    def test_tag_field_none(self):
+        self.assertIsNone(self._def.tag_field)
+
+    def test_tag_field(self):
+        tag_field = self._tag_fc(2800)
+        self._def.field(tag_field).value = 1847
+        self.assertEqual(self._def.tag_field, tag_field)
+        self.assertEqual(self._def.tag_field.addr, tag_field.addr)
+
+    def test_selected_field_none(self):
+        self.assertIsNone(self._def.selected_field)
+
+    def test_selected_field(self):
+        var_field1 = self._fc()
+        tag_field1 = self._tag_fc(1001)
+        var_field1.field(tag_field1).value = -17.34
+        self.assertEqual(var_field1.field(), -17.34)
+        self.assertEqual(var_field1.selected_field, -17.34)
+        var_field2 = self._fc()
+        tag_field2 = self._tag_fc(2500)
+        var_field2.field(tag_field2).value = 1921
+        self.assertEqual(var_field2.field(), 1921)
+        self.assertEqual(var_field2.selected_field, 1921)
+
+    def test_eq(self):
+        tag_fc = bt2.EnumerationFieldClass(size=32)
+        tag_fc.add_mapping('corner', 23)
+        tag_fc.add_mapping('zoom', 17, 20)
+        tag_fc.add_mapping('mellotron', 1001)
+        tag_fc.add_mapping('giorgio', 2000, 3000)
+        fc0 = bt2.IntegerFieldClass(32, is_signed=True)
+        fc1 = bt2.StringFieldClass()
+        fc2 = bt2.FloatingPointNumberFieldClass()
+        fc3 = bt2.IntegerFieldClass(17)
+        fc = bt2.VariantFieldClass('salut', tag_fc)
+        fc.append_field('corner', fc0)
+        fc.append_field('zoom', fc1)
+        fc.append_field('mellotron', fc2)
+        fc.append_field('giorgio', fc3)
+        field = fc()
+        field_tag = tag_fc(23)
+        def_tag = self._tag_fc(23)
+        field.field(field_tag).value = 1774
+        self._def.field(def_tag).value = 1774
+        self.assertEqual(self._def, field)
+
+    def test_eq_invalid_type(self):
+        self.assertNotEqual(self._def, 23)
+
+    def test_is_set(self):
+        self.assertFalse(self._def.is_set)
+        tag_field = self._tag_fc(2800)
+        self._def.field(tag_field).value = 684
+        self.assertTrue(self._def.is_set)
+
+    def test_reset(self):
+        tag_field = self._tag_fc(2800)
+        self._def.field(tag_field).value = 684
+        self._def.reset()
+        self.assertFalse(self._def.is_set)
+        self.assertIsNone(self._def.selected_field)
+        self.assertIsNone(self._def.tag_field)
+
+    def test_str_op_int(self):
+        v = self._fc()
+        v.field(self._tag_fc(23)).value = 42
+        f = self._fc0(42)
+        self.assertEqual(str(f), str(v))
+
+    def test_str_op_str(self):
+        v = self._fc()
+        v.field(self._tag_fc(18)).value = 'some test string'
+        f = self._fc1('some test string')
+        self.assertEqual(str(f), str(v))
+
+    def test_str_op_flt(self):
+        v = self._fc()
+        v.field(self._tag_fc(1001)).value = 14.4245
+        f = self._fc2(14.4245)
+        self.assertEqual(str(f), str(v))
+
+    def test_str_op_unset(self):
+        self.assertEqual(str(self._fc()), 'Unset')
index fbbadfdccf680f91dbfcfb8b1db52a0b4c9ba135..ca524bb0ac53131d25b8cdc17c6d36238441def5 100644 (file)
@@ -1,4 +1,4 @@
-import bt2.fields
+import bt2.field
 import unittest
 import copy
 import bt2
@@ -125,7 +125,7 @@ class IntegerFieldClassTestCase(_TestIntegerFieldClassProps, _TestCopySimple,
 
     def test_create_field(self):
         field = self._fc()
-        self.assertIsInstance(field, bt2.fields._IntegerField)
+        self.assertIsInstance(field, bt2.field._IntegerField)
 
     def test_create_field_init(self):
         field = self._fc(23)
@@ -173,7 +173,7 @@ class FloatingPointNumberFieldClassTestCase(_TestCopySimple, _TestAlignmentProp,
 
     def test_create_field(self):
         field = self._fc()
-        self.assertIsInstance(field, bt2.fields._FloatingPointNumberField)
+        self.assertIsInstance(field, bt2.field._FloatingPointNumberField)
 
     def test_create_field_init(self):
         field = self._fc(17.5)
@@ -421,7 +421,7 @@ class EnumerationFieldClassTestCase(_TestIntegerFieldClassProps, _TestInvalidEq,
     def test_create_field(self):
         self._fc.add_mapping('c', 4, 5)
         field = self._fc()
-        self.assertIsInstance(field, bt2.fields._EnumerationField)
+        self.assertIsInstance(field, bt2.field._EnumerationField)
 
     def test_create_field_init(self):
         self._fc.add_mapping('c', 4, 5)
@@ -455,7 +455,7 @@ class StringFieldClassTestCase(_TestCopySimple, _TestInvalidEq,
 
     def test_create_field(self):
         field = self._fc()
-        self.assertIsInstance(field, bt2.fields._StringField)
+        self.assertIsInstance(field, bt2.field._StringField)
 
     def test_create_field_init(self):
         field = self._fc('hola')
@@ -608,7 +608,7 @@ class StructureFieldClassTestCase(_TestFieldContainer, unittest.TestCase):
 
     def test_create_field(self):
         field = self._fc()
-        self.assertIsInstance(field, bt2.fields._StructureField)
+        self.assertIsInstance(field, bt2.field._StructureField)
 
     def test_create_field_init_invalid(self):
         with self.assertRaises(bt2.Error):
@@ -668,7 +668,7 @@ class ArrayFieldClassTestCase(_TestInvalidEq, _TestCopySimple,
 
     def test_create_field(self):
         field = self._fc()
-        self.assertIsInstance(field, bt2.fields._ArrayField)
+        self.assertIsInstance(field, bt2.field._ArrayField)
 
     def test_create_field_init_invalid(self):
         with self.assertRaises(bt2.Error):
@@ -700,7 +700,7 @@ class SequenceFieldClassTestCase(_TestInvalidEq, _TestCopySimple,
 
     def test_create_field(self):
         field = self._fc()
-        self.assertIsInstance(field, bt2.fields._SequenceField)
+        self.assertIsInstance(field, bt2.field._SequenceField)
 
     def test_create_field_init_invalid(self):
         with self.assertRaises(bt2.Error):
diff --git a/tests/bindings/python/bt2/test_fields.py b/tests/bindings/python/bt2/test_fields.py
deleted file mode 100644 (file)
index f444622..0000000
+++ /dev/null
@@ -1,1675 +0,0 @@
-from functools import partial, partialmethod
-import operator
-import unittest
-import numbers
-import math
-import copy
-import itertools
-import bt2
-
-
-class _TestCopySimple:
-    def test_copy(self):
-        cpy = copy.copy(self._def)
-        self.assertIsNot(cpy, self._def)
-        self.assertNotEqual(cpy.addr, self._def.addr)
-        self.assertEqual(cpy, self._def)
-
-    def test_deepcopy(self):
-        cpy = copy.deepcopy(self._def)
-        self.assertIsNot(cpy, self._def)
-        self.assertNotEqual(cpy.addr, self._def.addr)
-        self.assertEqual(cpy, self._def)
-
-
-_COMP_BINOPS = (
-    operator.eq,
-    operator.ne,
-)
-
-
-class _TestNumericField(_TestCopySimple):
-    def _binop(self, op, rhs):
-        rexc = None
-        rvexc = None
-        comp_value = rhs
-
-        if isinstance(rhs, (bt2.fields._IntegerField, bt2.fields._FloatingPointNumberField)):
-            comp_value = copy.copy(rhs)
-
-        try:
-            r = op(self._def, rhs)
-        except Exception as e:
-            rexc = e
-
-        try:
-            rv = op(self._def_value, comp_value)
-        except Exception as e:
-            rvexc = e
-
-        if rexc is not None or rvexc is not None:
-            # at least one of the operations raised an exception: in
-            # this case both operations should have raised the same
-            # type of exception (division by zero, bit shift with a
-            # floating point number operand, etc.)
-            self.assertIs(type(rexc), type(rvexc))
-            return None, None
-
-        return r, rv
-
-    def _unaryop(self, op):
-        rexc = None
-        rvexc = None
-
-        try:
-            r = op(self._def)
-        except Exception as e:
-            rexc = e
-
-        try:
-            rv = op(self._def_value)
-        except Exception as e:
-            rvexc = e
-
-        if rexc is not None or rvexc is not None:
-            # at least one of the operations raised an exception: in
-            # this case both operations should have raised the same
-            # type of exception (division by zero, bit shift with a
-            # floating point number operand, etc.)
-            self.assertIs(type(rexc), type(rvexc))
-            return None, None
-
-        return r, rv
-
-    def _test_unaryop_type(self, op):
-        r, rv = self._unaryop(op)
-
-        if r is None:
-            return
-
-        self.assertIsInstance(r, type(rv))
-
-    def _test_unaryop_value(self, op):
-        r, rv = self._unaryop(op)
-
-        if r is None:
-            return
-
-        self.assertEqual(r, rv)
-
-    def _test_unaryop_addr_same(self, op):
-        addr_before = self._def.addr
-        self._unaryop(op)
-        self.assertEqual(self._def.addr, addr_before)
-
-    def _test_unaryop_value_same(self, op):
-        value_before = copy.copy(self._def_value)
-        self._unaryop(op)
-        self.assertEqual(self._def, value_before)
-
-    def _test_binop_type(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        if op in _COMP_BINOPS:
-            # __eq__() and __ne__() always return a 'bool' object
-            self.assertIsInstance(r, bool)
-        else:
-            self.assertIsInstance(r, type(rv))
-
-    def _test_binop_value(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        self.assertEqual(r, rv)
-
-    def _test_binop_lhs_addr_same(self, op, rhs):
-        addr_before = self._def.addr
-        r, rv = self._binop(op, rhs)
-        self.assertEqual(self._def.addr, addr_before)
-
-    def _test_binop_lhs_value_same(self, op, rhs):
-        value_before = copy.copy(self._def)
-        r, rv = self._binop(op, rhs)
-        self.assertEqual(self._def, value_before)
-
-    def _test_binop_invalid_unknown(self, op):
-        if op in _COMP_BINOPS:
-            self.skipTest('not testing')
-
-        class A:
-            pass
-
-        with self.assertRaises(TypeError):
-            op(self._def, A())
-
-    def _test_binop_invalid_none(self, op):
-        if op in _COMP_BINOPS:
-            self.skipTest('not testing')
-
-        with self.assertRaises(TypeError):
-            op(self._def, None)
-
-    def _test_ibinop_value(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        # The inplace operators are special for field objects because
-        # they do not return a new, immutable object like it's the case
-        # for Python numbers. In Python, `a += 2`, where `a` is a number
-        # object, assigns a new number object reference to `a`, dropping
-        # the old reference. Since BT's field objects are mutable, we
-        # modify their internal value with the inplace operators. This
-        # means however that we can lose data in the process, for
-        # example:
-        #
-        #     int_value_obj += 3.3
-        #
-        # Here, if `int_value_obj` is a Python `int` with the value 2,
-        # it would be a `float` object after this, holding the value
-        # 5.3. In our case, if `int_value_obj` is an integer field
-        # object, 3.3 is converted to an `int` object (3) and added to
-        # the current value of `int_value_obj`, so after this the value
-        # of the object is 5. This does not compare to 5.3, which is
-        # why we also use the `int()` type here.
-        if isinstance(self._def, bt2.fields._IntegerField):
-            rv = int(rv)
-
-        self.assertEqual(r, rv)
-
-    def _test_ibinop_type(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        self.assertIs(r, self._def)
-
-    def _test_ibinop_invalid_unknown(self, op):
-        class A:
-            pass
-
-        with self.assertRaises(TypeError):
-            op(self._def, A())
-
-    def _test_ibinop_invalid_none(self, op):
-        with self.assertRaises(TypeError):
-            op(self._def, None)
-
-    def _test_binop_rhs_false(self, test_cb, op):
-        test_cb(op, False)
-
-    def _test_binop_rhs_true(self, test_cb, op):
-        test_cb(op, True)
-
-    def _test_binop_rhs_pos_int(self, test_cb, op):
-        test_cb(op, 2)
-
-    def _test_binop_rhs_neg_int(self, test_cb, op):
-        test_cb(op, -23)
-
-    def _test_binop_rhs_zero_int(self, test_cb, op):
-        test_cb(op, 0)
-
-    def _test_binop_rhs_pos_vint(self, test_cb, op):
-        test_cb(op, bt2.create_value(2))
-
-    def _test_binop_rhs_neg_vint(self, test_cb, op):
-        test_cb(op, bt2.create_value(-23))
-
-    def _test_binop_rhs_zero_vint(self, test_cb, op):
-        test_cb(op, bt2.create_value(0))
-
-    def _test_binop_rhs_pos_float(self, test_cb, op):
-        test_cb(op, 2.2)
-
-    def _test_binop_rhs_neg_float(self, test_cb, op):
-        test_cb(op, -23.4)
-
-    def _test_binop_rhs_zero_float(self, test_cb, op):
-        test_cb(op, 0.0)
-
-    def _test_binop_rhs_pos_vfloat(self, test_cb, op):
-        test_cb(op, bt2.create_value(2.2))
-
-    def _test_binop_rhs_neg_vfloat(self, test_cb, op):
-        test_cb(op, bt2.create_value(-23.4))
-
-    def _test_binop_rhs_zero_vfloat(self, test_cb, op):
-        test_cb(op, bt2.create_value(0.0))
-
-    def _test_binop_type_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_type, op)
-
-    def _test_binop_type_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_type, op)
-
-    def _test_binop_type_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_type, op)
-
-    def _test_binop_type_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_type, op)
-
-    def _test_binop_type_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_type, op)
-
-    def _test_binop_type_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_type, op)
-
-    def _test_binop_type_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_type, op)
-
-    def _test_binop_type_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_type, op)
-
-    def _test_binop_type_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_type, op)
-
-    def _test_binop_type_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_type, op)
-
-    def _test_binop_type_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_type, op)
-
-    def _test_binop_type_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_type, op)
-
-    def _test_binop_type_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_type, op)
-
-    def _test_binop_type_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_type, op)
-
-    def _test_binop_value_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_value, op)
-
-    def _test_binop_value_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_value, op)
-
-    def _test_binop_value_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_value, op)
-
-    def _test_binop_value_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_value, op)
-
-    def _test_binop_value_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_value, op)
-
-    def _test_binop_value_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_value, op)
-
-    def _test_binop_value_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_value, op)
-
-    def _test_binop_value_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_value, op)
-
-    def _test_binop_value_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_value, op)
-
-    def _test_binop_value_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_value, op)
-
-    def _test_binop_value_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_value, op)
-
-    def _test_binop_value_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_value, op)
-
-    def _test_binop_value_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_value, op)
-
-    def _test_binop_value_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_value, op)
-
-    def _test_binop_lhs_addr_same_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_value_same_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_value_same, op)
-
-    def _test_ibinop_type_false(self, op):
-        self._test_binop_rhs_false(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_true(self, op):
-        self._test_binop_rhs_true(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_ibinop_type, op)
-
-    def _test_ibinop_value_false(self, op):
-        self._test_binop_rhs_false(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_true(self, op):
-        self._test_binop_rhs_true(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_ibinop_value, op)
-
-    def test_bool_op(self):
-        self.assertEqual(bool(self._def), bool(self._def_value))
-
-    def test_int_op(self):
-        self.assertEqual(int(self._def), int(self._def_value))
-
-    def test_float_op(self):
-        self.assertEqual(float(self._def), float(self._def_value))
-
-    def test_complex_op(self):
-        self.assertEqual(complex(self._def), complex(self._def_value))
-
-    def test_str_op(self):
-        self.assertEqual(str(self._def), str(self._def_value))
-
-    def test_eq_none(self):
-        self.assertFalse(self._def == None)
-
-    def test_ne_none(self):
-        self.assertTrue(self._def != None)
-
-    def test_is_set(self):
-        raw = self._def_value
-        field = self._fc()
-        self.assertFalse(field.is_set)
-        field.value = raw
-        self.assertTrue(field.is_set)
-
-    def test_reset(self):
-        raw = self._def_value
-        field = self._fc()
-        field.value = raw
-        self.assertTrue(field.is_set)
-        field.reset()
-        self.assertFalse(field.is_set)
-        other = self._fc()
-        self.assertEqual(other, field)
-
-
-_BINOPS = (
-    ('lt', operator.lt),
-    ('le', operator.le),
-    ('eq', operator.eq),
-    ('ne', operator.ne),
-    ('ge', operator.ge),
-    ('gt', operator.gt),
-    ('add', operator.add),
-    ('radd', lambda a, b: operator.add(b, a)),
-    ('and', operator.and_),
-    ('rand', lambda a, b: operator.and_(b, a)),
-    ('floordiv', operator.floordiv),
-    ('rfloordiv', lambda a, b: operator.floordiv(b, a)),
-    ('lshift', operator.lshift),
-    ('rlshift', lambda a, b: operator.lshift(b, a)),
-    ('mod', operator.mod),
-    ('rmod', lambda a, b: operator.mod(b, a)),
-    ('mul', operator.mul),
-    ('rmul', lambda a, b: operator.mul(b, a)),
-    ('or', operator.or_),
-    ('ror', lambda a, b: operator.or_(b, a)),
-    ('pow', operator.pow),
-    ('rpow', lambda a, b: operator.pow(b, a)),
-    ('rshift', operator.rshift),
-    ('rrshift', lambda a, b: operator.rshift(b, a)),
-    ('sub', operator.sub),
-    ('rsub', lambda a, b: operator.sub(b, a)),
-    ('truediv', operator.truediv),
-    ('rtruediv', lambda a, b: operator.truediv(b, a)),
-    ('xor', operator.xor),
-    ('rxor', lambda a, b: operator.xor(b, a)),
-)
-
-
-_IBINOPS = (
-    ('iadd', operator.iadd),
-    ('iand', operator.iand),
-    ('ifloordiv', operator.ifloordiv),
-    ('ilshift', operator.ilshift),
-    ('imod', operator.imod),
-    ('imul', operator.imul),
-    ('ior', operator.ior),
-    ('ipow', operator.ipow),
-    ('irshift', operator.irshift),
-    ('isub', operator.isub),
-    ('itruediv', operator.itruediv),
-    ('ixor', operator.ixor),
-)
-
-
-_UNARYOPS = (
-    ('neg', operator.neg),
-    ('pos', operator.pos),
-    ('abs', operator.abs),
-    ('invert', operator.invert),
-    ('round', round),
-    ('round_0', partial(round, ndigits=0)),
-    ('round_1', partial(round, ndigits=1)),
-    ('round_2', partial(round, ndigits=2)),
-    ('round_3', partial(round, ndigits=3)),
-    ('ceil', math.ceil),
-    ('floor', math.floor),
-    ('trunc', math.trunc),
-)
-
-
-def _inject_numeric_testing_methods(cls):
-    def test_binop_name(suffix):
-        return 'test_binop_{}_{}'.format(name, suffix)
-
-    def test_ibinop_name(suffix):
-        return 'test_ibinop_{}_{}'.format(name, suffix)
-
-    def test_unaryop_name(suffix):
-        return 'test_unaryop_{}_{}'.format(name, suffix)
-
-    # inject testing methods for each binary operation
-    for name, binop in _BINOPS:
-        setattr(cls, test_binop_name('invalid_unknown'), partialmethod(_TestNumericField._test_binop_invalid_unknown, op=binop))
-        setattr(cls, test_binop_name('invalid_none'), partialmethod(_TestNumericField._test_binop_invalid_none, op=binop))
-        setattr(cls, test_binop_name('type_true'), partialmethod(_TestNumericField._test_binop_type_true, op=binop))
-        setattr(cls, test_binop_name('type_pos_int'), partialmethod(_TestNumericField._test_binop_type_pos_int, op=binop))
-        setattr(cls, test_binop_name('type_pos_vint'), partialmethod(_TestNumericField._test_binop_type_pos_vint, op=binop))
-        setattr(cls, test_binop_name('value_true'), partialmethod(_TestNumericField._test_binop_value_true, op=binop))
-        setattr(cls, test_binop_name('value_pos_int'), partialmethod(_TestNumericField._test_binop_value_pos_int, op=binop))
-        setattr(cls, test_binop_name('value_pos_vint'), partialmethod(_TestNumericField._test_binop_value_pos_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_true'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_true, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_int'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_int, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_vint'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_true'), partialmethod(_TestNumericField._test_binop_lhs_value_same_true, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_int'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_int, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_vint'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_vint, op=binop))
-        setattr(cls, test_binop_name('type_neg_int'), partialmethod(_TestNumericField._test_binop_type_neg_int, op=binop))
-        setattr(cls, test_binop_name('type_neg_vint'), partialmethod(_TestNumericField._test_binop_type_neg_vint, op=binop))
-        setattr(cls, test_binop_name('value_neg_int'), partialmethod(_TestNumericField._test_binop_value_neg_int, op=binop))
-        setattr(cls, test_binop_name('value_neg_vint'), partialmethod(_TestNumericField._test_binop_value_neg_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_int'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_int, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_vint'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_int'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_int, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_vint'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_vint, op=binop))
-        setattr(cls, test_binop_name('type_false'), partialmethod(_TestNumericField._test_binop_type_false, op=binop))
-        setattr(cls, test_binop_name('type_zero_int'), partialmethod(_TestNumericField._test_binop_type_zero_int, op=binop))
-        setattr(cls, test_binop_name('type_zero_vint'), partialmethod(_TestNumericField._test_binop_type_zero_vint, op=binop))
-        setattr(cls, test_binop_name('value_false'), partialmethod(_TestNumericField._test_binop_value_false, op=binop))
-        setattr(cls, test_binop_name('value_zero_int'), partialmethod(_TestNumericField._test_binop_value_zero_int, op=binop))
-        setattr(cls, test_binop_name('value_zero_vint'), partialmethod(_TestNumericField._test_binop_value_zero_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_false'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_false, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_int'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_int, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_vint'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_false'), partialmethod(_TestNumericField._test_binop_lhs_value_same_false, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_int'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_int, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_vint'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_vint, op=binop))
-        setattr(cls, test_binop_name('type_pos_float'), partialmethod(_TestNumericField._test_binop_type_pos_float, op=binop))
-        setattr(cls, test_binop_name('type_neg_float'), partialmethod(_TestNumericField._test_binop_type_neg_float, op=binop))
-        setattr(cls, test_binop_name('type_pos_vfloat'), partialmethod(_TestNumericField._test_binop_type_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('type_neg_vfloat'), partialmethod(_TestNumericField._test_binop_type_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('value_pos_float'), partialmethod(_TestNumericField._test_binop_value_pos_float, op=binop))
-        setattr(cls, test_binop_name('value_neg_float'), partialmethod(_TestNumericField._test_binop_value_neg_float, op=binop))
-        setattr(cls, test_binop_name('value_pos_vfloat'), partialmethod(_TestNumericField._test_binop_value_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('value_neg_vfloat'), partialmethod(_TestNumericField._test_binop_value_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_float'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_float, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_float'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_float, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_float'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_float, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_float'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_float, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_value_same_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_value_same_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('type_zero_float'), partialmethod(_TestNumericField._test_binop_type_zero_float, op=binop))
-        setattr(cls, test_binop_name('type_zero_vfloat'), partialmethod(_TestNumericField._test_binop_type_zero_vfloat, op=binop))
-        setattr(cls, test_binop_name('value_zero_float'), partialmethod(_TestNumericField._test_binop_value_zero_float, op=binop))
-        setattr(cls, test_binop_name('value_zero_vfloat'), partialmethod(_TestNumericField._test_binop_value_zero_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_float'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_float, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_addr_same_zero_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_float'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_float, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_vfloat'), partialmethod(_TestNumericField._test_binop_lhs_value_same_zero_vfloat, op=binop))
-
-    # inject testing methods for each unary operation
-    for name, unaryop in _UNARYOPS:
-        setattr(cls, test_unaryop_name('type'), partialmethod(_TestNumericField._test_unaryop_type, op=unaryop))
-        setattr(cls, test_unaryop_name('value'), partialmethod(_TestNumericField._test_unaryop_value, op=unaryop))
-        setattr(cls, test_unaryop_name('addr_same'), partialmethod(_TestNumericField._test_unaryop_addr_same, op=unaryop))
-        setattr(cls, test_unaryop_name('value_same'), partialmethod(_TestNumericField._test_unaryop_value_same, op=unaryop))
-
-    # inject testing methods for each inplace binary operation
-    for name, ibinop in _IBINOPS:
-        setattr(cls, test_ibinop_name('invalid_unknown'), partialmethod(_TestNumericField._test_ibinop_invalid_unknown, op=ibinop))
-        setattr(cls, test_ibinop_name('invalid_none'), partialmethod(_TestNumericField._test_ibinop_invalid_none, op=ibinop))
-        setattr(cls, test_ibinop_name('type_true'), partialmethod(_TestNumericField._test_ibinop_type_true, op=ibinop))
-        setattr(cls, test_ibinop_name('value_true'), partialmethod(_TestNumericField._test_ibinop_value_true, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_int'), partialmethod(_TestNumericField._test_ibinop_type_pos_int, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_vint'), partialmethod(_TestNumericField._test_ibinop_type_pos_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_int'), partialmethod(_TestNumericField._test_ibinop_value_pos_int, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_vint'), partialmethod(_TestNumericField._test_ibinop_value_pos_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_int'), partialmethod(_TestNumericField._test_ibinop_type_neg_int, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_vint'), partialmethod(_TestNumericField._test_ibinop_type_neg_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_int'), partialmethod(_TestNumericField._test_ibinop_value_neg_int, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_vint'), partialmethod(_TestNumericField._test_ibinop_value_neg_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('type_false'), partialmethod(_TestNumericField._test_ibinop_type_false, op=ibinop))
-        setattr(cls, test_ibinop_name('value_false'), partialmethod(_TestNumericField._test_ibinop_value_false, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_int'), partialmethod(_TestNumericField._test_ibinop_type_zero_int, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_vint'), partialmethod(_TestNumericField._test_ibinop_type_zero_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_int'), partialmethod(_TestNumericField._test_ibinop_value_zero_int, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_vint'), partialmethod(_TestNumericField._test_ibinop_value_zero_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_float'), partialmethod(_TestNumericField._test_ibinop_type_pos_float, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_float'), partialmethod(_TestNumericField._test_ibinop_type_neg_float, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_vfloat'), partialmethod(_TestNumericField._test_ibinop_type_pos_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_vfloat'), partialmethod(_TestNumericField._test_ibinop_type_neg_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_float'), partialmethod(_TestNumericField._test_ibinop_value_pos_float, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_float'), partialmethod(_TestNumericField._test_ibinop_value_neg_float, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_vfloat'), partialmethod(_TestNumericField._test_ibinop_value_pos_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_vfloat'), partialmethod(_TestNumericField._test_ibinop_value_neg_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_float'), partialmethod(_TestNumericField._test_ibinop_type_zero_float, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_vfloat'), partialmethod(_TestNumericField._test_ibinop_type_zero_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_float'), partialmethod(_TestNumericField._test_ibinop_value_zero_float, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_vfloat'), partialmethod(_TestNumericField._test_ibinop_value_zero_vfloat, op=ibinop))
-
-
-class _TestIntegerFieldCommon(_TestNumericField):
-    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_pos_int(self):
-        raw = 477
-        self._def.value = raw
-        self.assertEqual(self._def, raw)
-
-    def test_assign_neg_int(self):
-        raw = -13
-        self._def.value = raw
-        self.assertEqual(self._def, raw)
-
-    def test_assign_int_field(self):
-        raw = 999
-        field = self._fc()
-        field.value = raw
-        self._def.value = field
-        self.assertEqual(self._def, raw)
-
-    def test_assign_float(self):
-        raw = 123.456
-        self._def.value = raw
-        self.assertEqual(self._def, int(raw))
-
-    def test_assign_invalid_type(self):
-        with self.assertRaises(TypeError):
-            self._def.value = 'yes'
-
-    def test_assign_uint(self):
-        fc = bt2.IntegerFieldClass(size=32, is_signed=False)
-        field = fc()
-        raw = 1777
-        field.value = 1777
-        self.assertEqual(field, raw)
-
-    def test_assign_uint_invalid_neg(self):
-        fc = bt2.IntegerFieldClass(size=32, is_signed=False)
-        field = fc()
-
-        with self.assertRaises(ValueError):
-            field.value = -23
-
-    def test_str_op(self):
-        self.assertEqual(str(self._def), str(self._def_value))
-
-    def test_str_op_unset(self):
-        self.assertEqual(str(self._fc()), 'Unset')
-
-
-_inject_numeric_testing_methods(_TestIntegerFieldCommon)
-
-
-@unittest.skip("this is broken")
-class IntegerFieldTestCase(_TestIntegerFieldCommon, unittest.TestCase):
-    def setUp(self):
-        self._fc = bt2.IntegerFieldClass(25, is_signed=True)
-        self._field = self._fc()
-        self._def = self._fc()
-        self._def.value = 17
-        self._def_value = 17
-        self._def_new_value = -101
-
-    def tearDown(self):
-        del self._fc
-        del self._field
-        del self._def
-
-
-@unittest.skip("this is broken")
-class EnumerationFieldTestCase(_TestIntegerFieldCommon, unittest.TestCase):
-    def setUp(self):
-        self._fc = bt2.EnumerationFieldClass(size=32, is_signed=True)
-        self._fc.add_mapping('whole range', -(2 ** 31), (2 ** 31) - 1)
-        self._fc.add_mapping('something', 17)
-        self._fc.add_mapping('speaker', 12, 16)
-        self._fc.add_mapping('can', 18, 2540)
-        self._fc.add_mapping('zip', -45, 1001)
-        self._def = self._fc()
-        self._def.value = 17
-        self._def_value = 17
-        self._def_new_value = -101
-
-    def tearDown(self):
-        del self._fc
-        del self._def
-
-    def test_mappings(self):
-        mappings = (
-            ('whole range', -(2 ** 31), (2 ** 31) - 1),
-            ('something', 17, 17),
-            ('zip', -45, 1001),
-        )
-
-        total = 0
-        index_set = set()
-
-        for fm in self._def.mappings:
-            total += 1
-            for index, mapping in enumerate(mappings):
-                if fm.name == mapping[0] and fm.lower == mapping[1] and fm.upper == mapping[2]:
-                    index_set.add(index)
-
-        self.assertEqual(total, 3)
-        self.assertTrue(0 in index_set and 1 in index_set and 2 in index_set)
-
-    def test_str_op(self):
-        expected_string_found = False
-        s = str(self._def)
-
-        # Establish all permutations of the three expected matches since
-        # the order in which mappings are enumerated is not explicitly part of
-        # the API.
-        for p in itertools.permutations(["'whole range'", "'something'",
-                                         "'zip'"]):
-            candidate = '{} ({})'.format(self._def_value, ', '.join(p))
-            if candidate == s:
-                expected_string_found = True
-                break
-
-        self.assertTrue(expected_string_found)
-
-    def test_str_op_unset(self):
-        self.assertEqual(str(self._fc()), 'Unset')
-
-
-@unittest.skip("this is broken")
-class FloatingPointNumberFieldTestCase(_TestNumericField, unittest.TestCase):
-    def setUp(self):
-        self._fc = bt2.FloatingPointNumberFieldClass()
-        self._field = self._fc()
-        self._def = self._fc()
-        self._def.value = 52.7
-        self._def_value = 52.7
-        self._def_new_value = -17.164857
-
-    def tearDown(self):
-        del self._fc
-        del self._field
-        del self._def
-
-    def _test_invalid_op(self, cb):
-        with self.assertRaises(TypeError):
-            cb()
-
-    def test_assign_true(self):
-        self._def.value = True
-        self.assertTrue(self._def)
-
-    def test_assign_false(self):
-        self._def.value = False
-        self.assertFalse(self._def)
-
-    def test_assign_pos_int(self):
-        raw = 477
-        self._def.value = raw
-        self.assertEqual(self._def, float(raw))
-
-    def test_assign_neg_int(self):
-        raw = -13
-        self._def.value = raw
-        self.assertEqual(self._def, float(raw))
-
-    def test_assign_int_field(self):
-        fc = bt2.IntegerFieldClass(32)
-        field = fc()
-        raw = 999
-        field.value = raw
-        self._def.value = field
-        self.assertEqual(self._def, float(raw))
-
-    def test_assign_float(self):
-        raw = -19.23
-        self._def.value = raw
-        self.assertEqual(self._def, raw)
-
-    def test_assign_float_field(self):
-        fc = bt2.FloatingPointNumberFieldClass(32)
-        field = fc()
-        raw = 101.32
-        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 = 'yes'
-
-    def test_invalid_lshift(self):
-        self._test_invalid_op(lambda: self._def << 23)
-
-    def test_invalid_rshift(self):
-        self._test_invalid_op(lambda: self._def >> 23)
-
-    def test_invalid_and(self):
-        self._test_invalid_op(lambda: self._def & 23)
-
-    def test_invalid_or(self):
-        self._test_invalid_op(lambda: self._def | 23)
-
-    def test_invalid_xor(self):
-        self._test_invalid_op(lambda: self._def ^ 23)
-
-    def test_invalid_invert(self):
-        self._test_invalid_op(lambda: ~self._def)
-
-    def test_str_op(self):
-        self.assertEqual(str(self._def), str(self._def_value))
-
-    def test_str_op_unset(self):
-        self.assertEqual(str(self._fc()), 'Unset')
-
-_inject_numeric_testing_methods(FloatingPointNumberFieldTestCase)
-
-
-@unittest.skip("this is broken")
-class StringFieldTestCase(_TestCopySimple, unittest.TestCase):
-    def setUp(self):
-        self._fc = bt2.StringFieldClass()
-        self._def_value = 'Hello, World!'
-        self._def = self._fc()
-        self._def.value = self._def_value
-        self._def_new_value = 'Yes!'
-
-    def tearDown(self):
-        del self._fc
-        del self._def
-
-    def test_assign_int(self):
-        with self.assertRaises(TypeError):
-            self._def.value = 283
-
-    def test_assign_string_field(self):
-        fc = bt2.StringFieldClass()
-        field = fc()
-        raw = 'zorg'
-        field.value = raw
-        self.assertEqual(field, raw)
-
-    def test_eq(self):
-        self.assertEqual(self._def, self._def_value)
-
-    def test_eq(self):
-        self.assertNotEqual(self._def, 23)
-
-    def test_lt_vstring(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        s2 = self._fc()
-        s2.value = 'bateau'
-        self.assertLess(s1, s2)
-
-    def test_lt_string(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        self.assertLess(s1, 'bateau')
-
-    def test_le_vstring(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        s2 = self._fc()
-        s2.value = 'bateau'
-        self.assertLessEqual(s1, s2)
-
-    def test_le_string(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        self.assertLessEqual(s1, 'bateau')
-
-    def test_gt_vstring(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        s2 = self._fc()
-        s2.value = 'bateau'
-        self.assertGreater(s2, s1)
-
-    def test_gt_string(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        self.assertGreater('bateau', s1)
-
-    def test_ge_vstring(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        s2 = self._fc()
-        s2.value = 'bateau'
-        self.assertGreaterEqual(s2, s1)
-
-    def test_ge_string(self):
-        s1 = self._fc()
-        s1.value = 'allo'
-        self.assertGreaterEqual('bateau', s1)
-
-    def test_bool_op(self):
-        self.assertEqual(bool(self._def), bool(self._def_value))
-
-    def test_str_op(self):
-        self.assertEqual(str(self._def), str(self._def_value))
-
-    def test_str_op_unset(self):
-        self.assertEqual(str(self._fc()), 'Unset')
-
-    def test_len(self):
-        self.assertEqual(len(self._def), len(self._def_value))
-
-    def test_getitem(self):
-        self.assertEqual(self._def[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_append_string_field(self):
-        fc = bt2.StringFieldClass()
-        field = fc()
-        to_append = 'meow meow meow'
-        field.value = to_append
-        self._def += field
-        self._def_value += to_append
-        self.assertEqual(self._def, self._def_value)
-
-    def test_is_set(self):
-        raw = self._def_value
-        field = self._fc()
-        self.assertFalse(field.is_set)
-        field.value = raw
-        self.assertTrue(field.is_set)
-
-    def test_reset(self):
-        raw = self._def_value
-        field = self._fc()
-        field.value = raw
-        self.assertTrue(field.is_set)
-        field.reset()
-        self.assertFalse(field.is_set)
-        other = self._fc()
-        self.assertEqual(other, field)
-
-
-class _TestArraySequenceFieldCommon(_TestCopySimple):
-    def _modify_def(self):
-        self._def[2] = 23
-
-    def test_bool_op_true(self):
-        self.assertTrue(self._def)
-
-    def test_len(self):
-        self.assertEqual(len(self._def), 3)
-
-    def test_getitem(self):
-        field = self._def[1]
-        self.assertIs(type(field), bt2.fields._IntegerField)
-        self.assertEqual(field, 1847)
-
-    def test_eq(self):
-        fc = bt2.ArrayFieldClass(self._elem_fc, 3)
-        field = fc()
-        field[0] = 45
-        field[1] = 1847
-        field[2] = 1948754
-        self.assertEqual(self._def, field)
-
-    def test_eq_invalid_type(self):
-        self.assertNotEqual(self._def, 23)
-
-    def test_eq_diff_len(self):
-        fc = bt2.ArrayFieldClass(self._elem_fc, 2)
-        field = fc()
-        field[0] = 45
-        field[1] = 1847
-        self.assertNotEqual(self._def, field)
-
-    def test_eq_diff_content_same_len(self):
-        fc = bt2.ArrayFieldClass(self._elem_fc, 3)
-        field = fc()
-        field[0] = 45
-        field[1] = 1846
-        field[2] = 1948754
-        self.assertNotEqual(self._def, field)
-
-    def test_setitem(self):
-        self._def[2] = 24
-        self.assertEqual(self._def[2], 24)
-
-    def test_setitem_int_field(self):
-        int_field = self._elem_fc()
-        int_field.value = 19487
-        self._def[1] = int_field
-        self.assertEqual(self._def[1], 19487)
-
-    def test_setitem_non_basic_field(self):
-        elem_fc = bt2.StructureFieldClass()
-        array_fc = bt2.ArrayFieldClass(elem_fc, 3)
-        elem_field = elem_fc()
-        array_field = array_fc()
-
-        with self.assertRaises(TypeError):
-            array_field[1] = 23
-
-    def test_setitem_none(self):
-        with self.assertRaises(TypeError):
-            self._def[1] = None
-
-    def test_setitem_index_wrong_type(self):
-        with self.assertRaises(TypeError):
-            self._def['yes'] = 23
-
-    def test_setitem_index_neg(self):
-        with self.assertRaises(IndexError):
-            self._def[-2] = 23
-
-    def test_setitem_index_out_of_range(self):
-        with self.assertRaises(IndexError):
-            self._def[len(self._def)] = 134679
-
-    def test_iter(self):
-        for field, value in zip(self._def, (45, 1847, 1948754)):
-            self.assertEqual(field, value)
-
-    def test_value_int_field(self):
-        values = [45646, 145, 12145]
-        self._def.value = values
-        self.assertEqual(values, self._def)
-
-    def test_value_unset(self):
-        values = [45646, None, 12145]
-        self._def.value = values
-        self.assertFalse(self._def[1].is_set)
-
-    def test_value_rollback(self):
-        values = [45, 1847, 1948754]
-        # value is out of range, should not affect those we set previously
-        with self.assertRaises(bt2.Error):
-            self._def[2].value = 2**60
-        self.assertEqual(values, self._def)
-
-    def test_value_check_sequence(self):
-        values = 42
-        with self.assertRaises(TypeError):
-            self._def.value = values
-
-    def test_value_wrong_type_in_sequence(self):
-        values = [32, 'hello', 11]
-        with self.assertRaises(TypeError):
-            self._def.value = values
-
-    def test_value_complex_type(self):
-        struct_fc = bt2.StructureFieldClass()
-        int_fc = bt2.IntegerFieldClass(32)
-        str_fc = bt2.StringFieldClass()
-        struct_fc.append_field(field_class=int_fc, name='an_int')
-        struct_fc.append_field(field_class=str_fc, name='a_string')
-        struct_fc.append_field(field_class=int_fc, name='another_int')
-        array_fc = bt2.ArrayFieldClass(struct_fc, 3)
-        values = [
-            {
-                'an_int': 42,
-                'a_string': 'hello',
-                'another_int': 66
-            },
-            {
-                'an_int': 1,
-                'a_string': 'goodbye',
-                'another_int': 488
-            },
-            {
-                'an_int': 156,
-                'a_string': 'or not',
-                'another_int': 4648
-            },
-        ]
-
-        array = array_fc()
-        array.value = values
-        self.assertEqual(values, array)
-        values[0]['an_int'] = 'a string'
-        with self.assertRaises(TypeError):
-            array.value = values
-
-    def test_is_set(self):
-        raw = self._def_value
-        field = self._fc()
-        self.assertFalse(field.is_set)
-        field.value = raw
-        self.assertTrue(field.is_set)
-
-    def test_reset(self):
-        raw = self._def_value
-        field = self._fc()
-        field.value = raw
-        self.assertTrue(field.is_set)
-        field.reset()
-        self.assertFalse(field.is_set)
-        other = self._fc()
-        self.assertEqual(other, field)
-
-    def test_str_op(self):
-        s = str(self._def)
-        expected_string = '[{}]'.format(', '.join(
-            [repr(v) for v in self._def_value]))
-        self.assertEqual(expected_string, s)
-
-    def test_str_op_unset(self):
-        self.assertEqual(str(self._fc()), 'Unset')
-
-
-@unittest.skip("this is broken")
-class ArrayFieldTestCase(_TestArraySequenceFieldCommon, unittest.TestCase):
-    def setUp(self):
-        self._elem_fc = bt2.IntegerFieldClass(32)
-        self._fc = bt2.ArrayFieldClass(self._elem_fc, 3)
-        self._def = self._fc()
-        self._def[0] = 45
-        self._def[1] = 1847
-        self._def[2] = 1948754
-        self._def_value = [45, 1847, 1948754]
-
-    def tearDown(self):
-        del self._elem_fc
-        del self._fc
-        del self._def
-
-    def test_value_wrong_len(self):
-        values = [45, 1847]
-        with self.assertRaises(ValueError):
-            self._def.value = values
-
-
-@unittest.skip("this is broken")
-class SequenceFieldTestCase(_TestArraySequenceFieldCommon, unittest.TestCase):
-    def setUp(self):
-        self._elem_fc = bt2.IntegerFieldClass(32)
-        self._fc = bt2.SequenceFieldClass(self._elem_fc, 'the.length')
-        self._def = self._fc()
-        self._length_field = self._elem_fc(3)
-        self._def.length_field = self._length_field
-        self._def[0] = 45
-        self._def[1] = 1847
-        self._def[2] = 1948754
-        self._def_value = [45, 1847, 1948754]
-
-    def tearDown(self):
-        del self._elem_fc
-        del self._fc
-        del self._def
-        del self._length_field
-
-    def test_value_resize(self):
-        new_values = [1, 2, 3, 4]
-        self._def.value = new_values
-        self.assertCountEqual(self._def, new_values)
-
-    def test_value_resize_rollback(self):
-        with self.assertRaises(TypeError):
-            self._def.value = [1, 2, 3, 'unexpected string']
-        self.assertEqual(self._def, self._def_value)
-
-        self._def.reset()
-        with self.assertRaises(TypeError):
-            self._def.value = [1, 2, 3, 'unexpected string']
-        self.assertFalse(self._def.is_set)
-
-
-@unittest.skip("this is broken")
-class StructureFieldTestCase(_TestCopySimple, unittest.TestCase):
-    def setUp(self):
-        self._fc0 = bt2.IntegerFieldClass(32, is_signed=True)
-        self._fc1 = bt2.StringFieldClass()
-        self._fc2 = bt2.FloatingPointNumberFieldClass()
-        self._fc3 = bt2.IntegerFieldClass(17)
-        self._fc = bt2.StructureFieldClass()
-        self._fc.append_field('A', self._fc0)
-        self._fc.append_field('B', self._fc1)
-        self._fc.append_field('C', self._fc2)
-        self._fc.append_field('D', self._fc3)
-        self._def = self._fc()
-        self._def['A'] = -1872
-        self._def['B'] = 'salut'
-        self._def['C'] = 17.5
-        self._def['D'] = 16497
-        self._def_value = {
-            'A': -1872,
-            'B': 'salut',
-            'C': 17.5,
-            'D': 16497
-        }
-
-    def tearDown(self):
-        del self._fc0
-        del self._fc1
-        del self._fc2
-        del self._fc3
-        del self._fc
-        del self._def
-
-    def _modify_def(self):
-        self._def['B'] = 'hola'
-
-    def test_bool_op_true(self):
-        self.assertTrue(self._def)
-
-    def test_bool_op_false(self):
-        fc = bt2.StructureFieldClass()
-        field = fc()
-        self.assertFalse(field)
-
-    def test_len(self):
-        self.assertEqual(len(self._def), 4)
-
-    def test_getitem(self):
-        field = self._def['A']
-        self.assertIs(type(field), bt2.fields._IntegerField)
-        self.assertEqual(field, -1872)
-
-    def test_at_index_out_of_bounds_after(self):
-        with self.assertRaises(IndexError):
-            self._def.at_index(len(self._fc))
-
-    def test_eq(self):
-        fc = bt2.StructureFieldClass()
-        fc.append_field('A', self._fc0)
-        fc.append_field('B', self._fc1)
-        fc.append_field('C', self._fc2)
-        fc.append_field('D', self._fc3)
-        field = fc()
-        field['A'] = -1872
-        field['B'] = 'salut'
-        field['C'] = 17.5
-        field['D'] = 16497
-        self.assertEqual(self._def, field)
-
-    def test_eq_invalid_type(self):
-        self.assertNotEqual(self._def, 23)
-
-    def test_eq_diff_len(self):
-        fc = bt2.StructureFieldClass()
-        fc.append_field('A', self._fc0)
-        fc.append_field('B', self._fc1)
-        fc.append_field('C', self._fc2)
-        field = fc()
-        field['A'] = -1872
-        field['B'] = 'salut'
-        field['C'] = 17.5
-        self.assertNotEqual(self._def, field)
-
-    def test_eq_diff_content_same_len(self):
-        fc = bt2.StructureFieldClass()
-        fc.append_field('A', self._fc0)
-        fc.append_field('B', self._fc1)
-        fc.append_field('C', self._fc2)
-        fc.append_field('D', self._fc3)
-        field = fc()
-        field['A'] = -1872
-        field['B'] = 'salut'
-        field['C'] = 17.4
-        field['D'] = 16497
-        self.assertNotEqual(self._def, field)
-
-    def test_eq_same_content_diff_keys(self):
-        fc = bt2.StructureFieldClass()
-        fc.append_field('A', self._fc0)
-        fc.append_field('B', self._fc1)
-        fc.append_field('E', self._fc2)
-        fc.append_field('D', self._fc3)
-        field = fc()
-        field['A'] = -1872
-        field['B'] = 'salut'
-        field['E'] = 17.4
-        field['D'] = 16497
-        self.assertNotEqual(self._def, field)
-
-    def test_setitem(self):
-        self._def['C'] = -18.47
-        self.assertEqual(self._def['C'], -18.47)
-
-    def test_setitem_int_field(self):
-        int_fc = bt2.IntegerFieldClass(16)
-        int_field = int_fc()
-        int_field.value = 19487
-        self._def['D'] = int_field
-        self.assertEqual(self._def['D'], 19487)
-
-    def test_setitem_non_basic_field(self):
-        elem_fc = bt2.StructureFieldClass()
-        elem_field = elem_fc()
-        struct_fc = bt2.StructureFieldClass()
-        struct_fc.append_field('A', elem_fc)
-        struct_field = struct_fc()
-
-        # Will fail on access to .items() of the value
-        with self.assertRaises(AttributeError):
-            struct_field['A'] = 23
-
-    def test_setitem_none(self):
-        with self.assertRaises(TypeError):
-            self._def['C'] = None
-
-    def test_setitem_key_wrong_type(self):
-        with self.assertRaises(TypeError):
-            self._def[3] = 23
-
-    def test_setitem_wrong_key(self):
-        with self.assertRaises(KeyError):
-            self._def['hi'] = 134679
-
-    def test_at_index(self):
-        self.assertEqual(self._def.at_index(1), 'salut')
-
-    def test_iter(self):
-        orig_values = {
-            'A': -1872,
-            'B': 'salut',
-            'C': 17.5,
-            'D': 16497,
-        }
-
-        for vkey, vval in self._def.items():
-            val = orig_values[vkey]
-            self.assertEqual(vval, val)
-
-    def test_value(self):
-        orig_values = {
-            'A': -1872,
-            'B': 'salut',
-            'C': 17.5,
-            'D': 16497,
-        }
-        self.assertEqual(self._def, orig_values)
-
-    def test_set_value(self):
-        int_fc = bt2.IntegerFieldClass(32)
-        str_fc = bt2.StringFieldClass()
-        struct_fc = bt2.StructureFieldClass()
-        struct_fc.append_field(field_class=int_fc, name='an_int')
-        struct_fc.append_field(field_class=str_fc, name='a_string')
-        struct_fc.append_field(field_class=int_fc, name='another_int')
-        values = {
-            'an_int': 42,
-            'a_string': 'hello',
-            'another_int': 66
-        }
-
-        struct = struct_fc()
-        struct.value = values
-        self.assertEqual(values, struct)
-
-        bad_type_values = copy.deepcopy(values)
-        bad_type_values['an_int'] = 'a string'
-        with self.assertRaises(TypeError):
-            struct.value = bad_type_values
-
-        unknown_key_values = copy.deepcopy(values)
-        unknown_key_values['unknown_key'] = 16546
-        with self.assertRaises(KeyError):
-            struct.value = unknown_key_values
-
-    def test_value_rollback(self):
-        int_fc = bt2.IntegerFieldClass(32)
-        str_fc = bt2.StringFieldClass()
-        struct_fc = bt2.StructureFieldClass()
-        struct_fc.append_field(field_class=int_fc, name='an_int')
-        struct_fc.append_field(field_class=str_fc, name='a_string')
-        struct_fc.append_field(field_class=int_fc, name='another_int')
-        values = {
-            'an_int': 42,
-            'a_string': 'hello',
-            'another_int': 66
-        }
-
-    def test_is_set(self):
-        values = {
-            'an_int': 42,
-            'a_string': 'hello',
-            'another_int': 66
-        }
-
-        int_fc = bt2.IntegerFieldClass(32)
-        str_fc = bt2.StringFieldClass()
-        struct_fc = bt2.StructureFieldClass()
-        struct_fc.append_field(field_class=int_fc, name='an_int')
-        struct_fc.append_field(field_class=str_fc, name='a_string')
-        struct_fc.append_field(field_class=int_fc, name='another_int')
-
-        struct = struct_fc()
-        self.assertFalse(struct.is_set)
-        struct.value = values
-        self.assertTrue(struct.is_set)
-
-        struct = struct_fc()
-        struct['an_int'].value = 42
-        self.assertFalse(struct.is_set)
-
-    def test_reset(self):
-        values = {
-            'an_int': 42,
-            'a_string': 'hello',
-            'another_int': 66
-        }
-
-        int_fc = bt2.IntegerFieldClass(32)
-        str_fc = bt2.StringFieldClass()
-        struct_fc = bt2.StructureFieldClass()
-        struct_fc.append_field(field_class=int_fc, name='an_int')
-        struct_fc.append_field(field_class=str_fc, name='a_string')
-        struct_fc.append_field(field_class=int_fc, name='another_int')
-
-        struct = struct_fc()
-        struct.value = values
-        self.assertTrue(struct.is_set)
-        struct.reset()
-        self.assertEqual(struct_fc(), struct)
-
-    def test_str_op(self):
-        expected_string_found = False
-        s = str(self._def)
-        # Establish all permutations of the three expected matches since
-        # the order in which mappings are enumerated is not explicitly part of
-        # the API.
-        for p in itertools.permutations([(k, v) for k, v in self._def.items()]):
-            items = ['{}: {}'.format(repr(k), repr(v)) for k, v in p]
-            candidate = '{{{}}}'.format(', '.join(items))
-            if candidate == s:
-                expected_string_found = True
-                break
-
-        self.assertTrue(expected_string_found)
-
-    def test_str_op_unset(self):
-        self.assertEqual(str(self._fc()), 'Unset')
-
-
-@unittest.skip("this is broken")
-class VariantFieldTestCase(_TestCopySimple, unittest.TestCase):
-    def setUp(self):
-        self._tag_fc = bt2.EnumerationFieldClass(size=32)
-        self._tag_fc.add_mapping('corner', 23)
-        self._tag_fc.add_mapping('zoom', 17, 20)
-        self._tag_fc.add_mapping('mellotron', 1001)
-        self._tag_fc.add_mapping('giorgio', 2000, 3000)
-        self._fc0 = bt2.IntegerFieldClass(32, is_signed=True)
-        self._fc1 = bt2.StringFieldClass()
-        self._fc2 = bt2.FloatingPointNumberFieldClass()
-        self._fc3 = bt2.IntegerFieldClass(17)
-        self._fc = bt2.VariantFieldClass('salut', self._tag_fc)
-        self._fc.append_field('corner', self._fc0)
-        self._fc.append_field('zoom', self._fc1)
-        self._fc.append_field('mellotron', self._fc2)
-        self._fc.append_field('giorgio', self._fc3)
-        self._def = self._fc()
-
-    def tearDown(self):
-        del self._tag_fc
-        del self._fc0
-        del self._fc1
-        del self._fc2
-        del self._fc3
-        del self._fc
-        del self._def
-
-    def test_bool_op_true(self):
-        tag_field = self._tag_fc(1001)
-        self._def.field(tag_field).value = -17.34
-        self.assertTrue(self._def)
-
-    def test_bool_op_false(self):
-        self.assertFalse(self._def)
-
-    def test_tag_field_none(self):
-        self.assertIsNone(self._def.tag_field)
-
-    def test_tag_field(self):
-        tag_field = self._tag_fc(2800)
-        self._def.field(tag_field).value = 1847
-        self.assertEqual(self._def.tag_field, tag_field)
-        self.assertEqual(self._def.tag_field.addr, tag_field.addr)
-
-    def test_selected_field_none(self):
-        self.assertIsNone(self._def.selected_field)
-
-    def test_selected_field(self):
-        var_field1 = self._fc()
-        tag_field1 = self._tag_fc(1001)
-        var_field1.field(tag_field1).value = -17.34
-        self.assertEqual(var_field1.field(), -17.34)
-        self.assertEqual(var_field1.selected_field, -17.34)
-        var_field2 = self._fc()
-        tag_field2 = self._tag_fc(2500)
-        var_field2.field(tag_field2).value = 1921
-        self.assertEqual(var_field2.field(), 1921)
-        self.assertEqual(var_field2.selected_field, 1921)
-
-    def test_eq(self):
-        tag_fc = bt2.EnumerationFieldClass(size=32)
-        tag_fc.add_mapping('corner', 23)
-        tag_fc.add_mapping('zoom', 17, 20)
-        tag_fc.add_mapping('mellotron', 1001)
-        tag_fc.add_mapping('giorgio', 2000, 3000)
-        fc0 = bt2.IntegerFieldClass(32, is_signed=True)
-        fc1 = bt2.StringFieldClass()
-        fc2 = bt2.FloatingPointNumberFieldClass()
-        fc3 = bt2.IntegerFieldClass(17)
-        fc = bt2.VariantFieldClass('salut', tag_fc)
-        fc.append_field('corner', fc0)
-        fc.append_field('zoom', fc1)
-        fc.append_field('mellotron', fc2)
-        fc.append_field('giorgio', fc3)
-        field = fc()
-        field_tag = tag_fc(23)
-        def_tag = self._tag_fc(23)
-        field.field(field_tag).value = 1774
-        self._def.field(def_tag).value = 1774
-        self.assertEqual(self._def, field)
-
-    def test_eq_invalid_type(self):
-        self.assertNotEqual(self._def, 23)
-
-    def test_is_set(self):
-        self.assertFalse(self._def.is_set)
-        tag_field = self._tag_fc(2800)
-        self._def.field(tag_field).value = 684
-        self.assertTrue(self._def.is_set)
-
-    def test_reset(self):
-        tag_field = self._tag_fc(2800)
-        self._def.field(tag_field).value = 684
-        self._def.reset()
-        self.assertFalse(self._def.is_set)
-        self.assertIsNone(self._def.selected_field)
-        self.assertIsNone(self._def.tag_field)
-
-    def test_str_op_int(self):
-        v = self._fc()
-        v.field(self._tag_fc(23)).value = 42
-        f = self._fc0(42)
-        self.assertEqual(str(f), str(v))
-
-    def test_str_op_str(self):
-        v = self._fc()
-        v.field(self._tag_fc(18)).value = 'some test string'
-        f = self._fc1('some test string')
-        self.assertEqual(str(f), str(v))
-
-    def test_str_op_flt(self):
-        v = self._fc()
-        v.field(self._tag_fc(1001)).value = 14.4245
-        f = self._fc2(14.4245)
-        self.assertEqual(str(f), str(v))
-
-    def test_str_op_unset(self):
-        self.assertEqual(str(self._fc()), 'Unset')
index 9021821a11c22d54cb18c43fd2a8d07c289946b3..1d37e22502e67e4e542b57a4fbea28184bd30e20 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import collections
 import unittest
 import copy
index de60c49bd910b00904ba132e4b24e80a5d79d632..77a4ca15cfbfc6e660d7c0f6a1f35ba0127e301a 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import collections
 import unittest
 import copy
index 3f7e121af774a5f4773e3b4580caacf528d85a03..455fca55d16f2f270b8233c344c18be7e737c622 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import collections
 import unittest
 import copy
index bd5482ef98e0b088e600bbd89538c653f7a453dc..f7592820d6ff189031028e729ac61edd8ed33c7a 100644 (file)
@@ -1,5 +1,5 @@
 from collections import OrderedDict
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index bc5249173f7a1e1ec9a68819c2ef2e5c2048f1f2..68943b39d158f567dac4fe701e6190bdb5e0c777 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index 93b9ab12199fe4d9563e81fe4d6e05adb29929d5..b346cbb6c272a7c7bbaa796edb3ddf6856c4999f 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index cdaccdcf087a7a5305aa1f865e5429a5a07e2436..e1b298861f4dc661c3633acf9366e18da8a904e7 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index c3b7f65f5df4c4422ffd440cc33850b66ecbc4fe..fa31088f9f3309b0c336468613e9f1373b8f08b4 100644 (file)
@@ -1,5 +1,5 @@
 from collections import OrderedDict
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index 5f8267bf05a9f735cd1540a607267cbd68596d7c..3f5f4a8abd2e9b1fba9cf74593dfdff98699329d 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import bt2
index b82cf12c9c16d5b6fe668f13e18d5f3f78e80c62..d4c7de90e246e564afdeaba0c6ed5769b8fce164 100644 (file)
@@ -1,4 +1,4 @@
-from bt2 import values
+from bt2 import value
 import unittest
 import copy
 import uuid
diff --git a/tests/bindings/python/bt2/test_value.py b/tests/bindings/python/bt2/test_value.py
new file mode 100644 (file)
index 0000000..2b15d10
--- /dev/null
@@ -0,0 +1,1567 @@
+from functools import partial, partialmethod
+import operator
+import unittest
+import numbers
+import math
+import copy
+import bt2
+
+
+class _TestFrozen:
+    def test_is_frozen(self):
+        self._def.freeze()
+        self.assertTrue(self._def.is_frozen)
+
+    def test_frozen(self):
+        self._def.freeze()
+        self.assertTrue(self._def.frozen)
+
+    def test_frozen_exc(self):
+        self._def.freeze()
+
+        with self.assertRaisesRegex(bt2.Frozen, r'.* value object is frozen$') as cm:
+            self._modify_def()
+
+        self.assertEqual(self._def, self._def_value)
+
+    def test_get_value_when_frozen(self):
+        self._def.freeze()
+        self.assertEqual(self._def, self._def_value)
+
+
+class _TestFrozenSimple(_TestFrozen):
+    def _modify_def(self):
+        self._def.value = self._def_new_value
+
+
+class _TestCopySimple:
+    def test_copy(self):
+        cpy = copy.copy(self._def)
+        self.assertIsNot(cpy, self._def)
+        self.assertNotEqual(cpy.addr, self._def.addr)
+        self.assertEqual(cpy, self._def)
+
+    def test_deepcopy(self):
+        cpy = copy.deepcopy(self._def)
+        self.assertIsNot(cpy, self._def)
+        self.assertNotEqual(cpy.addr, self._def.addr)
+        self.assertEqual(cpy, self._def)
+
+
+_COMP_BINOPS = (
+    operator.eq,
+    operator.ne,
+)
+
+
+class _TestNumericValue(_TestFrozenSimple, _TestCopySimple):
+    def _binop(self, op, rhs):
+        rexc = None
+        rvexc = None
+        comp_value = rhs
+
+        try:
+            r = op(self._def, rhs)
+        except Exception as e:
+            rexc = e
+
+        try:
+            rv = op(self._def_value, comp_value)
+        except Exception as e:
+            rvexc = e
+
+        if rexc is not None or rvexc is not None:
+            # at least one of the operations raised an exception: in
+            # this case both operations should have raised the same
+            # type of exception (division by zero, bit shift with a
+            # floating point number operand, etc.)
+            self.assertIs(type(rexc), type(rvexc))
+            return None, None
+
+        return r, rv
+
+    def _unaryop(self, op):
+        rexc = None
+        rvexc = None
+
+        try:
+            r = op(self._def)
+        except Exception as e:
+            rexc = e
+
+        try:
+            rv = op(self._def_value)
+        except Exception as e:
+            rvexc = e
+
+        if rexc is not None or rvexc is not None:
+            # at least one of the operations raised an exception: in
+            # this case both operations should have raised the same
+            # type of exception (division by zero, bit shift with a
+            # floating point number operand, etc.)
+            self.assertIs(type(rexc), type(rvexc))
+            return None, None
+
+        return r, rv
+
+    def _test_unaryop_type(self, op):
+        r, rv = self._unaryop(op)
+
+        if r is None:
+            return
+
+        self.assertIsInstance(r, type(rv))
+
+    def _test_unaryop_value(self, op):
+        r, rv = self._unaryop(op)
+
+        if r is None:
+            return
+
+        self.assertEqual(r, rv)
+
+    def _test_unaryop_addr_same(self, op):
+        addr_before = self._def.addr
+        self._unaryop(op)
+        self.assertEqual(self._def.addr, addr_before)
+
+    def _test_unaryop_value_same(self, op):
+        value_before = copy.copy(self._def)
+        self._unaryop(op)
+        self.assertEqual(self._def, value_before)
+
+    def _test_binop_type(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        if op in _COMP_BINOPS:
+            # __eq__() and __ne__() always return a 'bool' object
+            self.assertIsInstance(r, bool)
+        else:
+            self.assertIsInstance(r, type(rv))
+
+    def _test_binop_value(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        self.assertEqual(r, rv)
+
+    def _test_binop_lhs_addr_same(self, op, rhs):
+        addr_before = self._def.addr
+        r, rv = self._binop(op, rhs)
+        self.assertEqual(self._def.addr, addr_before)
+
+    def _test_binop_lhs_value_same(self, op, rhs):
+        value_before = copy.copy(self._def)
+        r, rv = self._binop(op, rhs)
+        self.assertEqual(self._def, value_before)
+
+    def _test_binop_invalid_unknown(self, op):
+        if op in _COMP_BINOPS:
+            self.skipTest('not testing')
+
+        class A:
+            pass
+
+        with self.assertRaises(TypeError):
+            op(self._def, A())
+
+    def _test_binop_invalid_none(self, op):
+        if op in _COMP_BINOPS:
+            self.skipTest('not testing')
+
+        with self.assertRaises(TypeError):
+            op(self._def, None)
+
+    def _test_ibinop_value(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        # The inplace operators are special for value objects because
+        # they do not return a new, immutable object like it's the case
+        # for Python numbers. In Python, `a += 2`, where `a` is a number
+        # object, assigns a new number object reference to `a`, dropping
+        # the old reference. Since BT's value objects are mutable, we
+        # modify their internal value with the inplace operators. This
+        # means however that we can lose data in the process, for
+        # example:
+        #
+        #     int_value_obj += 3.3
+        #
+        # Here, if `int_value_obj` is a Python `int` with the value 2,
+        # it would be a `float` object after this, holding the value
+        # 5.3. In our case, if `int_value_obj` is an integer value
+        # object, 3.3 is converted to an `int` object (3) and added to
+        # the current value of `int_value_obj`, so after this the value
+        # of the object is 5. This does not compare to 5.3, which is
+        # why we also use the `int()` type here.
+        if type(self._def) is bt2.IntegerValue:
+            rv = int(rv)
+
+        self.assertEqual(r, rv)
+
+    def _test_ibinop_type(self, op, rhs):
+        r, rv = self._binop(op, rhs)
+
+        if r is None:
+            return
+
+        self.assertIs(r, self._def)
+
+    def _test_ibinop_invalid_unknown(self, op):
+        class A:
+            pass
+
+        with self.assertRaises(TypeError):
+            op(self._def, A())
+
+    def _test_ibinop_invalid_none(self, op):
+        with self.assertRaises(TypeError):
+            op(self._def, None)
+
+    def _test_binop_rhs_false(self, test_cb, op):
+        test_cb(op, False)
+
+    def _test_binop_rhs_true(self, test_cb, op):
+        test_cb(op, True)
+
+    def _test_binop_rhs_pos_int(self, test_cb, op):
+        test_cb(op, 2)
+
+    def _test_binop_rhs_neg_int(self, test_cb, op):
+        test_cb(op, -23)
+
+    def _test_binop_rhs_zero_int(self, test_cb, op):
+        test_cb(op, 0)
+
+    def _test_binop_rhs_pos_vint(self, test_cb, op):
+        test_cb(op, bt2.create_value(2))
+
+    def _test_binop_rhs_neg_vint(self, test_cb, op):
+        test_cb(op, bt2.create_value(-23))
+
+    def _test_binop_rhs_zero_vint(self, test_cb, op):
+        test_cb(op, bt2.create_value(0))
+
+    def _test_binop_rhs_pos_float(self, test_cb, op):
+        test_cb(op, 2.2)
+
+    def _test_binop_rhs_neg_float(self, test_cb, op):
+        test_cb(op, -23.4)
+
+    def _test_binop_rhs_zero_float(self, test_cb, op):
+        test_cb(op, 0.0)
+
+    def _test_binop_rhs_pos_vfloat(self, test_cb, op):
+        test_cb(op, bt2.create_value(2.2))
+
+    def _test_binop_rhs_neg_vfloat(self, test_cb, op):
+        test_cb(op, bt2.create_value(-23.4))
+
+    def _test_binop_rhs_zero_vfloat(self, test_cb, op):
+        test_cb(op, bt2.create_value(0.0))
+
+    def _test_binop_type_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_type, op)
+
+    def _test_binop_type_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_type, op)
+
+    def _test_binop_type_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_type, op)
+
+    def _test_binop_type_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_type, op)
+
+    def _test_binop_type_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_type, op)
+
+    def _test_binop_type_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_type, op)
+
+    def _test_binop_type_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_type, op)
+
+    def _test_binop_type_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_type, op)
+
+    def _test_binop_type_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_type, op)
+
+    def _test_binop_type_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_type, op)
+
+    def _test_binop_type_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_type, op)
+
+    def _test_binop_type_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_type, op)
+
+    def _test_binop_type_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_type, op)
+
+    def _test_binop_type_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_type, op)
+
+    def _test_binop_value_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_value, op)
+
+    def _test_binop_value_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_value, op)
+
+    def _test_binop_value_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_value, op)
+
+    def _test_binop_value_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_value, op)
+
+    def _test_binop_value_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_value, op)
+
+    def _test_binop_value_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_value, op)
+
+    def _test_binop_value_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_value, op)
+
+    def _test_binop_value_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_value, op)
+
+    def _test_binop_value_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_value, op)
+
+    def _test_binop_value_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_value, op)
+
+    def _test_binop_value_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_value, op)
+
+    def _test_binop_value_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_value, op)
+
+    def _test_binop_value_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_value, op)
+
+    def _test_binop_value_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_value, op)
+
+    def _test_binop_lhs_addr_same_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_addr_same_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_addr_same, op)
+
+    def _test_binop_lhs_value_same_false(self, op):
+        self._test_binop_rhs_false(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_true(self, op):
+        self._test_binop_rhs_true(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_value_same, op)
+
+    def _test_binop_lhs_value_same_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_value_same, op)
+
+    def _test_ibinop_type_false(self, op):
+        self._test_binop_rhs_false(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_true(self, op):
+        self._test_binop_rhs_true(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_ibinop_type, op)
+
+    def _test_ibinop_type_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_ibinop_type, op)
+
+    def _test_ibinop_value_false(self, op):
+        self._test_binop_rhs_false(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_true(self, op):
+        self._test_binop_rhs_true(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_int(self, op):
+        self._test_binop_rhs_pos_int(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_int(self, op):
+        self._test_binop_rhs_neg_int(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_int(self, op):
+        self._test_binop_rhs_zero_int(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_vint(self, op):
+        self._test_binop_rhs_pos_vint(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_vint(self, op):
+        self._test_binop_rhs_neg_vint(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_vint(self, op):
+        self._test_binop_rhs_zero_vint(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_float(self, op):
+        self._test_binop_rhs_pos_float(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_float(self, op):
+        self._test_binop_rhs_neg_float(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_float(self, op):
+        self._test_binop_rhs_zero_float(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_pos_vfloat(self, op):
+        self._test_binop_rhs_pos_vfloat(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_neg_vfloat(self, op):
+        self._test_binop_rhs_neg_vfloat(self._test_ibinop_value, op)
+
+    def _test_ibinop_value_zero_vfloat(self, op):
+        self._test_binop_rhs_zero_vfloat(self._test_ibinop_value, op)
+
+    def test_bool_op(self):
+        self.assertEqual(bool(self._def), bool(self._def_value))
+
+    def test_int_op(self):
+        self.assertEqual(int(self._def), int(self._def_value))
+
+    def test_float_op(self):
+        self.assertEqual(float(self._def), float(self._def_value))
+
+    def test_complex_op(self):
+        self.assertEqual(complex(self._def), complex(self._def_value))
+
+    def test_str_op(self):
+        self.assertEqual(str(self._def), str(self._def_value))
+
+    def test_eq_none(self):
+        self.assertFalse(self._def == None)
+
+    def test_ne_none(self):
+        self.assertTrue(self._def != None)
+
+
+_BINOPS = (
+    ('lt', operator.lt),
+    ('le', operator.le),
+    ('eq', operator.eq),
+    ('ne', operator.ne),
+    ('ge', operator.ge),
+    ('gt', operator.gt),
+    ('add', operator.add),
+    ('radd', lambda a, b: operator.add(b, a)),
+    ('and', operator.and_),
+    ('rand', lambda a, b: operator.and_(b, a)),
+    ('floordiv', operator.floordiv),
+    ('rfloordiv', lambda a, b: operator.floordiv(b, a)),
+    ('lshift', operator.lshift),
+    ('rlshift', lambda a, b: operator.lshift(b, a)),
+    ('mod', operator.mod),
+    ('rmod', lambda a, b: operator.mod(b, a)),
+    ('mul', operator.mul),
+    ('rmul', lambda a, b: operator.mul(b, a)),
+    ('or', operator.or_),
+    ('ror', lambda a, b: operator.or_(b, a)),
+    ('pow', operator.pow),
+    ('rpow', lambda a, b: operator.pow(b, a)),
+    ('rshift', operator.rshift),
+    ('rrshift', lambda a, b: operator.rshift(b, a)),
+    ('sub', operator.sub),
+    ('rsub', lambda a, b: operator.sub(b, a)),
+    ('truediv', operator.truediv),
+    ('rtruediv', lambda a, b: operator.truediv(b, a)),
+    ('xor', operator.xor),
+    ('rxor', lambda a, b: operator.xor(b, a)),
+)
+
+
+_IBINOPS = (
+    ('iadd', operator.iadd),
+    ('iand', operator.iand),
+    ('ifloordiv', operator.ifloordiv),
+    ('ilshift', operator.ilshift),
+    ('imod', operator.imod),
+    ('imul', operator.imul),
+    ('ior', operator.ior),
+    ('ipow', operator.ipow),
+    ('irshift', operator.irshift),
+    ('isub', operator.isub),
+    ('itruediv', operator.itruediv),
+    ('ixor', operator.ixor),
+)
+
+
+_UNARYOPS = (
+    ('neg', operator.neg),
+    ('pos', operator.pos),
+    ('abs', operator.abs),
+    ('invert', operator.invert),
+    ('round', round),
+    ('round_0', partial(round, ndigits=0)),
+    ('round_1', partial(round, ndigits=1)),
+    ('round_2', partial(round, ndigits=2)),
+    ('round_3', partial(round, ndigits=3)),
+    ('ceil', math.ceil),
+    ('floor', math.floor),
+    ('trunc', math.trunc),
+)
+
+
+def _inject_numeric_testing_methods(cls):
+    def test_binop_name(suffix):
+        return 'test_binop_{}_{}'.format(name, suffix)
+
+    def test_ibinop_name(suffix):
+        return 'test_ibinop_{}_{}'.format(name, suffix)
+
+    def test_unaryop_name(suffix):
+        return 'test_unaryop_{}_{}'.format(name, suffix)
+
+    # inject testing methods for each binary operation
+    for name, binop in _BINOPS:
+
+        setattr(cls, test_binop_name('invalid_unknown'), partialmethod(_TestNumericValue._test_binop_invalid_unknown, op=binop))
+        setattr(cls, test_binop_name('invalid_none'), partialmethod(_TestNumericValue._test_binop_invalid_none, op=binop))
+        setattr(cls, test_binop_name('type_true'), partialmethod(_TestNumericValue._test_binop_type_true, op=binop))
+        setattr(cls, test_binop_name('type_pos_int'), partialmethod(_TestNumericValue._test_binop_type_pos_int, op=binop))
+        setattr(cls, test_binop_name('type_pos_vint'), partialmethod(_TestNumericValue._test_binop_type_pos_vint, op=binop))
+        setattr(cls, test_binop_name('value_true'), partialmethod(_TestNumericValue._test_binop_value_true, op=binop))
+        setattr(cls, test_binop_name('value_pos_int'), partialmethod(_TestNumericValue._test_binop_value_pos_int, op=binop))
+        setattr(cls, test_binop_name('value_pos_vint'), partialmethod(_TestNumericValue._test_binop_value_pos_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_true'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_true, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_int'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_int, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_vint'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_true'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_true, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_int'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_int, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_vint'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_vint, op=binop))
+        setattr(cls, test_binop_name('type_neg_int'), partialmethod(_TestNumericValue._test_binop_type_neg_int, op=binop))
+        setattr(cls, test_binop_name('type_neg_vint'), partialmethod(_TestNumericValue._test_binop_type_neg_vint, op=binop))
+        setattr(cls, test_binop_name('value_neg_int'), partialmethod(_TestNumericValue._test_binop_value_neg_int, op=binop))
+        setattr(cls, test_binop_name('value_neg_vint'), partialmethod(_TestNumericValue._test_binop_value_neg_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_int'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_int, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_vint'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_int'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_int, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_vint'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_vint, op=binop))
+        setattr(cls, test_binop_name('type_false'), partialmethod(_TestNumericValue._test_binop_type_false, op=binop))
+        setattr(cls, test_binop_name('type_zero_int'), partialmethod(_TestNumericValue._test_binop_type_zero_int, op=binop))
+        setattr(cls, test_binop_name('type_zero_vint'), partialmethod(_TestNumericValue._test_binop_type_zero_vint, op=binop))
+        setattr(cls, test_binop_name('value_false'), partialmethod(_TestNumericValue._test_binop_value_false, op=binop))
+        setattr(cls, test_binop_name('value_zero_int'), partialmethod(_TestNumericValue._test_binop_value_zero_int, op=binop))
+        setattr(cls, test_binop_name('value_zero_vint'), partialmethod(_TestNumericValue._test_binop_value_zero_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_false'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_false, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_int'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_int, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_vint'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_vint, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_false'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_false, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_int'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_int, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_vint'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_vint, op=binop))
+        setattr(cls, test_binop_name('type_pos_float'), partialmethod(_TestNumericValue._test_binop_type_pos_float, op=binop))
+        setattr(cls, test_binop_name('type_neg_float'), partialmethod(_TestNumericValue._test_binop_type_neg_float, op=binop))
+        setattr(cls, test_binop_name('type_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_type_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('type_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_type_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('value_pos_float'), partialmethod(_TestNumericValue._test_binop_value_pos_float, op=binop))
+        setattr(cls, test_binop_name('value_neg_float'), partialmethod(_TestNumericValue._test_binop_value_neg_float, op=binop))
+        setattr(cls, test_binop_name('value_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_value_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('value_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_value_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_float'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_float, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_float'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_float, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_float'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_float, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_float'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_float, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_vfloat, op=binop))
+        setattr(cls, test_binop_name('type_zero_float'), partialmethod(_TestNumericValue._test_binop_type_zero_float, op=binop))
+        setattr(cls, test_binop_name('type_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_type_zero_vfloat, op=binop))
+        setattr(cls, test_binop_name('value_zero_float'), partialmethod(_TestNumericValue._test_binop_value_zero_float, op=binop))
+        setattr(cls, test_binop_name('value_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_value_zero_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_float'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_float, op=binop))
+        setattr(cls, test_binop_name('lhs_addr_same_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_vfloat, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_float'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_float, op=binop))
+        setattr(cls, test_binop_name('lhs_value_same_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_vfloat, op=binop))
+
+    # inject testing methods for each unary operation
+    for name, unaryop in _UNARYOPS:
+        setattr(cls, test_unaryop_name('type'), partialmethod(_TestNumericValue._test_unaryop_type, op=unaryop))
+        setattr(cls, test_unaryop_name('value'), partialmethod(_TestNumericValue._test_unaryop_value, op=unaryop))
+        setattr(cls, test_unaryop_name('addr_same'), partialmethod(_TestNumericValue._test_unaryop_addr_same, op=unaryop))
+        setattr(cls, test_unaryop_name('value_same'), partialmethod(_TestNumericValue._test_unaryop_value_same, op=unaryop))
+
+    # inject testing methods for each inplace binary operation
+    for name, ibinop in _IBINOPS:
+        setattr(cls, test_ibinop_name('invalid_unknown'), partialmethod(_TestNumericValue._test_ibinop_invalid_unknown, op=ibinop))
+        setattr(cls, test_ibinop_name('invalid_none'), partialmethod(_TestNumericValue._test_ibinop_invalid_none, op=ibinop))
+        setattr(cls, test_ibinop_name('type_true'), partialmethod(_TestNumericValue._test_ibinop_type_true, op=ibinop))
+        setattr(cls, test_ibinop_name('value_true'), partialmethod(_TestNumericValue._test_ibinop_value_true, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_int'), partialmethod(_TestNumericValue._test_ibinop_type_pos_int, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_vint'), partialmethod(_TestNumericValue._test_ibinop_type_pos_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_int'), partialmethod(_TestNumericValue._test_ibinop_value_pos_int, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_vint'), partialmethod(_TestNumericValue._test_ibinop_value_pos_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_int'), partialmethod(_TestNumericValue._test_ibinop_type_neg_int, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_vint'), partialmethod(_TestNumericValue._test_ibinop_type_neg_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_int'), partialmethod(_TestNumericValue._test_ibinop_value_neg_int, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_vint'), partialmethod(_TestNumericValue._test_ibinop_value_neg_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('type_false'), partialmethod(_TestNumericValue._test_ibinop_type_false, op=ibinop))
+        setattr(cls, test_ibinop_name('value_false'), partialmethod(_TestNumericValue._test_ibinop_value_false, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_int'), partialmethod(_TestNumericValue._test_ibinop_type_zero_int, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_vint'), partialmethod(_TestNumericValue._test_ibinop_type_zero_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_int'), partialmethod(_TestNumericValue._test_ibinop_value_zero_int, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_vint'), partialmethod(_TestNumericValue._test_ibinop_value_zero_vint, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_float'), partialmethod(_TestNumericValue._test_ibinop_type_pos_float, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_float'), partialmethod(_TestNumericValue._test_ibinop_type_neg_float, op=ibinop))
+        setattr(cls, test_ibinop_name('type_pos_vfloat'), partialmethod(_TestNumericValue._test_ibinop_type_pos_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('type_neg_vfloat'), partialmethod(_TestNumericValue._test_ibinop_type_neg_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_float'), partialmethod(_TestNumericValue._test_ibinop_value_pos_float, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_float'), partialmethod(_TestNumericValue._test_ibinop_value_neg_float, op=ibinop))
+        setattr(cls, test_ibinop_name('value_pos_vfloat'), partialmethod(_TestNumericValue._test_ibinop_value_pos_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('value_neg_vfloat'), partialmethod(_TestNumericValue._test_ibinop_value_neg_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_float'), partialmethod(_TestNumericValue._test_ibinop_type_zero_float, op=ibinop))
+        setattr(cls, test_ibinop_name('type_zero_vfloat'), partialmethod(_TestNumericValue._test_ibinop_type_zero_vfloat, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_float'), partialmethod(_TestNumericValue._test_ibinop_value_zero_float, op=ibinop))
+        setattr(cls, test_ibinop_name('value_zero_vfloat'), partialmethod(_TestNumericValue._test_ibinop_value_zero_vfloat, op=ibinop))
+
+
+@unittest.skip("this is broken")
+class CreateValueFuncTestCase(unittest.TestCase):
+    def test_create_none(self):
+        v = bt2.create_value(None)
+        self.assertIsNone(v)
+
+    def test_create_bool_false(self):
+        v = bt2.create_value(False)
+        self.assertIsInstance(v, bt2.BoolValue)
+        self.assertFalse(v)
+
+    def test_create_bool_true(self):
+        v = bt2.create_value(True)
+        self.assertIsInstance(v, bt2.BoolValue)
+        self.assertTrue(v)
+
+    def test_create_int_pos(self):
+        raw = 23
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.IntegerValue)
+        self.assertEqual(v, raw)
+
+    def test_create_int_neg(self):
+        raw = -23
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.IntegerValue)
+        self.assertEqual(v, raw)
+
+    def test_create_float_pos(self):
+        raw = 17.5
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.FloatValue)
+        self.assertEqual(v, raw)
+
+    def test_create_float_neg(self):
+        raw = -17.5
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.FloatValue)
+        self.assertEqual(v, raw)
+
+    def test_create_string(self):
+        raw = 'salut'
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.StringValue)
+        self.assertEqual(v, raw)
+
+    def test_create_string_empty(self):
+        raw = ''
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.StringValue)
+        self.assertEqual(v, raw)
+
+    def test_create_array_from_list(self):
+        raw = [1, 2, 3]
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.ArrayValue)
+        self.assertEqual(v, raw)
+
+    def test_create_array_from_tuple(self):
+        raw = 4, 5, 6
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.ArrayValue)
+        self.assertEqual(v, raw)
+
+    def test_create_array_from_empty_list(self):
+        raw = []
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.ArrayValue)
+        self.assertEqual(v, raw)
+
+    def test_create_array_from_empty_tuple(self):
+        raw = ()
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.ArrayValue)
+        self.assertEqual(v, raw)
+
+    def test_create_map(self):
+        raw = {'salut': 23}
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.MapValue)
+        self.assertEqual(v, raw)
+
+    def test_create_map_empty(self):
+        raw = {}
+        v = bt2.create_value(raw)
+        self.assertIsInstance(v, bt2.MapValue)
+        self.assertEqual(v, raw)
+
+    def test_create_vfalse(self):
+        v = bt2.create_value(bt2.create_value(False))
+        self.assertIsInstance(v, bt2.BoolValue)
+        self.assertFalse(v)
+
+    def test_create_invalid(self):
+        class A:
+            pass
+
+        a = A()
+
+        with self.assertRaisesRegex(TypeError, "cannot create value object from 'A' object") as cm:
+            v = bt2.create_value(a)
+
+
+@unittest.skip("this is broken")
+class BoolValueTestCase(_TestFrozenSimple, _TestCopySimple, unittest.TestCase):
+    def setUp(self):
+        self._f = bt2.BoolValue(False)
+        self._t = bt2.BoolValue(True)
+        self._def = self._f
+        self._def_value = False
+        self._def_new_value = True
+
+    def tearDown(self):
+        del self._f
+        del self._t
+        del self._def
+
+    def _assert_expecting_bool(self):
+        return self.assertRaisesRegex(TypeError, r"expecting a 'bool' object")
+
+    def test_create_default(self):
+        b = bt2.BoolValue()
+        self.assertFalse(b)
+
+    def test_create_false(self):
+        self.assertFalse(self._f)
+
+    def test_create_true(self):
+        self.assertTrue(self._t)
+
+    def test_create_from_vfalse(self):
+        b = bt2.BoolValue(self._f)
+        self.assertFalse(b)
+
+    def test_create_from_vtrue(self):
+        b = bt2.BoolValue(self._t)
+        self.assertTrue(b)
+
+    def test_create_from_int_non_zero(self):
+        with self.assertRaises(TypeError):
+            b = bt2.BoolValue(23)
+
+    def test_create_from_int_zero(self):
+        with self.assertRaises(TypeError):
+            b = bt2.BoolValue(0)
+
+    def test_assign_true(self):
+        b = bt2.BoolValue()
+        b.value = True
+        self.assertTrue(b)
+
+    def test_assign_false(self):
+        b = bt2.BoolValue()
+        b.value = False
+        self.assertFalse(b)
+
+    def test_assign_vtrue(self):
+        b = bt2.BoolValue()
+        b.value = self._t
+        self.assertTrue(b)
+
+    def test_assign_vfalse(self):
+        b = bt2.BoolValue()
+        b.value = False
+        self.assertFalse(b)
+
+    def test_assign_int(self):
+        with self.assertRaises(TypeError):
+            b = bt2.BoolValue()
+            b.value = 23
+
+    def test_bool_op(self):
+        self.assertEqual(bool(self._def), bool(self._def_value))
+
+    def test_str_op(self):
+        self.assertEqual(str(self._def), str(self._def_value))
+
+    def test_eq_none(self):
+        self.assertFalse(self._def == None)
+
+    def test_ne_none(self):
+        self.assertTrue(self._def != None)
+
+    def test_vfalse_eq_false(self):
+        self.assertEqual(self._f, False)
+
+    def test_vfalse_ne_true(self):
+        self.assertNotEqual(self._f, True)
+
+    def test_vtrue_eq_true(self):
+        self.assertEqual(self._t, True)
+
+    def test_vtrue_ne_false(self):
+        self.assertNotEqual(self._t, False)
+
+
+@unittest.skip("this is broken")
+class IntegerValueTestCase(_TestNumericValue, unittest.TestCase):
+    def setUp(self):
+        self._pv = 23
+        self._nv = -52
+        self._ip = bt2.IntegerValue(self._pv)
+        self._in = bt2.IntegerValue(self._nv)
+        self._def = self._ip
+        self._def_value = self._pv
+        self._def_new_value = -101
+
+    def tearDown(self):
+        del self._ip
+        del self._in
+        del self._def
+        del self._def_value
+
+    def _assert_expecting_int(self):
+        return self.assertRaisesRegex(TypeError, r'expecting a number object')
+
+    def _assert_expecting_int64(self):
+        return self.assertRaisesRegex(ValueError, r"expecting a signed 64-bit integral value")
+
+    def _assert_expecting_uint64(self):
+        return self.assertRaisesRegex(ValueError, r"expecting an unsigned 64-bit integral value")
+
+    def test_create_default(self):
+        i = bt2.IntegerValue()
+        self.assertEqual(i, 0)
+
+    def test_create_pos(self):
+        self.assertEqual(self._ip, self._pv)
+
+    def test_create_neg(self):
+        self.assertEqual(self._in, self._nv)
+
+    def test_create_pos_too_big(self):
+        with self._assert_expecting_int64():
+            i = bt2.IntegerValue(2 ** 63)
+
+    def test_create_neg_too_big(self):
+        with self._assert_expecting_int64():
+            i = bt2.IntegerValue(-(2 ** 63) - 1)
+
+    def test_create_from_vint(self):
+        i = bt2.IntegerValue(self._ip)
+        self.assertEqual(i, self._pv)
+
+    def test_create_from_false(self):
+        i = bt2.IntegerValue(False)
+        self.assertFalse(i)
+
+    def test_create_from_true(self):
+        i = bt2.IntegerValue(True)
+        self.assertTrue(i)
+
+    def test_create_from_float(self):
+        i = bt2.IntegerValue(99.6)
+        self.assertEqual(i, 99)
+
+    def test_create_from_vfloat(self):
+        f = bt2.create_value(17.5)
+        i = bt2.IntegerValue(f)
+        self.assertEqual(i, 17)
+
+    def test_create_from_unknown(self):
+        class A:
+            pass
+
+        with self._assert_expecting_int():
+            i = bt2.IntegerValue(A())
+
+    def test_create_from_varray(self):
+        with self._assert_expecting_int():
+            i = bt2.IntegerValue(bt2.ArrayValue())
+
+    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_pos_int(self):
+        raw = 477
+        self._def.value = raw
+        self.assertEqual(self._def, raw)
+
+    def test_assign_neg_int(self):
+        raw = -13
+        self._def.value = raw
+        self.assertEqual(self._def, raw)
+
+    def test_assign_vint(self):
+        raw = 999
+        self._def.value = bt2.create_value(raw)
+        self.assertEqual(self._def, raw)
+
+    def test_assign_vfloat(self):
+        raw = 123.456
+        self._def.value = bt2.create_value(raw)
+        self.assertEqual(self._def, int(raw))
+
+
+_inject_numeric_testing_methods(IntegerValueTestCase)
+
+
+@unittest.skip("this is broken")
+class FloatValueTestCase(_TestNumericValue, unittest.TestCase):
+    def setUp(self):
+        self._pv = 23.4
+        self._nv = -52.7
+        self._fp = bt2.FloatValue(self._pv)
+        self._fn = bt2.FloatValue(self._nv)
+        self._def = self._fp
+        self._def_value = self._pv
+        self._def_new_value = -101.88
+
+    def tearDown(self):
+        del self._fp
+        del self._fn
+        del self._def
+        del self._def_value
+
+    def _assert_expecting_float(self):
+        return self.assertRaisesRegex(TypeError, r"expecting a real number object")
+
+    def _test_invalid_op(self, cb):
+        with self.assertRaises(TypeError):
+            cb()
+
+    def test_create_default(self):
+        f = bt2.FloatValue()
+        self.assertEqual(f, 0.0)
+
+    def test_create_pos(self):
+        self.assertEqual(self._fp, self._pv)
+
+    def test_create_neg(self):
+        self.assertEqual(self._fn, self._nv)
+
+    def test_create_from_vint(self):
+        f = bt2.FloatValue(self._fp)
+        self.assertEqual(f, self._pv)
+
+    def test_create_from_false(self):
+        f = bt2.FloatValue(False)
+        self.assertFalse(f)
+
+    def test_create_from_true(self):
+        f = bt2.FloatValue(True)
+        self.assertTrue(f)
+
+    def test_create_from_int(self):
+        raw = 17
+        f = bt2.FloatValue(raw)
+        self.assertEqual(f, float(raw))
+
+    def test_create_from_vint(self):
+        raw = 17
+        f = bt2.FloatValue(bt2.create_value(raw))
+        self.assertEqual(f, float(raw))
+
+    def test_create_from_vfloat(self):
+        raw = 17.17
+        f = bt2.FloatValue(bt2.create_value(raw))
+        self.assertEqual(f, raw)
+
+    def test_create_from_unknown(self):
+        class A:
+            pass
+
+        with self._assert_expecting_float():
+            f = bt2.FloatValue(A())
+
+    def test_create_from_varray(self):
+        with self._assert_expecting_float():
+            f = bt2.FloatValue(bt2.ArrayValue())
+
+    def test_assign_true(self):
+        self._def.value = True
+        self.assertTrue(self._def)
+
+    def test_assign_false(self):
+        self._def.value = False
+        self.assertFalse(self._def)
+
+    def test_assign_pos_int(self):
+        raw = 477
+        self._def.value = raw
+        self.assertEqual(self._def, float(raw))
+
+    def test_assign_neg_int(self):
+        raw = -13
+        self._def.value = raw
+        self.assertEqual(self._def, float(raw))
+
+    def test_assign_vint(self):
+        raw = 999
+        self._def.value = bt2.create_value(raw)
+        self.assertEqual(self._def, float(raw))
+
+    def test_assign_float(self):
+        raw = -19.23
+        self._def.value = raw
+        self.assertEqual(self._def, raw)
+
+    def test_assign_vfloat(self):
+        raw = 101.32
+        self._def.value = bt2.create_value(raw)
+        self.assertEqual(self._def, raw)
+
+    def test_invalid_lshift(self):
+        self._test_invalid_op(lambda: self._def << 23)
+
+    def test_invalid_rshift(self):
+        self._test_invalid_op(lambda: self._def >> 23)
+
+    def test_invalid_and(self):
+        self._test_invalid_op(lambda: self._def & 23)
+
+    def test_invalid_or(self):
+        self._test_invalid_op(lambda: self._def | 23)
+
+    def test_invalid_xor(self):
+        self._test_invalid_op(lambda: self._def ^ 23)
+
+    def test_invalid_invert(self):
+        self._test_invalid_op(lambda: ~self._def)
+
+
+_inject_numeric_testing_methods(FloatValueTestCase)
+
+
+@unittest.skip("this is broken")
+class StringValueTestCase(_TestCopySimple, _TestFrozenSimple, unittest.TestCase):
+    def setUp(self):
+        self._def_value = 'Hello, World!'
+        self._def = bt2.StringValue(self._def_value)
+        self._def_new_value = 'Yes!'
+
+    def tearDown(self):
+        del self._def
+
+    def _assert_expecting_str(self):
+        return self.assertRaises(TypeError)
+
+    def test_create_default(self):
+        s = bt2.StringValue()
+        self.assertEqual(s, '')
+
+    def test_create_from_str(self):
+        raw = 'liberté'
+        s = bt2.StringValue(raw)
+        self.assertEqual(s, raw)
+
+    def test_create_from_vstr(self):
+        raw = 'liberté'
+        s = bt2.StringValue(bt2.create_value(raw))
+        self.assertEqual(s, raw)
+
+    def test_create_from_unknown(self):
+        class A:
+            pass
+
+        with self._assert_expecting_str():
+            i = bt2.StringValue(A())
+
+    def test_create_from_varray(self):
+        with self._assert_expecting_str():
+            i = bt2.StringValue(bt2.ArrayValue())
+
+    def test_assign_int(self):
+        with self._assert_expecting_str():
+            self._def.value = 283
+
+    def test_assign_str(self):
+        raw = 'zorg'
+        self._def = raw
+        self.assertEqual(self._def, raw)
+
+    def test_assign_vstr(self):
+        raw = 'zorg'
+        self._def = bt2.create_value(raw)
+        self.assertEqual(self._def, raw)
+
+    def test_eq(self):
+        self.assertEqual(self._def, self._def_value)
+
+    def test_eq(self):
+        self.assertNotEqual(self._def, 23)
+
+    def test_lt_vstring(self):
+        s1 = bt2.StringValue('allo')
+        s2 = bt2.StringValue('bateau')
+        self.assertLess(s1, s2)
+
+    def test_lt_string(self):
+        s1 = bt2.StringValue('allo')
+        self.assertLess(s1, 'bateau')
+
+    def test_le_vstring(self):
+        s1 = bt2.StringValue('allo')
+        s2 = bt2.StringValue('bateau')
+        self.assertLessEqual(s1, s2)
+
+    def test_le_string(self):
+        s1 = bt2.StringValue('allo')
+        self.assertLessEqual(s1, 'bateau')
+
+    def test_gt_vstring(self):
+        s1 = bt2.StringValue('allo')
+        s2 = bt2.StringValue('bateau')
+        self.assertGreater(s2, s1)
+
+    def test_gt_string(self):
+        s1 = bt2.StringValue('allo')
+        self.assertGreater('bateau', s1)
+
+    def test_ge_vstring(self):
+        s1 = bt2.StringValue('allo')
+        s2 = bt2.StringValue('bateau')
+        self.assertGreaterEqual(s2, s1)
+
+    def test_ge_string(self):
+        s1 = bt2.StringValue('allo')
+        self.assertGreaterEqual('bateau', s1)
+
+    def test_bool_op(self):
+        self.assertEqual(bool(self._def), bool(self._def_value))
+
+    def test_str_op(self):
+        self.assertEqual(str(self._def), str(self._def_value))
+
+    def test_len(self):
+        self.assertEqual(len(self._def), len(self._def_value))
+
+    def test_getitem(self):
+        self.assertEqual(self._def[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_append_vstr(self):
+        to_append = 'meow meow meow'
+        self._def += bt2.create_value(to_append)
+        self._def_value += to_append
+        self.assertEqual(self._def, self._def_value)
+
+
+@unittest.skip("this is broken")
+class ArrayValueTestCase(_TestFrozen, unittest.TestCase):
+    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))
+
+    def tearDown(self):
+        del self._def
+
+    def _modify_def(self):
+        self._def[2] = 'xyz'
+
+    def _assert_type_error(self):
+        return self.assertRaises(TypeError)
+
+    def test_create_default(self):
+        a = bt2.ArrayValue()
+        self.assertEqual(len(a), 0)
+
+    def test_create_from_array(self):
+        self.assertEqual(self._def, self._def_value)
+
+    def test_create_from_tuple(self):
+        t = 1, 2, False, None
+        a = bt2.ArrayValue(t)
+        self.assertEqual(a, t)
+
+    def test_create_from_varray(self):
+        va = bt2.ArrayValue(copy.deepcopy(self._def_value))
+        a = bt2.ArrayValue(va)
+        self.assertEqual(va, a)
+
+    def test_create_from_unknown(self):
+        class A:
+            pass
+
+        with self._assert_type_error():
+            a = bt2.ArrayValue(A())
+
+    def test_bool_op_true(self):
+        self.assertTrue(bool(self._def))
+
+    def test_bool_op_false(self):
+        self.assertFalse(bool(bt2.ArrayValue()))
+
+    def test_len(self):
+        self.assertEqual(len(self._def), len(self._def_value))
+
+    def test_copy(self):
+        to_copy = (1, 2, 'hello', (4, 5.2))
+        a = bt2.ArrayValue(to_copy)
+        cpy = copy.copy(a)
+        self.assertEqual(a, cpy)
+        self.assertNotEqual(a.addr, cpy.addr)
+        self.assertEqual(a[3].addr, cpy[3].addr)
+
+    def test_deepcopy(self):
+        to_copy = (1, 2, 'hello', (4, 5.2))
+        a = bt2.ArrayValue(to_copy)
+        cpy = copy.deepcopy(a)
+        self.assertEqual(a, cpy)
+        self.assertNotEqual(a.addr, cpy.addr)
+        self.assertNotEqual(a[3].addr, cpy[3].addr)
+
+    def test_eq_int(self):
+        self.assertNotEqual(self._def, 23)
+
+    def test_eq_diff_len(self):
+        a1 = bt2.create_value([1, 2, 3])
+        a2 = bt2.create_value([1, 2])
+        self.assertNotEqual(a1, a2)
+
+    def test_eq_diff_content_same_len(self):
+        a1 = bt2.create_value([1, 2, 3])
+        a2 = bt2.create_value([4, 5, 6])
+        self.assertNotEqual(a1, a2)
+
+    def test_eq_same_content_same_len(self):
+        raw = (3, True, [1, 2.5, None, {'a': 17.6, 'b': None}])
+        a1 = bt2.ArrayValue(raw)
+        a2 = bt2.ArrayValue(copy.deepcopy(raw))
+        self.assertEqual(a1, a2)
+
+    def test_setitem_int(self):
+        raw = 19
+        self._def[2] = raw
+        self.assertEqual(self._def[2], raw)
+
+    def test_setitem_vint(self):
+        raw = 19
+        self._def[2] = bt2.create_value(raw)
+        self.assertEqual(self._def[2], raw)
+
+    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
+
+    def test_setitem_index_neg(self):
+        with self.assertRaises(IndexError):
+            self._def[-2] = 23
+
+    def test_setitem_index_out_of_range(self):
+        with self.assertRaises(IndexError):
+            self._def[len(self._def)] = 23
+
+    def test_append_none(self):
+        self._def.append(None)
+        self.assertIsNone(self._def[len(self._def) - 1])
+
+    def test_append_int(self):
+        raw = 145
+        self._def.append(raw)
+        self.assertEqual(self._def[len(self._def) - 1], raw)
+
+    def test_append_vint(self):
+        raw = 145
+        self._def.append(bt2.create_value(raw))
+        self.assertEqual(self._def[len(self._def) - 1], raw)
+
+    def test_append_unknown(self):
+        class A:
+            pass
+
+        with self._assert_type_error():
+            self._def.append(A())
+
+    def test_iadd(self):
+        raw = 4, 5, True
+        self._def += raw
+        self.assertEqual(self._def[len(self._def) - 3], raw[0])
+        self.assertEqual(self._def[len(self._def) - 2], raw[1])
+        self.assertEqual(self._def[len(self._def) - 1], raw[2])
+
+    def test_iadd_unknown(self):
+        class A:
+            pass
+
+        with self._assert_type_error():
+            self._def += A()
+
+    def test_iadd_list_unknown(self):
+        class A:
+            pass
+
+        with self._assert_type_error():
+            self._def += [A()]
+
+    def test_iter(self):
+        for velem, elem in zip(self._def, self._def_value):
+            self.assertEqual(velem, elem)
+
+
+@unittest.skip("this is broken")
+class MapValueTestCase(_TestFrozen, unittest.TestCase):
+    def setUp(self):
+        self._def_value = {
+            'none': None,
+            'false': False,
+            'true': True,
+            'neg-int': -23,
+            'zero': 0,
+            'pos-int': 42,
+            'neg-float': -42.4,
+            'pos-float': 23.17,
+            'str': 'yes'
+        }
+        self._def = bt2.MapValue(copy.deepcopy(self._def_value))
+
+    def tearDown(self):
+        del self._def
+
+    def _modify_def(self):
+        self._def['zero'] = 1
+
+    def test_create_default(self):
+        m = bt2.MapValue()
+        self.assertEqual(len(m), 0)
+
+    def test_create_from_dict(self):
+        self.assertEqual(self._def, self._def_value)
+
+    def test_create_from_vmap(self):
+        vm = bt2.MapValue(copy.deepcopy(self._def_value))
+        m = bt2.MapValue(vm)
+        self.assertEqual(vm, m)
+
+    def test_create_from_unknown(self):
+        class A:
+            pass
+
+        with self.assertRaises(AttributeError):
+            m = bt2.MapValue(A())
+
+    def test_bool_op_true(self):
+        self.assertTrue(bool(self._def))
+
+    def test_bool_op_false(self):
+        self.assertFalse(bool(bt2.MapValue()))
+
+    def test_len(self):
+        self.assertEqual(len(self._def), len(self._def_value))
+
+    def test_copy(self):
+        to_copy = {
+            'yes': 1,
+            'no': 2,
+            's': 'hello',
+            'inner': (4, 5.2)
+        }
+        m = bt2.MapValue(to_copy)
+        cpy = copy.copy(m)
+        self.assertEqual(m, cpy)
+        self.assertNotEqual(m.addr, cpy.addr)
+        self.assertEqual(m['inner'].addr, cpy['inner'].addr)
+
+    def test_deepcopy(self):
+        to_copy = {
+            'yes': 1,
+            'no': 2,
+            's': 'hello',
+            'inner': (4, 5.2)
+        }
+        m = bt2.MapValue(to_copy)
+        cpy = copy.deepcopy(m)
+        self.assertEqual(m, cpy)
+        self.assertNotEqual(m.addr, cpy.addr)
+        self.assertNotEqual(m['inner'].addr, cpy['inner'].addr)
+
+    def test_eq_int(self):
+        self.assertNotEqual(self._def, 23)
+
+    def test_eq_diff_len(self):
+        a1 = bt2.create_value({'a': 1, 'b': 2, 'c': 3})
+        a2 = bt2.create_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_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_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)
+        a2 = bt2.MapValue(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_setitem_vint(self):
+        raw = 19
+        self._def['pos-int'] = bt2.create_value(raw)
+        self.assertEqual(self._def['pos-int'], raw)
+
+    def test_setitem_none(self):
+        self._def['none'] = None
+        self.assertIsNone(self._def['none'])
+
+    def test_setitem_new_int(self):
+        old_len = len(self._def)
+        self._def['new-int'] = 23
+        self.assertEqual(self._def['new-int'], 23)
+        self.assertEqual(len(self._def), old_len + 1)
+
+    def test_setitem_index_wrong_type(self):
+        with self.assertRaises(TypeError):
+            self._def[18] = 23
+
+    def test_iter(self):
+        for vkey, vval in self._def.items():
+            val = self._def_value[vkey]
+            self.assertEqual(vval, val)
+
+    def test_getitem_wrong_key(self):
+        with self.assertRaises(KeyError):
+            self._def['kilojoule']
diff --git a/tests/bindings/python/bt2/test_values.py b/tests/bindings/python/bt2/test_values.py
deleted file mode 100644 (file)
index 2b15d10..0000000
+++ /dev/null
@@ -1,1567 +0,0 @@
-from functools import partial, partialmethod
-import operator
-import unittest
-import numbers
-import math
-import copy
-import bt2
-
-
-class _TestFrozen:
-    def test_is_frozen(self):
-        self._def.freeze()
-        self.assertTrue(self._def.is_frozen)
-
-    def test_frozen(self):
-        self._def.freeze()
-        self.assertTrue(self._def.frozen)
-
-    def test_frozen_exc(self):
-        self._def.freeze()
-
-        with self.assertRaisesRegex(bt2.Frozen, r'.* value object is frozen$') as cm:
-            self._modify_def()
-
-        self.assertEqual(self._def, self._def_value)
-
-    def test_get_value_when_frozen(self):
-        self._def.freeze()
-        self.assertEqual(self._def, self._def_value)
-
-
-class _TestFrozenSimple(_TestFrozen):
-    def _modify_def(self):
-        self._def.value = self._def_new_value
-
-
-class _TestCopySimple:
-    def test_copy(self):
-        cpy = copy.copy(self._def)
-        self.assertIsNot(cpy, self._def)
-        self.assertNotEqual(cpy.addr, self._def.addr)
-        self.assertEqual(cpy, self._def)
-
-    def test_deepcopy(self):
-        cpy = copy.deepcopy(self._def)
-        self.assertIsNot(cpy, self._def)
-        self.assertNotEqual(cpy.addr, self._def.addr)
-        self.assertEqual(cpy, self._def)
-
-
-_COMP_BINOPS = (
-    operator.eq,
-    operator.ne,
-)
-
-
-class _TestNumericValue(_TestFrozenSimple, _TestCopySimple):
-    def _binop(self, op, rhs):
-        rexc = None
-        rvexc = None
-        comp_value = rhs
-
-        try:
-            r = op(self._def, rhs)
-        except Exception as e:
-            rexc = e
-
-        try:
-            rv = op(self._def_value, comp_value)
-        except Exception as e:
-            rvexc = e
-
-        if rexc is not None or rvexc is not None:
-            # at least one of the operations raised an exception: in
-            # this case both operations should have raised the same
-            # type of exception (division by zero, bit shift with a
-            # floating point number operand, etc.)
-            self.assertIs(type(rexc), type(rvexc))
-            return None, None
-
-        return r, rv
-
-    def _unaryop(self, op):
-        rexc = None
-        rvexc = None
-
-        try:
-            r = op(self._def)
-        except Exception as e:
-            rexc = e
-
-        try:
-            rv = op(self._def_value)
-        except Exception as e:
-            rvexc = e
-
-        if rexc is not None or rvexc is not None:
-            # at least one of the operations raised an exception: in
-            # this case both operations should have raised the same
-            # type of exception (division by zero, bit shift with a
-            # floating point number operand, etc.)
-            self.assertIs(type(rexc), type(rvexc))
-            return None, None
-
-        return r, rv
-
-    def _test_unaryop_type(self, op):
-        r, rv = self._unaryop(op)
-
-        if r is None:
-            return
-
-        self.assertIsInstance(r, type(rv))
-
-    def _test_unaryop_value(self, op):
-        r, rv = self._unaryop(op)
-
-        if r is None:
-            return
-
-        self.assertEqual(r, rv)
-
-    def _test_unaryop_addr_same(self, op):
-        addr_before = self._def.addr
-        self._unaryop(op)
-        self.assertEqual(self._def.addr, addr_before)
-
-    def _test_unaryop_value_same(self, op):
-        value_before = copy.copy(self._def)
-        self._unaryop(op)
-        self.assertEqual(self._def, value_before)
-
-    def _test_binop_type(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        if op in _COMP_BINOPS:
-            # __eq__() and __ne__() always return a 'bool' object
-            self.assertIsInstance(r, bool)
-        else:
-            self.assertIsInstance(r, type(rv))
-
-    def _test_binop_value(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        self.assertEqual(r, rv)
-
-    def _test_binop_lhs_addr_same(self, op, rhs):
-        addr_before = self._def.addr
-        r, rv = self._binop(op, rhs)
-        self.assertEqual(self._def.addr, addr_before)
-
-    def _test_binop_lhs_value_same(self, op, rhs):
-        value_before = copy.copy(self._def)
-        r, rv = self._binop(op, rhs)
-        self.assertEqual(self._def, value_before)
-
-    def _test_binop_invalid_unknown(self, op):
-        if op in _COMP_BINOPS:
-            self.skipTest('not testing')
-
-        class A:
-            pass
-
-        with self.assertRaises(TypeError):
-            op(self._def, A())
-
-    def _test_binop_invalid_none(self, op):
-        if op in _COMP_BINOPS:
-            self.skipTest('not testing')
-
-        with self.assertRaises(TypeError):
-            op(self._def, None)
-
-    def _test_ibinop_value(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        # The inplace operators are special for value objects because
-        # they do not return a new, immutable object like it's the case
-        # for Python numbers. In Python, `a += 2`, where `a` is a number
-        # object, assigns a new number object reference to `a`, dropping
-        # the old reference. Since BT's value objects are mutable, we
-        # modify their internal value with the inplace operators. This
-        # means however that we can lose data in the process, for
-        # example:
-        #
-        #     int_value_obj += 3.3
-        #
-        # Here, if `int_value_obj` is a Python `int` with the value 2,
-        # it would be a `float` object after this, holding the value
-        # 5.3. In our case, if `int_value_obj` is an integer value
-        # object, 3.3 is converted to an `int` object (3) and added to
-        # the current value of `int_value_obj`, so after this the value
-        # of the object is 5. This does not compare to 5.3, which is
-        # why we also use the `int()` type here.
-        if type(self._def) is bt2.IntegerValue:
-            rv = int(rv)
-
-        self.assertEqual(r, rv)
-
-    def _test_ibinop_type(self, op, rhs):
-        r, rv = self._binop(op, rhs)
-
-        if r is None:
-            return
-
-        self.assertIs(r, self._def)
-
-    def _test_ibinop_invalid_unknown(self, op):
-        class A:
-            pass
-
-        with self.assertRaises(TypeError):
-            op(self._def, A())
-
-    def _test_ibinop_invalid_none(self, op):
-        with self.assertRaises(TypeError):
-            op(self._def, None)
-
-    def _test_binop_rhs_false(self, test_cb, op):
-        test_cb(op, False)
-
-    def _test_binop_rhs_true(self, test_cb, op):
-        test_cb(op, True)
-
-    def _test_binop_rhs_pos_int(self, test_cb, op):
-        test_cb(op, 2)
-
-    def _test_binop_rhs_neg_int(self, test_cb, op):
-        test_cb(op, -23)
-
-    def _test_binop_rhs_zero_int(self, test_cb, op):
-        test_cb(op, 0)
-
-    def _test_binop_rhs_pos_vint(self, test_cb, op):
-        test_cb(op, bt2.create_value(2))
-
-    def _test_binop_rhs_neg_vint(self, test_cb, op):
-        test_cb(op, bt2.create_value(-23))
-
-    def _test_binop_rhs_zero_vint(self, test_cb, op):
-        test_cb(op, bt2.create_value(0))
-
-    def _test_binop_rhs_pos_float(self, test_cb, op):
-        test_cb(op, 2.2)
-
-    def _test_binop_rhs_neg_float(self, test_cb, op):
-        test_cb(op, -23.4)
-
-    def _test_binop_rhs_zero_float(self, test_cb, op):
-        test_cb(op, 0.0)
-
-    def _test_binop_rhs_pos_vfloat(self, test_cb, op):
-        test_cb(op, bt2.create_value(2.2))
-
-    def _test_binop_rhs_neg_vfloat(self, test_cb, op):
-        test_cb(op, bt2.create_value(-23.4))
-
-    def _test_binop_rhs_zero_vfloat(self, test_cb, op):
-        test_cb(op, bt2.create_value(0.0))
-
-    def _test_binop_type_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_type, op)
-
-    def _test_binop_type_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_type, op)
-
-    def _test_binop_type_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_type, op)
-
-    def _test_binop_type_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_type, op)
-
-    def _test_binop_type_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_type, op)
-
-    def _test_binop_type_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_type, op)
-
-    def _test_binop_type_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_type, op)
-
-    def _test_binop_type_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_type, op)
-
-    def _test_binop_type_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_type, op)
-
-    def _test_binop_type_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_type, op)
-
-    def _test_binop_type_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_type, op)
-
-    def _test_binop_type_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_type, op)
-
-    def _test_binop_type_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_type, op)
-
-    def _test_binop_type_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_type, op)
-
-    def _test_binop_value_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_value, op)
-
-    def _test_binop_value_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_value, op)
-
-    def _test_binop_value_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_value, op)
-
-    def _test_binop_value_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_value, op)
-
-    def _test_binop_value_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_value, op)
-
-    def _test_binop_value_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_value, op)
-
-    def _test_binop_value_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_value, op)
-
-    def _test_binop_value_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_value, op)
-
-    def _test_binop_value_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_value, op)
-
-    def _test_binop_value_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_value, op)
-
-    def _test_binop_value_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_value, op)
-
-    def _test_binop_value_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_value, op)
-
-    def _test_binop_value_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_value, op)
-
-    def _test_binop_value_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_value, op)
-
-    def _test_binop_lhs_addr_same_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_addr_same_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_addr_same, op)
-
-    def _test_binop_lhs_value_same_false(self, op):
-        self._test_binop_rhs_false(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_true(self, op):
-        self._test_binop_rhs_true(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_binop_lhs_value_same, op)
-
-    def _test_binop_lhs_value_same_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_binop_lhs_value_same, op)
-
-    def _test_ibinop_type_false(self, op):
-        self._test_binop_rhs_false(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_true(self, op):
-        self._test_binop_rhs_true(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_ibinop_type, op)
-
-    def _test_ibinop_type_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_ibinop_type, op)
-
-    def _test_ibinop_value_false(self, op):
-        self._test_binop_rhs_false(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_true(self, op):
-        self._test_binop_rhs_true(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_int(self, op):
-        self._test_binop_rhs_pos_int(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_int(self, op):
-        self._test_binop_rhs_neg_int(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_int(self, op):
-        self._test_binop_rhs_zero_int(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_vint(self, op):
-        self._test_binop_rhs_pos_vint(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_vint(self, op):
-        self._test_binop_rhs_neg_vint(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_vint(self, op):
-        self._test_binop_rhs_zero_vint(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_float(self, op):
-        self._test_binop_rhs_pos_float(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_float(self, op):
-        self._test_binop_rhs_neg_float(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_float(self, op):
-        self._test_binop_rhs_zero_float(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_pos_vfloat(self, op):
-        self._test_binop_rhs_pos_vfloat(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_neg_vfloat(self, op):
-        self._test_binop_rhs_neg_vfloat(self._test_ibinop_value, op)
-
-    def _test_ibinop_value_zero_vfloat(self, op):
-        self._test_binop_rhs_zero_vfloat(self._test_ibinop_value, op)
-
-    def test_bool_op(self):
-        self.assertEqual(bool(self._def), bool(self._def_value))
-
-    def test_int_op(self):
-        self.assertEqual(int(self._def), int(self._def_value))
-
-    def test_float_op(self):
-        self.assertEqual(float(self._def), float(self._def_value))
-
-    def test_complex_op(self):
-        self.assertEqual(complex(self._def), complex(self._def_value))
-
-    def test_str_op(self):
-        self.assertEqual(str(self._def), str(self._def_value))
-
-    def test_eq_none(self):
-        self.assertFalse(self._def == None)
-
-    def test_ne_none(self):
-        self.assertTrue(self._def != None)
-
-
-_BINOPS = (
-    ('lt', operator.lt),
-    ('le', operator.le),
-    ('eq', operator.eq),
-    ('ne', operator.ne),
-    ('ge', operator.ge),
-    ('gt', operator.gt),
-    ('add', operator.add),
-    ('radd', lambda a, b: operator.add(b, a)),
-    ('and', operator.and_),
-    ('rand', lambda a, b: operator.and_(b, a)),
-    ('floordiv', operator.floordiv),
-    ('rfloordiv', lambda a, b: operator.floordiv(b, a)),
-    ('lshift', operator.lshift),
-    ('rlshift', lambda a, b: operator.lshift(b, a)),
-    ('mod', operator.mod),
-    ('rmod', lambda a, b: operator.mod(b, a)),
-    ('mul', operator.mul),
-    ('rmul', lambda a, b: operator.mul(b, a)),
-    ('or', operator.or_),
-    ('ror', lambda a, b: operator.or_(b, a)),
-    ('pow', operator.pow),
-    ('rpow', lambda a, b: operator.pow(b, a)),
-    ('rshift', operator.rshift),
-    ('rrshift', lambda a, b: operator.rshift(b, a)),
-    ('sub', operator.sub),
-    ('rsub', lambda a, b: operator.sub(b, a)),
-    ('truediv', operator.truediv),
-    ('rtruediv', lambda a, b: operator.truediv(b, a)),
-    ('xor', operator.xor),
-    ('rxor', lambda a, b: operator.xor(b, a)),
-)
-
-
-_IBINOPS = (
-    ('iadd', operator.iadd),
-    ('iand', operator.iand),
-    ('ifloordiv', operator.ifloordiv),
-    ('ilshift', operator.ilshift),
-    ('imod', operator.imod),
-    ('imul', operator.imul),
-    ('ior', operator.ior),
-    ('ipow', operator.ipow),
-    ('irshift', operator.irshift),
-    ('isub', operator.isub),
-    ('itruediv', operator.itruediv),
-    ('ixor', operator.ixor),
-)
-
-
-_UNARYOPS = (
-    ('neg', operator.neg),
-    ('pos', operator.pos),
-    ('abs', operator.abs),
-    ('invert', operator.invert),
-    ('round', round),
-    ('round_0', partial(round, ndigits=0)),
-    ('round_1', partial(round, ndigits=1)),
-    ('round_2', partial(round, ndigits=2)),
-    ('round_3', partial(round, ndigits=3)),
-    ('ceil', math.ceil),
-    ('floor', math.floor),
-    ('trunc', math.trunc),
-)
-
-
-def _inject_numeric_testing_methods(cls):
-    def test_binop_name(suffix):
-        return 'test_binop_{}_{}'.format(name, suffix)
-
-    def test_ibinop_name(suffix):
-        return 'test_ibinop_{}_{}'.format(name, suffix)
-
-    def test_unaryop_name(suffix):
-        return 'test_unaryop_{}_{}'.format(name, suffix)
-
-    # inject testing methods for each binary operation
-    for name, binop in _BINOPS:
-
-        setattr(cls, test_binop_name('invalid_unknown'), partialmethod(_TestNumericValue._test_binop_invalid_unknown, op=binop))
-        setattr(cls, test_binop_name('invalid_none'), partialmethod(_TestNumericValue._test_binop_invalid_none, op=binop))
-        setattr(cls, test_binop_name('type_true'), partialmethod(_TestNumericValue._test_binop_type_true, op=binop))
-        setattr(cls, test_binop_name('type_pos_int'), partialmethod(_TestNumericValue._test_binop_type_pos_int, op=binop))
-        setattr(cls, test_binop_name('type_pos_vint'), partialmethod(_TestNumericValue._test_binop_type_pos_vint, op=binop))
-        setattr(cls, test_binop_name('value_true'), partialmethod(_TestNumericValue._test_binop_value_true, op=binop))
-        setattr(cls, test_binop_name('value_pos_int'), partialmethod(_TestNumericValue._test_binop_value_pos_int, op=binop))
-        setattr(cls, test_binop_name('value_pos_vint'), partialmethod(_TestNumericValue._test_binop_value_pos_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_true'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_true, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_int'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_int, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_vint'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_true'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_true, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_int'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_int, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_vint'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_vint, op=binop))
-        setattr(cls, test_binop_name('type_neg_int'), partialmethod(_TestNumericValue._test_binop_type_neg_int, op=binop))
-        setattr(cls, test_binop_name('type_neg_vint'), partialmethod(_TestNumericValue._test_binop_type_neg_vint, op=binop))
-        setattr(cls, test_binop_name('value_neg_int'), partialmethod(_TestNumericValue._test_binop_value_neg_int, op=binop))
-        setattr(cls, test_binop_name('value_neg_vint'), partialmethod(_TestNumericValue._test_binop_value_neg_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_int'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_int, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_vint'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_int'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_int, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_vint'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_vint, op=binop))
-        setattr(cls, test_binop_name('type_false'), partialmethod(_TestNumericValue._test_binop_type_false, op=binop))
-        setattr(cls, test_binop_name('type_zero_int'), partialmethod(_TestNumericValue._test_binop_type_zero_int, op=binop))
-        setattr(cls, test_binop_name('type_zero_vint'), partialmethod(_TestNumericValue._test_binop_type_zero_vint, op=binop))
-        setattr(cls, test_binop_name('value_false'), partialmethod(_TestNumericValue._test_binop_value_false, op=binop))
-        setattr(cls, test_binop_name('value_zero_int'), partialmethod(_TestNumericValue._test_binop_value_zero_int, op=binop))
-        setattr(cls, test_binop_name('value_zero_vint'), partialmethod(_TestNumericValue._test_binop_value_zero_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_false'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_false, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_int'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_int, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_vint'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_vint, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_false'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_false, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_int'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_int, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_vint'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_vint, op=binop))
-        setattr(cls, test_binop_name('type_pos_float'), partialmethod(_TestNumericValue._test_binop_type_pos_float, op=binop))
-        setattr(cls, test_binop_name('type_neg_float'), partialmethod(_TestNumericValue._test_binop_type_neg_float, op=binop))
-        setattr(cls, test_binop_name('type_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_type_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('type_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_type_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('value_pos_float'), partialmethod(_TestNumericValue._test_binop_value_pos_float, op=binop))
-        setattr(cls, test_binop_name('value_neg_float'), partialmethod(_TestNumericValue._test_binop_value_neg_float, op=binop))
-        setattr(cls, test_binop_name('value_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_value_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('value_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_value_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_float'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_float, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_float'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_float, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_float'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_float, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_float'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_float, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_pos_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_pos_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_neg_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_neg_vfloat, op=binop))
-        setattr(cls, test_binop_name('type_zero_float'), partialmethod(_TestNumericValue._test_binop_type_zero_float, op=binop))
-        setattr(cls, test_binop_name('type_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_type_zero_vfloat, op=binop))
-        setattr(cls, test_binop_name('value_zero_float'), partialmethod(_TestNumericValue._test_binop_value_zero_float, op=binop))
-        setattr(cls, test_binop_name('value_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_value_zero_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_float'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_float, op=binop))
-        setattr(cls, test_binop_name('lhs_addr_same_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_addr_same_zero_vfloat, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_float'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_float, op=binop))
-        setattr(cls, test_binop_name('lhs_value_same_zero_vfloat'), partialmethod(_TestNumericValue._test_binop_lhs_value_same_zero_vfloat, op=binop))
-
-    # inject testing methods for each unary operation
-    for name, unaryop in _UNARYOPS:
-        setattr(cls, test_unaryop_name('type'), partialmethod(_TestNumericValue._test_unaryop_type, op=unaryop))
-        setattr(cls, test_unaryop_name('value'), partialmethod(_TestNumericValue._test_unaryop_value, op=unaryop))
-        setattr(cls, test_unaryop_name('addr_same'), partialmethod(_TestNumericValue._test_unaryop_addr_same, op=unaryop))
-        setattr(cls, test_unaryop_name('value_same'), partialmethod(_TestNumericValue._test_unaryop_value_same, op=unaryop))
-
-    # inject testing methods for each inplace binary operation
-    for name, ibinop in _IBINOPS:
-        setattr(cls, test_ibinop_name('invalid_unknown'), partialmethod(_TestNumericValue._test_ibinop_invalid_unknown, op=ibinop))
-        setattr(cls, test_ibinop_name('invalid_none'), partialmethod(_TestNumericValue._test_ibinop_invalid_none, op=ibinop))
-        setattr(cls, test_ibinop_name('type_true'), partialmethod(_TestNumericValue._test_ibinop_type_true, op=ibinop))
-        setattr(cls, test_ibinop_name('value_true'), partialmethod(_TestNumericValue._test_ibinop_value_true, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_int'), partialmethod(_TestNumericValue._test_ibinop_type_pos_int, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_vint'), partialmethod(_TestNumericValue._test_ibinop_type_pos_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_int'), partialmethod(_TestNumericValue._test_ibinop_value_pos_int, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_vint'), partialmethod(_TestNumericValue._test_ibinop_value_pos_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_int'), partialmethod(_TestNumericValue._test_ibinop_type_neg_int, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_vint'), partialmethod(_TestNumericValue._test_ibinop_type_neg_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_int'), partialmethod(_TestNumericValue._test_ibinop_value_neg_int, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_vint'), partialmethod(_TestNumericValue._test_ibinop_value_neg_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('type_false'), partialmethod(_TestNumericValue._test_ibinop_type_false, op=ibinop))
-        setattr(cls, test_ibinop_name('value_false'), partialmethod(_TestNumericValue._test_ibinop_value_false, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_int'), partialmethod(_TestNumericValue._test_ibinop_type_zero_int, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_vint'), partialmethod(_TestNumericValue._test_ibinop_type_zero_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_int'), partialmethod(_TestNumericValue._test_ibinop_value_zero_int, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_vint'), partialmethod(_TestNumericValue._test_ibinop_value_zero_vint, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_float'), partialmethod(_TestNumericValue._test_ibinop_type_pos_float, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_float'), partialmethod(_TestNumericValue._test_ibinop_type_neg_float, op=ibinop))
-        setattr(cls, test_ibinop_name('type_pos_vfloat'), partialmethod(_TestNumericValue._test_ibinop_type_pos_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('type_neg_vfloat'), partialmethod(_TestNumericValue._test_ibinop_type_neg_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_float'), partialmethod(_TestNumericValue._test_ibinop_value_pos_float, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_float'), partialmethod(_TestNumericValue._test_ibinop_value_neg_float, op=ibinop))
-        setattr(cls, test_ibinop_name('value_pos_vfloat'), partialmethod(_TestNumericValue._test_ibinop_value_pos_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('value_neg_vfloat'), partialmethod(_TestNumericValue._test_ibinop_value_neg_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_float'), partialmethod(_TestNumericValue._test_ibinop_type_zero_float, op=ibinop))
-        setattr(cls, test_ibinop_name('type_zero_vfloat'), partialmethod(_TestNumericValue._test_ibinop_type_zero_vfloat, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_float'), partialmethod(_TestNumericValue._test_ibinop_value_zero_float, op=ibinop))
-        setattr(cls, test_ibinop_name('value_zero_vfloat'), partialmethod(_TestNumericValue._test_ibinop_value_zero_vfloat, op=ibinop))
-
-
-@unittest.skip("this is broken")
-class CreateValueFuncTestCase(unittest.TestCase):
-    def test_create_none(self):
-        v = bt2.create_value(None)
-        self.assertIsNone(v)
-
-    def test_create_bool_false(self):
-        v = bt2.create_value(False)
-        self.assertIsInstance(v, bt2.BoolValue)
-        self.assertFalse(v)
-
-    def test_create_bool_true(self):
-        v = bt2.create_value(True)
-        self.assertIsInstance(v, bt2.BoolValue)
-        self.assertTrue(v)
-
-    def test_create_int_pos(self):
-        raw = 23
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.IntegerValue)
-        self.assertEqual(v, raw)
-
-    def test_create_int_neg(self):
-        raw = -23
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.IntegerValue)
-        self.assertEqual(v, raw)
-
-    def test_create_float_pos(self):
-        raw = 17.5
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.FloatValue)
-        self.assertEqual(v, raw)
-
-    def test_create_float_neg(self):
-        raw = -17.5
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.FloatValue)
-        self.assertEqual(v, raw)
-
-    def test_create_string(self):
-        raw = 'salut'
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.StringValue)
-        self.assertEqual(v, raw)
-
-    def test_create_string_empty(self):
-        raw = ''
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.StringValue)
-        self.assertEqual(v, raw)
-
-    def test_create_array_from_list(self):
-        raw = [1, 2, 3]
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.ArrayValue)
-        self.assertEqual(v, raw)
-
-    def test_create_array_from_tuple(self):
-        raw = 4, 5, 6
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.ArrayValue)
-        self.assertEqual(v, raw)
-
-    def test_create_array_from_empty_list(self):
-        raw = []
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.ArrayValue)
-        self.assertEqual(v, raw)
-
-    def test_create_array_from_empty_tuple(self):
-        raw = ()
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.ArrayValue)
-        self.assertEqual(v, raw)
-
-    def test_create_map(self):
-        raw = {'salut': 23}
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.MapValue)
-        self.assertEqual(v, raw)
-
-    def test_create_map_empty(self):
-        raw = {}
-        v = bt2.create_value(raw)
-        self.assertIsInstance(v, bt2.MapValue)
-        self.assertEqual(v, raw)
-
-    def test_create_vfalse(self):
-        v = bt2.create_value(bt2.create_value(False))
-        self.assertIsInstance(v, bt2.BoolValue)
-        self.assertFalse(v)
-
-    def test_create_invalid(self):
-        class A:
-            pass
-
-        a = A()
-
-        with self.assertRaisesRegex(TypeError, "cannot create value object from 'A' object") as cm:
-            v = bt2.create_value(a)
-
-
-@unittest.skip("this is broken")
-class BoolValueTestCase(_TestFrozenSimple, _TestCopySimple, unittest.TestCase):
-    def setUp(self):
-        self._f = bt2.BoolValue(False)
-        self._t = bt2.BoolValue(True)
-        self._def = self._f
-        self._def_value = False
-        self._def_new_value = True
-
-    def tearDown(self):
-        del self._f
-        del self._t
-        del self._def
-
-    def _assert_expecting_bool(self):
-        return self.assertRaisesRegex(TypeError, r"expecting a 'bool' object")
-
-    def test_create_default(self):
-        b = bt2.BoolValue()
-        self.assertFalse(b)
-
-    def test_create_false(self):
-        self.assertFalse(self._f)
-
-    def test_create_true(self):
-        self.assertTrue(self._t)
-
-    def test_create_from_vfalse(self):
-        b = bt2.BoolValue(self._f)
-        self.assertFalse(b)
-
-    def test_create_from_vtrue(self):
-        b = bt2.BoolValue(self._t)
-        self.assertTrue(b)
-
-    def test_create_from_int_non_zero(self):
-        with self.assertRaises(TypeError):
-            b = bt2.BoolValue(23)
-
-    def test_create_from_int_zero(self):
-        with self.assertRaises(TypeError):
-            b = bt2.BoolValue(0)
-
-    def test_assign_true(self):
-        b = bt2.BoolValue()
-        b.value = True
-        self.assertTrue(b)
-
-    def test_assign_false(self):
-        b = bt2.BoolValue()
-        b.value = False
-        self.assertFalse(b)
-
-    def test_assign_vtrue(self):
-        b = bt2.BoolValue()
-        b.value = self._t
-        self.assertTrue(b)
-
-    def test_assign_vfalse(self):
-        b = bt2.BoolValue()
-        b.value = False
-        self.assertFalse(b)
-
-    def test_assign_int(self):
-        with self.assertRaises(TypeError):
-            b = bt2.BoolValue()
-            b.value = 23
-
-    def test_bool_op(self):
-        self.assertEqual(bool(self._def), bool(self._def_value))
-
-    def test_str_op(self):
-        self.assertEqual(str(self._def), str(self._def_value))
-
-    def test_eq_none(self):
-        self.assertFalse(self._def == None)
-
-    def test_ne_none(self):
-        self.assertTrue(self._def != None)
-
-    def test_vfalse_eq_false(self):
-        self.assertEqual(self._f, False)
-
-    def test_vfalse_ne_true(self):
-        self.assertNotEqual(self._f, True)
-
-    def test_vtrue_eq_true(self):
-        self.assertEqual(self._t, True)
-
-    def test_vtrue_ne_false(self):
-        self.assertNotEqual(self._t, False)
-
-
-@unittest.skip("this is broken")
-class IntegerValueTestCase(_TestNumericValue, unittest.TestCase):
-    def setUp(self):
-        self._pv = 23
-        self._nv = -52
-        self._ip = bt2.IntegerValue(self._pv)
-        self._in = bt2.IntegerValue(self._nv)
-        self._def = self._ip
-        self._def_value = self._pv
-        self._def_new_value = -101
-
-    def tearDown(self):
-        del self._ip
-        del self._in
-        del self._def
-        del self._def_value
-
-    def _assert_expecting_int(self):
-        return self.assertRaisesRegex(TypeError, r'expecting a number object')
-
-    def _assert_expecting_int64(self):
-        return self.assertRaisesRegex(ValueError, r"expecting a signed 64-bit integral value")
-
-    def _assert_expecting_uint64(self):
-        return self.assertRaisesRegex(ValueError, r"expecting an unsigned 64-bit integral value")
-
-    def test_create_default(self):
-        i = bt2.IntegerValue()
-        self.assertEqual(i, 0)
-
-    def test_create_pos(self):
-        self.assertEqual(self._ip, self._pv)
-
-    def test_create_neg(self):
-        self.assertEqual(self._in, self._nv)
-
-    def test_create_pos_too_big(self):
-        with self._assert_expecting_int64():
-            i = bt2.IntegerValue(2 ** 63)
-
-    def test_create_neg_too_big(self):
-        with self._assert_expecting_int64():
-            i = bt2.IntegerValue(-(2 ** 63) - 1)
-
-    def test_create_from_vint(self):
-        i = bt2.IntegerValue(self._ip)
-        self.assertEqual(i, self._pv)
-
-    def test_create_from_false(self):
-        i = bt2.IntegerValue(False)
-        self.assertFalse(i)
-
-    def test_create_from_true(self):
-        i = bt2.IntegerValue(True)
-        self.assertTrue(i)
-
-    def test_create_from_float(self):
-        i = bt2.IntegerValue(99.6)
-        self.assertEqual(i, 99)
-
-    def test_create_from_vfloat(self):
-        f = bt2.create_value(17.5)
-        i = bt2.IntegerValue(f)
-        self.assertEqual(i, 17)
-
-    def test_create_from_unknown(self):
-        class A:
-            pass
-
-        with self._assert_expecting_int():
-            i = bt2.IntegerValue(A())
-
-    def test_create_from_varray(self):
-        with self._assert_expecting_int():
-            i = bt2.IntegerValue(bt2.ArrayValue())
-
-    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_pos_int(self):
-        raw = 477
-        self._def.value = raw
-        self.assertEqual(self._def, raw)
-
-    def test_assign_neg_int(self):
-        raw = -13
-        self._def.value = raw
-        self.assertEqual(self._def, raw)
-
-    def test_assign_vint(self):
-        raw = 999
-        self._def.value = bt2.create_value(raw)
-        self.assertEqual(self._def, raw)
-
-    def test_assign_vfloat(self):
-        raw = 123.456
-        self._def.value = bt2.create_value(raw)
-        self.assertEqual(self._def, int(raw))
-
-
-_inject_numeric_testing_methods(IntegerValueTestCase)
-
-
-@unittest.skip("this is broken")
-class FloatValueTestCase(_TestNumericValue, unittest.TestCase):
-    def setUp(self):
-        self._pv = 23.4
-        self._nv = -52.7
-        self._fp = bt2.FloatValue(self._pv)
-        self._fn = bt2.FloatValue(self._nv)
-        self._def = self._fp
-        self._def_value = self._pv
-        self._def_new_value = -101.88
-
-    def tearDown(self):
-        del self._fp
-        del self._fn
-        del self._def
-        del self._def_value
-
-    def _assert_expecting_float(self):
-        return self.assertRaisesRegex(TypeError, r"expecting a real number object")
-
-    def _test_invalid_op(self, cb):
-        with self.assertRaises(TypeError):
-            cb()
-
-    def test_create_default(self):
-        f = bt2.FloatValue()
-        self.assertEqual(f, 0.0)
-
-    def test_create_pos(self):
-        self.assertEqual(self._fp, self._pv)
-
-    def test_create_neg(self):
-        self.assertEqual(self._fn, self._nv)
-
-    def test_create_from_vint(self):
-        f = bt2.FloatValue(self._fp)
-        self.assertEqual(f, self._pv)
-
-    def test_create_from_false(self):
-        f = bt2.FloatValue(False)
-        self.assertFalse(f)
-
-    def test_create_from_true(self):
-        f = bt2.FloatValue(True)
-        self.assertTrue(f)
-
-    def test_create_from_int(self):
-        raw = 17
-        f = bt2.FloatValue(raw)
-        self.assertEqual(f, float(raw))
-
-    def test_create_from_vint(self):
-        raw = 17
-        f = bt2.FloatValue(bt2.create_value(raw))
-        self.assertEqual(f, float(raw))
-
-    def test_create_from_vfloat(self):
-        raw = 17.17
-        f = bt2.FloatValue(bt2.create_value(raw))
-        self.assertEqual(f, raw)
-
-    def test_create_from_unknown(self):
-        class A:
-            pass
-
-        with self._assert_expecting_float():
-            f = bt2.FloatValue(A())
-
-    def test_create_from_varray(self):
-        with self._assert_expecting_float():
-            f = bt2.FloatValue(bt2.ArrayValue())
-
-    def test_assign_true(self):
-        self._def.value = True
-        self.assertTrue(self._def)
-
-    def test_assign_false(self):
-        self._def.value = False
-        self.assertFalse(self._def)
-
-    def test_assign_pos_int(self):
-        raw = 477
-        self._def.value = raw
-        self.assertEqual(self._def, float(raw))
-
-    def test_assign_neg_int(self):
-        raw = -13
-        self._def.value = raw
-        self.assertEqual(self._def, float(raw))
-
-    def test_assign_vint(self):
-        raw = 999
-        self._def.value = bt2.create_value(raw)
-        self.assertEqual(self._def, float(raw))
-
-    def test_assign_float(self):
-        raw = -19.23
-        self._def.value = raw
-        self.assertEqual(self._def, raw)
-
-    def test_assign_vfloat(self):
-        raw = 101.32
-        self._def.value = bt2.create_value(raw)
-        self.assertEqual(self._def, raw)
-
-    def test_invalid_lshift(self):
-        self._test_invalid_op(lambda: self._def << 23)
-
-    def test_invalid_rshift(self):
-        self._test_invalid_op(lambda: self._def >> 23)
-
-    def test_invalid_and(self):
-        self._test_invalid_op(lambda: self._def & 23)
-
-    def test_invalid_or(self):
-        self._test_invalid_op(lambda: self._def | 23)
-
-    def test_invalid_xor(self):
-        self._test_invalid_op(lambda: self._def ^ 23)
-
-    def test_invalid_invert(self):
-        self._test_invalid_op(lambda: ~self._def)
-
-
-_inject_numeric_testing_methods(FloatValueTestCase)
-
-
-@unittest.skip("this is broken")
-class StringValueTestCase(_TestCopySimple, _TestFrozenSimple, unittest.TestCase):
-    def setUp(self):
-        self._def_value = 'Hello, World!'
-        self._def = bt2.StringValue(self._def_value)
-        self._def_new_value = 'Yes!'
-
-    def tearDown(self):
-        del self._def
-
-    def _assert_expecting_str(self):
-        return self.assertRaises(TypeError)
-
-    def test_create_default(self):
-        s = bt2.StringValue()
-        self.assertEqual(s, '')
-
-    def test_create_from_str(self):
-        raw = 'liberté'
-        s = bt2.StringValue(raw)
-        self.assertEqual(s, raw)
-
-    def test_create_from_vstr(self):
-        raw = 'liberté'
-        s = bt2.StringValue(bt2.create_value(raw))
-        self.assertEqual(s, raw)
-
-    def test_create_from_unknown(self):
-        class A:
-            pass
-
-        with self._assert_expecting_str():
-            i = bt2.StringValue(A())
-
-    def test_create_from_varray(self):
-        with self._assert_expecting_str():
-            i = bt2.StringValue(bt2.ArrayValue())
-
-    def test_assign_int(self):
-        with self._assert_expecting_str():
-            self._def.value = 283
-
-    def test_assign_str(self):
-        raw = 'zorg'
-        self._def = raw
-        self.assertEqual(self._def, raw)
-
-    def test_assign_vstr(self):
-        raw = 'zorg'
-        self._def = bt2.create_value(raw)
-        self.assertEqual(self._def, raw)
-
-    def test_eq(self):
-        self.assertEqual(self._def, self._def_value)
-
-    def test_eq(self):
-        self.assertNotEqual(self._def, 23)
-
-    def test_lt_vstring(self):
-        s1 = bt2.StringValue('allo')
-        s2 = bt2.StringValue('bateau')
-        self.assertLess(s1, s2)
-
-    def test_lt_string(self):
-        s1 = bt2.StringValue('allo')
-        self.assertLess(s1, 'bateau')
-
-    def test_le_vstring(self):
-        s1 = bt2.StringValue('allo')
-        s2 = bt2.StringValue('bateau')
-        self.assertLessEqual(s1, s2)
-
-    def test_le_string(self):
-        s1 = bt2.StringValue('allo')
-        self.assertLessEqual(s1, 'bateau')
-
-    def test_gt_vstring(self):
-        s1 = bt2.StringValue('allo')
-        s2 = bt2.StringValue('bateau')
-        self.assertGreater(s2, s1)
-
-    def test_gt_string(self):
-        s1 = bt2.StringValue('allo')
-        self.assertGreater('bateau', s1)
-
-    def test_ge_vstring(self):
-        s1 = bt2.StringValue('allo')
-        s2 = bt2.StringValue('bateau')
-        self.assertGreaterEqual(s2, s1)
-
-    def test_ge_string(self):
-        s1 = bt2.StringValue('allo')
-        self.assertGreaterEqual('bateau', s1)
-
-    def test_bool_op(self):
-        self.assertEqual(bool(self._def), bool(self._def_value))
-
-    def test_str_op(self):
-        self.assertEqual(str(self._def), str(self._def_value))
-
-    def test_len(self):
-        self.assertEqual(len(self._def), len(self._def_value))
-
-    def test_getitem(self):
-        self.assertEqual(self._def[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_append_vstr(self):
-        to_append = 'meow meow meow'
-        self._def += bt2.create_value(to_append)
-        self._def_value += to_append
-        self.assertEqual(self._def, self._def_value)
-
-
-@unittest.skip("this is broken")
-class ArrayValueTestCase(_TestFrozen, unittest.TestCase):
-    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))
-
-    def tearDown(self):
-        del self._def
-
-    def _modify_def(self):
-        self._def[2] = 'xyz'
-
-    def _assert_type_error(self):
-        return self.assertRaises(TypeError)
-
-    def test_create_default(self):
-        a = bt2.ArrayValue()
-        self.assertEqual(len(a), 0)
-
-    def test_create_from_array(self):
-        self.assertEqual(self._def, self._def_value)
-
-    def test_create_from_tuple(self):
-        t = 1, 2, False, None
-        a = bt2.ArrayValue(t)
-        self.assertEqual(a, t)
-
-    def test_create_from_varray(self):
-        va = bt2.ArrayValue(copy.deepcopy(self._def_value))
-        a = bt2.ArrayValue(va)
-        self.assertEqual(va, a)
-
-    def test_create_from_unknown(self):
-        class A:
-            pass
-
-        with self._assert_type_error():
-            a = bt2.ArrayValue(A())
-
-    def test_bool_op_true(self):
-        self.assertTrue(bool(self._def))
-
-    def test_bool_op_false(self):
-        self.assertFalse(bool(bt2.ArrayValue()))
-
-    def test_len(self):
-        self.assertEqual(len(self._def), len(self._def_value))
-
-    def test_copy(self):
-        to_copy = (1, 2, 'hello', (4, 5.2))
-        a = bt2.ArrayValue(to_copy)
-        cpy = copy.copy(a)
-        self.assertEqual(a, cpy)
-        self.assertNotEqual(a.addr, cpy.addr)
-        self.assertEqual(a[3].addr, cpy[3].addr)
-
-    def test_deepcopy(self):
-        to_copy = (1, 2, 'hello', (4, 5.2))
-        a = bt2.ArrayValue(to_copy)
-        cpy = copy.deepcopy(a)
-        self.assertEqual(a, cpy)
-        self.assertNotEqual(a.addr, cpy.addr)
-        self.assertNotEqual(a[3].addr, cpy[3].addr)
-
-    def test_eq_int(self):
-        self.assertNotEqual(self._def, 23)
-
-    def test_eq_diff_len(self):
-        a1 = bt2.create_value([1, 2, 3])
-        a2 = bt2.create_value([1, 2])
-        self.assertNotEqual(a1, a2)
-
-    def test_eq_diff_content_same_len(self):
-        a1 = bt2.create_value([1, 2, 3])
-        a2 = bt2.create_value([4, 5, 6])
-        self.assertNotEqual(a1, a2)
-
-    def test_eq_same_content_same_len(self):
-        raw = (3, True, [1, 2.5, None, {'a': 17.6, 'b': None}])
-        a1 = bt2.ArrayValue(raw)
-        a2 = bt2.ArrayValue(copy.deepcopy(raw))
-        self.assertEqual(a1, a2)
-
-    def test_setitem_int(self):
-        raw = 19
-        self._def[2] = raw
-        self.assertEqual(self._def[2], raw)
-
-    def test_setitem_vint(self):
-        raw = 19
-        self._def[2] = bt2.create_value(raw)
-        self.assertEqual(self._def[2], raw)
-
-    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
-
-    def test_setitem_index_neg(self):
-        with self.assertRaises(IndexError):
-            self._def[-2] = 23
-
-    def test_setitem_index_out_of_range(self):
-        with self.assertRaises(IndexError):
-            self._def[len(self._def)] = 23
-
-    def test_append_none(self):
-        self._def.append(None)
-        self.assertIsNone(self._def[len(self._def) - 1])
-
-    def test_append_int(self):
-        raw = 145
-        self._def.append(raw)
-        self.assertEqual(self._def[len(self._def) - 1], raw)
-
-    def test_append_vint(self):
-        raw = 145
-        self._def.append(bt2.create_value(raw))
-        self.assertEqual(self._def[len(self._def) - 1], raw)
-
-    def test_append_unknown(self):
-        class A:
-            pass
-
-        with self._assert_type_error():
-            self._def.append(A())
-
-    def test_iadd(self):
-        raw = 4, 5, True
-        self._def += raw
-        self.assertEqual(self._def[len(self._def) - 3], raw[0])
-        self.assertEqual(self._def[len(self._def) - 2], raw[1])
-        self.assertEqual(self._def[len(self._def) - 1], raw[2])
-
-    def test_iadd_unknown(self):
-        class A:
-            pass
-
-        with self._assert_type_error():
-            self._def += A()
-
-    def test_iadd_list_unknown(self):
-        class A:
-            pass
-
-        with self._assert_type_error():
-            self._def += [A()]
-
-    def test_iter(self):
-        for velem, elem in zip(self._def, self._def_value):
-            self.assertEqual(velem, elem)
-
-
-@unittest.skip("this is broken")
-class MapValueTestCase(_TestFrozen, unittest.TestCase):
-    def setUp(self):
-        self._def_value = {
-            'none': None,
-            'false': False,
-            'true': True,
-            'neg-int': -23,
-            'zero': 0,
-            'pos-int': 42,
-            'neg-float': -42.4,
-            'pos-float': 23.17,
-            'str': 'yes'
-        }
-        self._def = bt2.MapValue(copy.deepcopy(self._def_value))
-
-    def tearDown(self):
-        del self._def
-
-    def _modify_def(self):
-        self._def['zero'] = 1
-
-    def test_create_default(self):
-        m = bt2.MapValue()
-        self.assertEqual(len(m), 0)
-
-    def test_create_from_dict(self):
-        self.assertEqual(self._def, self._def_value)
-
-    def test_create_from_vmap(self):
-        vm = bt2.MapValue(copy.deepcopy(self._def_value))
-        m = bt2.MapValue(vm)
-        self.assertEqual(vm, m)
-
-    def test_create_from_unknown(self):
-        class A:
-            pass
-
-        with self.assertRaises(AttributeError):
-            m = bt2.MapValue(A())
-
-    def test_bool_op_true(self):
-        self.assertTrue(bool(self._def))
-
-    def test_bool_op_false(self):
-        self.assertFalse(bool(bt2.MapValue()))
-
-    def test_len(self):
-        self.assertEqual(len(self._def), len(self._def_value))
-
-    def test_copy(self):
-        to_copy = {
-            'yes': 1,
-            'no': 2,
-            's': 'hello',
-            'inner': (4, 5.2)
-        }
-        m = bt2.MapValue(to_copy)
-        cpy = copy.copy(m)
-        self.assertEqual(m, cpy)
-        self.assertNotEqual(m.addr, cpy.addr)
-        self.assertEqual(m['inner'].addr, cpy['inner'].addr)
-
-    def test_deepcopy(self):
-        to_copy = {
-            'yes': 1,
-            'no': 2,
-            's': 'hello',
-            'inner': (4, 5.2)
-        }
-        m = bt2.MapValue(to_copy)
-        cpy = copy.deepcopy(m)
-        self.assertEqual(m, cpy)
-        self.assertNotEqual(m.addr, cpy.addr)
-        self.assertNotEqual(m['inner'].addr, cpy['inner'].addr)
-
-    def test_eq_int(self):
-        self.assertNotEqual(self._def, 23)
-
-    def test_eq_diff_len(self):
-        a1 = bt2.create_value({'a': 1, 'b': 2, 'c': 3})
-        a2 = bt2.create_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_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_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)
-        a2 = bt2.MapValue(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_setitem_vint(self):
-        raw = 19
-        self._def['pos-int'] = bt2.create_value(raw)
-        self.assertEqual(self._def['pos-int'], raw)
-
-    def test_setitem_none(self):
-        self._def['none'] = None
-        self.assertIsNone(self._def['none'])
-
-    def test_setitem_new_int(self):
-        old_len = len(self._def)
-        self._def['new-int'] = 23
-        self.assertEqual(self._def['new-int'], 23)
-        self.assertEqual(len(self._def), old_len + 1)
-
-    def test_setitem_index_wrong_type(self):
-        with self.assertRaises(TypeError):
-            self._def[18] = 23
-
-    def test_iter(self):
-        for vkey, vval in self._def.items():
-            val = self._def_value[vkey]
-            self.assertEqual(vval, val)
-
-    def test_getitem_wrong_key(self):
-        with self.assertRaises(KeyError):
-            self._def['kilojoule']
This page took 0.117697 seconds and 4 git commands to generate.