Example #1
0
class ObjectMapperMixin(metaclass=ABCMeta):
    def setUp(self):
        self.setUpBarSpec()
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.bar_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Bar', Bar)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.bar_spec)

    @abstractmethod
    def setUpBarSpec(self):
        raise NotImplementedError(
            'Cannot run test unless setUpBarSpec is implemented')

    def test_default_mapping(self):
        attr_map = self.mapper.get_attr_names(self.bar_spec)
        keys = set(attr_map.keys())
        for key in keys:
            with self.subTest(key=key):
                self.assertIs(attr_map[key], self.mapper.get_attr_spec(key))
                self.assertIs(attr_map[key], self.mapper.get_carg_spec(key))
Example #2
0
class TestObjectMapper(with_metaclass(ABCMeta, unittest.TestCase)):
    def setUp(self):
        self.setUpBarSpec()
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.bar_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Bar', Bar)
        self.type_map.register_map(Bar, ObjectMapper)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.bar_spec)

    def setUpBarSpec(self):
        raise unittest.SkipTest('setUpBarSpec not implemented')

    def test_default_mapping(self):
        attr_map = self.mapper.get_attr_names(self.bar_spec)
        keys = set(attr_map.keys())
        for key in keys:
            with self.subTest(key=key):
                self.assertIs(attr_map[key], self.mapper.get_attr_spec(key))
                self.assertIs(attr_map[key], self.mapper.get_carg_spec(key))
Example #3
0
    def test_build_empty_data(self):
        """Test building of a Data object with empty data."""
        baz_inc_spec = DatasetSpec(doc='doc',
                                   data_type_inc='Baz',
                                   quantity=ZERO_OR_MANY)
        baz_holder_spec = GroupSpec(doc='doc',
                                    data_type_def='BazHolder',
                                    datasets=[baz_inc_spec])
        self.spec_catalog.register_spec(baz_holder_spec, 'test.yaml')
        self.type_map.register_container_type(CORE_NAMESPACE, 'BazHolder',
                                              BazHolder)
        self.holder_mapper = ObjectMapper(baz_holder_spec)

        baz = Baz('MyBaz', [], 'abcdefghijklmnopqrstuvwxyz')
        holder = BazHolder('holder', [baz])

        builder = self.holder_mapper.build(holder, self.manager)
        expected = GroupBuilder(
            name='holder',
            datasets=[
                DatasetBuilder(name='MyBaz',
                               data=[],
                               attributes={
                                   'baz_attr': 'abcdefghijklmnopqrstuvwxyz',
                                   'data_type': 'Baz',
                                   'namespace': 'test_core',
                                   'object_id': baz.object_id
                               })
            ])
        self.assertBuilderEqual(builder, expected)
Example #4
0
    def setUp(self):
        self.foo_spec = GroupSpec(
            'A test group specification with data type Foo',
            data_type_def='Foo')
        self.bar_spec = GroupSpec(
            'A test group specification with a data type Bar',
            data_type_def='Bar',
            datasets=[DatasetSpec('an example dataset', 'int', name='data')],
            attributes=[
                AttributeSpec('attr1', 'an example string attribute', 'text'),
                AttributeSpec('attr2', 'an example integer attribute', 'int'),
                AttributeSpec('foo',
                              'a referenced foo',
                              RefSpec('Foo', 'object'),
                              required=False)
            ])

        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.foo_spec, 'test.yaml')
        self.spec_catalog.register_spec(self.bar_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Foo', Foo)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Bar', Bar)
        self.manager = BuildManager(self.type_map)
        self.foo_mapper = ObjectMapper(self.foo_spec)
        self.bar_mapper = ObjectMapper(self.bar_spec)
Example #5
0
class TestObjectMapperBadValue(TestCase):
    def test_bad_value(self):
        """Test that an error is raised if the container attribute value for a spec with a data type is not a container
        or collection of containers.
        """
        class Qux(Container):
            @docval(
                {
                    'name': 'name',
                    'type': str,
                    'doc': 'the name of this Qux'
                }, {
                    'name': 'foo',
                    'type': int,
                    'doc': 'a group'
                })
            def __init__(self, **kwargs):
                name, foo = getargs('name', 'foo', kwargs)
                super().__init__(name=name)
                self.__foo = foo
                if isinstance(foo, Foo):
                    self.__foo.parent = self

            @property
            def foo(self):
                return self.__foo

        self.qux_spec = GroupSpec(
            doc='A test group specification with data type Qux',
            data_type_def='Qux',
            groups=[GroupSpec('an example dataset', data_type_inc='Foo')])
        self.foo_spec = GroupSpec(
            'A test group specification with data type Foo',
            data_type_def='Foo')
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.qux_spec, 'test.yaml')
        self.spec_catalog.register_spec(self.foo_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Qux', Qux)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Foo', Foo)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.qux_spec)

        container = Qux('my_qux', foo=1)
        msg = "Qux 'my_qux' attribute 'foo' has unexpected type."
        with self.assertRaisesWith(ContainerConfigurationError, msg):
            self.mapper.build(container, self.manager)
Example #6
0
 def _test_convert_mismatch_helper(self, spec_type, value_types):
     data = 1
     spec = DatasetSpec('an example dataset', spec_type, name='data')
     for dtype in value_types:
         value = self._get_type(dtype)(data)  # convert data to given dtype
         with self.subTest(dtype=dtype):
             s = np.dtype(self._get_type(spec_type))
             g = np.dtype(self._get_type(dtype))
             msg = "expected %s, received %s - must supply %s" % (s.name, g.name, s.name)
             with self.assertRaisesWith(ValueError, msg):
                 ObjectMapper.convert_dtype(spec, value)
Example #7
0
    def test_ascii_spec(self):
        ascii_spec_types = ['ascii', 'bytes']
        for spec_type in ascii_spec_types:
            with self.subTest(spec_type=spec_type):
                spec = DatasetSpec('an example dataset', spec_type, name='data')

                value = 'a'
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
                self.assertEqual(ret, b'a')
                self.assertIs(type(ret), bytes)
                self.assertEqual(ret_dtype, 'ascii')

                value = b'a'
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
                self.assertEqual(ret, b'a')
                self.assertIs(type(ret), bytes)
                self.assertEqual(ret_dtype, 'ascii')

                value = ['a', 'b']
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
                self.assertListEqual(ret, [b'a', b'b'])
                self.assertIs(type(ret[0]), bytes)
                self.assertEqual(ret_dtype, 'ascii')

                value = np.array(['a', 'b'])
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
                np.testing.assert_array_equal(ret, np.array(['a', 'b'], dtype='S1'))
                self.assertEqual(ret_dtype, 'ascii')

                value = np.array(['a', 'b'], dtype='S1')
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
                np.testing.assert_array_equal(ret, value)
                self.assertEqual(ret_dtype, 'ascii')

                value = []
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
                self.assertListEqual(ret, value)
                self.assertEqual(ret_dtype, 'ascii')

                value = 1
                msg = "Expected unicode or ascii string, got <class 'int'>"
                with self.assertRaisesWith(ValueError, msg):
                    ObjectMapper.convert_dtype(spec, value)

                value = DataChunkIterator(np.array(['a', 'b']))
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)  # no conversion
                self.assertIs(ret, value)
                self.assertEqual(ret_dtype, 'ascii')

                value = DataChunkIterator(np.array(['a', 'b'], dtype='S1'))
                ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)  # no conversion
                self.assertIs(ret, value)
                self.assertEqual(ret_dtype, 'ascii')
Example #8
0
    def test_numeric_spec(self):
        spec_type = 'numeric'
        spec = DatasetSpec('an example dataset', spec_type, name='data')

        value = np.uint64(4)
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret), np.uint64)
        self.assertEqual(ret_dtype, np.uint64)

        value = DataChunkIterator(data=[1, 2, 3])
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(ret.dtype.type, np.dtype(int).type)
        self.assertIs(type(ret.data[0]), int)
        self.assertEqual(ret_dtype, np.dtype(int).type)

        value = ['a', 'b']
        msg = "Cannot convert from <class 'str'> to 'numeric' specification dtype."
        with self.assertRaisesWith(ValueError, msg):
            ObjectMapper.convert_dtype(spec, value)

        value = np.array(['a', 'b'])
        msg = "Cannot convert from <class 'numpy.str_'> to 'numeric' specification dtype."
        with self.assertRaisesWith(ValueError, msg):
            ObjectMapper.convert_dtype(spec, value)

        value = []
        msg = "Cannot infer dtype of empty list or tuple. Please use numpy array with specified dtype."
        with self.assertRaisesWith(ValueError, msg):
            ObjectMapper.convert_dtype(spec, value)
Example #9
0
    def test_dci_input(self):
        spec = DatasetSpec('an example dataset', 'int64', name='data')
        value = DataChunkIterator(np.array([1, 2, 3], dtype=np.int32))
        msg = "Spec 'data': Value with data type int32 is being converted to data type int64 as specified."
        with self.assertWarnsWith(UserWarning, msg):
            ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)  # no conversion
        self.assertIs(ret, value)
        self.assertEqual(ret_dtype, np.int64)

        spec = DatasetSpec('an example dataset', 'int16', name='data')
        value = DataChunkIterator(np.array([1, 2, 3], dtype=np.int32))
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)  # no conversion
        self.assertIs(ret, value)
        self.assertEqual(ret_dtype, np.int32)  # increase precision
Example #10
0
    def test_bool_spec(self):
        spec_type = 'bool'
        spec = DatasetSpec('an example dataset', spec_type, name='data')

        value = np.bool_(True)
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret), np.bool_)
        self.assertEqual(ret_dtype, np.bool_)

        value = True
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret), np.bool_)
        self.assertEqual(ret_dtype, np.bool_)
Example #11
0
 def setUp(self):
     self.bar_spec = GroupSpec(
         'A test group specification with a data type',
         data_type_def='Bar',
         datasets=[
             DatasetSpec('an example dataset',
                         'int',
                         name='data',
                         attributes=[
                             AttributeSpec('attr2',
                                           'an example integer attribute',
                                           'int')
                         ])
         ],
         attributes=[
             AttributeSpec('attr1', 'an example string attribute', 'text')
         ])
     self.spec_catalog = SpecCatalog()
     self.spec_catalog.register_spec(self.bar_spec, 'test.yaml')
     self.namespace = SpecNamespace('a test namespace',
                                    CORE_NAMESPACE, [{
                                        'source': 'test.yaml'
                                    }],
                                    catalog=self.spec_catalog)
     self.namespace_catalog = NamespaceCatalog()
     self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
     self.type_map = TypeMap(self.namespace_catalog)
     self.type_map.register_container_type(CORE_NAMESPACE, 'Bar', Bar)
     self.type_map.register_map(Bar, ObjectMapper)
     self.manager = BuildManager(self.type_map)
     self.mapper = ObjectMapper(self.bar_spec)
Example #12
0
 def setUp(self):
     self.setUpBazSpec()
     self.spec_catalog = SpecCatalog()
     self.spec_catalog.register_spec(self.baz_spec, 'test.yaml')
     self.namespace = SpecNamespace('a test namespace',
                                    CORE_NAMESPACE, [{
                                        'source': 'test.yaml'
                                    }],
                                    catalog=self.spec_catalog)
     self.namespace_catalog = NamespaceCatalog()
     self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
     self.type_map = TypeMap(self.namespace_catalog)
     self.type_map.register_container_type(CORE_NAMESPACE, 'Baz', Baz)
     self.type_map.register_map(Baz, ObjectMapper)
     self.manager = BuildManager(self.type_map)
     self.mapper = ObjectMapper(self.baz_spec)
Example #13
0
 def test_compound_type(self):
     """Test that convert_dtype passes through arguments if spec dtype is a list without any validation."""
     spec_type = [DtypeSpec('an int field', 'f1', 'int'), DtypeSpec('a float field', 'f2', 'float')]
     spec = DatasetSpec('an example dataset', spec_type, name='data')
     value = ['a', 1, 2.2]
     res, ret_dtype = ObjectMapper.convert_dtype(spec, value)
     self.assertListEqual(res, value)
     self.assertListEqual(ret_dtype, spec_type)
Example #14
0
 def _test_keep_higher_precision_helper(self, spec_type, value_types):
     data = 1
     spec = DatasetSpec('an example dataset', spec_type, name='data')
     for dtype in value_types:
         value = self._get_type(dtype)(data)
         match = (value, self._get_type(dtype))
         with self.subTest(dtype=dtype):
             ret = ObjectMapper.convert_dtype(spec, value)
             self.assertTupleEqual(ret, match)
             self.assertIs(ret[0].dtype.type, match[1])
Example #15
0
 def _test_convert_alias(self, spec_type, value_types):
     data = 1
     spec = DatasetSpec('an example dataset', spec_type, name='data')
     match = (self._get_type(spec_type)(data), self._get_type(spec_type))
     for dtype in value_types:
         value = self._get_type(dtype)(data)  # convert data to given dtype
         with self.subTest(dtype=dtype):
             ret = ObjectMapper.convert_dtype(spec, value)
             self.assertTupleEqual(ret, match)
             self.assertIs(ret[0].dtype.type, match[1])
Example #16
0
    def test_isodatetime_spec(self):
        spec_type = 'isodatetime'
        spec = DatasetSpec('an example dataset', spec_type, name='data')

        # NOTE: datetime.isoformat is called on all values with a datetime spec before conversion
        # see ObjectMapper.get_attr_value
        value = datetime.isoformat(datetime(2020, 11, 10))
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, b'2020-11-10T00:00:00')
        self.assertIs(type(ret), bytes)
        self.assertEqual(ret_dtype, 'ascii')
Example #17
0
 def _test_convert_higher_precision_helper(self, spec_type, value_types):
     data = 1
     spec = DatasetSpec('an example dataset', spec_type, name='data')
     match = (self._get_type(spec_type)(data), self._get_type(spec_type))
     for dtype in value_types:
         value = self._get_type(dtype)(data)  # convert data to given dtype
         with self.subTest(dtype=dtype):
             s = np.dtype(self._get_type(spec_type))
             g = np.dtype(self._get_type(dtype))
             msg = ("Spec 'data': Value with data type %s is being converted to data type %s as specified."
                    % (g.name, s.name))
             with self.assertWarnsWith(UserWarning, msg):
                 ret = ObjectMapper.convert_dtype(spec, value)
             self.assertTupleEqual(ret, match)
             self.assertIs(ret[0].dtype.type, match[1])
Example #18
0
class TestDataMapScalar(TestCase):
    def setUp(self):
        self.setUpBazSpec()
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.baz_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'BazScalar',
                                              BazScalar)
        self.type_map.register_map(BazScalar, ObjectMapper)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.baz_spec)

    def setUpBazSpec(self):
        self.baz_spec = DatasetSpec(doc='a BazScalar type',
                                    dtype='int',
                                    name='MyBaz',
                                    data_type_def='BazScalar')

    def test_construct_scalar_dataset(self):
        """Test constructing a Data object with an h5py.Dataset with shape (1, ) for scalar spec."""
        with h5py.File('test.h5', 'w') as file:
            test_ds = file.create_dataset('test_ds', data=[1])
            expected = BazScalar(
                name='MyBaz',
                data=1,
            )
            builder = DatasetBuilder(
                name='MyBaz',
                data=test_ds,
                attributes={
                    'data_type': 'BazScalar',
                    'namespace': CORE_NAMESPACE,
                    'object_id': expected.object_id
                },
            )
            container = self.mapper.construct(builder, self.manager)
            self.assertTrue(np.issubdtype(type(
                container.data), np.integer))  # as opposed to h5py.Dataset
            self.assertContainerEqual(container, expected)
        os.remove('test.h5')
Example #19
0
class TestDataMap(unittest.TestCase):
    def setUp(self):
        self.setUpBazSpec()
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.baz_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Baz', Baz)
        self.type_map.register_map(Baz, ObjectMapper)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.baz_spec)

    def setUpBazSpec(self):
        self.baz_spec = DatasetSpec(
            'an Baz type',
            'int',
            name='MyBaz',
            data_type_def='Baz',
            attributes=[
                AttributeSpec('baz_attr', 'an example string attribute',
                              'text')
            ])

    def test_build(self):
        ''' Test default mapping functionality when no attributes are nested '''
        container = Baz('my_baz', list(range(10)),
                        'abcdefghijklmnopqrstuvwxyz')
        builder = self.mapper.build(container, self.manager)
        expected = DatasetBuilder(
            'my_baz',
            list(range(10)),
            attributes={'baz_attr': 'abcdefghijklmnopqrstuvwxyz'})
        self.assertDictEqual(builder, expected)
Example #20
0
    def test_value_none(self):
        spec = DatasetSpec('an example dataset', 'int', name='data')
        self.assertTupleEqual(ObjectMapper.convert_dtype(spec, None), (None, 'int'))

        spec = DatasetSpec('an example dataset', RefSpec(reftype='object', target_type='int'), name='data')
        self.assertTupleEqual(ObjectMapper.convert_dtype(spec, None), (None, 'object'))
Example #21
0
class TestDataMap(BazSpecMixin, TestCase):
    def setUp(self):
        self.setUpBazSpec()
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.baz_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Baz', Baz)
        self.type_map.register_map(Baz, ObjectMapper)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.baz_spec)

    def setUpBazSpec(self):
        self.baz_spec = DatasetSpec(
            doc='an Baz type',
            dtype='int',
            name='MyBaz',
            data_type_def='Baz',
            shape=[None],
            attributes=[
                AttributeSpec('baz_attr', 'an example string attribute',
                              'text')
            ])

    def test_build(self):
        ''' Test default mapping functionality when no attributes are nested '''
        container = Baz('MyBaz', list(range(10)), 'abcdefghijklmnopqrstuvwxyz')
        builder = self.mapper.build(container, self.manager)
        expected = DatasetBuilder(
            'MyBaz',
            list(range(10)),
            attributes={'baz_attr': 'abcdefghijklmnopqrstuvwxyz'})
        self.assertBuilderEqual(builder, expected)

    def test_build_empty_data(self):
        """Test building of a Data object with empty data."""
        baz_inc_spec = DatasetSpec(doc='doc',
                                   data_type_inc='Baz',
                                   quantity=ZERO_OR_MANY)
        baz_holder_spec = GroupSpec(doc='doc',
                                    data_type_def='BazHolder',
                                    datasets=[baz_inc_spec])
        self.spec_catalog.register_spec(baz_holder_spec, 'test.yaml')
        self.type_map.register_container_type(CORE_NAMESPACE, 'BazHolder',
                                              BazHolder)
        self.holder_mapper = ObjectMapper(baz_holder_spec)

        baz = Baz('MyBaz', [], 'abcdefghijklmnopqrstuvwxyz')
        holder = BazHolder('holder', [baz])

        builder = self.holder_mapper.build(holder, self.manager)
        expected = GroupBuilder(
            name='holder',
            datasets=[
                DatasetBuilder(name='MyBaz',
                               data=[],
                               attributes={
                                   'baz_attr': 'abcdefghijklmnopqrstuvwxyz',
                                   'data_type': 'Baz',
                                   'namespace': 'test_core',
                                   'object_id': baz.object_id
                               })
            ])
        self.assertBuilderEqual(builder, expected)

    def test_append(self):
        with h5py.File('test.h5', 'w') as file:
            test_ds = file.create_dataset('test_ds',
                                          data=[1, 2, 3],
                                          chunks=True,
                                          maxshape=(None, ))
            container = Baz('MyBaz', test_ds, 'abcdefghijklmnopqrstuvwxyz')
            container.append(4)
            np.testing.assert_array_equal(container[:], [1, 2, 3, 4])
        os.remove('test.h5')

    def test_extend(self):
        with h5py.File('test.h5', 'w') as file:
            test_ds = file.create_dataset('test_ds',
                                          data=[1, 2, 3],
                                          chunks=True,
                                          maxshape=(None, ))
            container = Baz('MyBaz', test_ds, 'abcdefghijklmnopqrstuvwxyz')
            container.extend([4, 5])
            np.testing.assert_array_equal(container[:], [1, 2, 3, 4, 5])
        os.remove('test.h5')
Example #22
0
class TestDataMapScalarCompound(TestCase):
    def setUp(self):
        self.setUpBazSpec()
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.baz_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE,
                                              'BazScalarCompound',
                                              BazScalarCompound)
        self.type_map.register_map(BazScalarCompound, ObjectMapper)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.baz_spec)

    def setUpBazSpec(self):
        self.baz_spec = DatasetSpec(
            doc='a BazScalarCompound type',
            dtype=[
                DtypeSpec(name='id',
                          dtype='uint64',
                          doc='The unique identifier in this table.'),
                DtypeSpec(name='attr1', dtype='text', doc='A text attribute.'),
            ],
            name='MyBaz',
            data_type_def='BazScalarCompound',
        )

    def test_construct_scalar_compound_dataset(self):
        """Test construct on a compound h5py.Dataset with shape (1, ) for scalar spec does not resolve the data."""
        with h5py.File('test.h5', 'w') as file:
            comp_type = np.dtype([('id', np.uint64),
                                  ('attr1', h5py.special_dtype(vlen=str))])
            test_ds = file.create_dataset(name='test_ds',
                                          data=np.array((1, 'text'),
                                                        dtype=comp_type),
                                          shape=(1, ),
                                          dtype=comp_type)
            expected = BazScalarCompound(
                name='MyBaz',
                data=(1, 'text'),
            )
            builder = DatasetBuilder(
                name='MyBaz',
                data=test_ds,
                attributes={
                    'data_type': 'BazScalarCompound',
                    'namespace': CORE_NAMESPACE,
                    'object_id': expected.object_id
                },
            )
            container = self.mapper.construct(builder, self.manager)
            self.assertEqual(type(container.data), h5py.Dataset)
            self.assertContainerEqual(container, expected)
        os.remove('test.h5')
Example #23
0
    def test_no_spec(self):
        spec_type = None
        spec = DatasetSpec('an example dataset', spec_type, name='data')

        value = [1, 2, 3]
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertListEqual(ret, value)
        self.assertIs(type(ret[0]), int)
        self.assertEqual(ret_dtype, int)

        value = np.uint64(4)
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret), np.uint64)
        self.assertEqual(ret_dtype, np.uint64)

        value = 'hello'
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret), str)
        self.assertEqual(ret_dtype, 'utf8')

        value = b'hello'
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret), bytes)
        self.assertEqual(ret_dtype, 'ascii')

        value = np.array(['aa', 'bb'])
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        np.testing.assert_array_equal(ret, value)
        self.assertEqual(ret_dtype, 'utf8')

        value = np.array(['aa', 'bb'], dtype='S2')
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        np.testing.assert_array_equal(ret, value)
        self.assertEqual(ret_dtype, 'ascii')

        value = DataChunkIterator(data=[1, 2, 3])
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(ret.dtype.type, np.dtype(int).type)
        self.assertIs(type(ret.data[0]), int)
        self.assertEqual(ret_dtype, np.dtype(int).type)

        value = DataChunkIterator(data=['a', 'b'])
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(ret.dtype.type, np.str_)
        self.assertIs(type(ret.data[0]), str)
        self.assertEqual(ret_dtype, 'utf8')

        value = H5DataIO(np.arange(30).reshape(5, 2, 3))
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(ret.data.dtype.type, np.dtype(int).type)
        self.assertEqual(ret_dtype, np.dtype(int).type)

        value = H5DataIO(['foo', 'bar'])
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret.data[0]), str)
        self.assertEqual(ret_dtype, 'utf8')

        value = H5DataIO([b'foo', b'bar'])
        ret, ret_dtype = ObjectMapper.convert_dtype(spec, value)
        self.assertEqual(ret, value)
        self.assertIs(type(ret.data[0]), bytes)
        self.assertEqual(ret_dtype, 'ascii')

        value = []
        msg = "Cannot infer dtype of empty list or tuple. Please use numpy array with specified dtype."
        with self.assertRaisesWith(ValueError, msg):
            ObjectMapper.convert_dtype(spec, value)
Example #24
0
class TestReference(TestCase):
    def setUp(self):
        self.foo_spec = GroupSpec(
            'A test group specification with data type Foo',
            data_type_def='Foo')
        self.bar_spec = GroupSpec(
            'A test group specification with a data type Bar',
            data_type_def='Bar',
            datasets=[DatasetSpec('an example dataset', 'int', name='data')],
            attributes=[
                AttributeSpec('attr1', 'an example string attribute', 'text'),
                AttributeSpec('attr2', 'an example integer attribute', 'int'),
                AttributeSpec('foo',
                              'a referenced foo',
                              RefSpec('Foo', 'object'),
                              required=False)
            ])

        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.foo_spec, 'test.yaml')
        self.spec_catalog.register_spec(self.bar_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Foo', Foo)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Bar', Bar)
        self.manager = BuildManager(self.type_map)
        self.foo_mapper = ObjectMapper(self.foo_spec)
        self.bar_mapper = ObjectMapper(self.bar_spec)

    def test_build_attr_ref(self):
        ''' Test default mapping functionality when one container contains an attribute reference to another container.
        '''
        foo_inst = Foo('my_foo')
        bar_inst1 = Bar('my_bar1', list(range(10)), 'value1', 10, foo=foo_inst)
        bar_inst2 = Bar('my_bar2', list(range(10)), 'value1', 10)

        foo_builder = self.manager.build(foo_inst, root=True)
        bar1_builder = self.manager.build(bar_inst1, root=True)  # adds refs
        bar2_builder = self.manager.build(bar_inst2, root=True)

        foo_expected = GroupBuilder('my_foo',
                                    attributes={
                                        'data_type': 'Foo',
                                        'namespace': CORE_NAMESPACE,
                                        'object_id': foo_inst.object_id
                                    })
        bar1_expected = GroupBuilder(
            'n/a',  # name doesn't matter
            datasets={'data': DatasetBuilder('data', list(range(10)))},
            attributes={
                'attr1': 'value1',
                'attr2': 10,
                'foo': ReferenceBuilder(foo_expected),
                'data_type': 'Bar',
                'namespace': CORE_NAMESPACE,
                'object_id': bar_inst1.object_id
            })
        bar2_expected = GroupBuilder(
            'n/a',  # name doesn't matter
            datasets={'data': DatasetBuilder('data', list(range(10)))},
            attributes={
                'attr1': 'value1',
                'attr2': 10,
                'data_type': 'Bar',
                'namespace': CORE_NAMESPACE,
                'object_id': bar_inst2.object_id
            })
        self.assertDictEqual(foo_builder, foo_expected)
        self.assertDictEqual(bar1_builder, bar1_expected)
        self.assertDictEqual(bar2_builder, bar2_expected)

    def test_build_attr_ref_invalid(self):
        ''' Test default mapping functionality when one container contains an attribute reference to another container.
        '''
        bar_inst1 = Bar('my_bar1', list(range(10)), 'value1', 10)
        bar_inst1._Bar__foo = object()  # make foo object a non-container type

        msg = "invalid type for reference 'foo' (<class 'object'>) - must be AbstractContainer"
        with self.assertRaisesWith(ValueError, msg):
            self.bar_mapper.build(bar_inst1, self.manager)
Example #25
0
 def test_override_type_int_restrict_precision(self):
     spec = DatasetSpec('an example dataset', 'int8', name='data')
     res = ObjectMapper.convert_dtype(spec, np.int64(1), 'int64')
     self.assertTupleEqual(res, (np.int64(1), np.int64))
Example #26
0
class TestLinkedContainer(TestCase):
    def setUp(self):
        self.foo_spec = GroupSpec(
            'A test group specification with data type Foo',
            data_type_def='Foo')
        self.bar_spec = GroupSpec(
            'A test group specification with a data type Bar',
            data_type_def='Bar',
            groups=[self.foo_spec],
            datasets=[DatasetSpec('an example dataset', 'int', name='data')],
            attributes=[
                AttributeSpec('attr1', 'an example string attribute', 'text'),
                AttributeSpec('attr2', 'an example integer attribute', 'int')
            ])

        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.foo_spec, 'test.yaml')
        self.spec_catalog.register_spec(self.bar_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Foo', Foo)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Bar', Bar)
        self.manager = BuildManager(self.type_map)
        self.foo_mapper = ObjectMapper(self.foo_spec)
        self.bar_mapper = ObjectMapper(self.bar_spec)

    def test_build_child_link(self):
        ''' Test default mapping functionality when one container contains a child link to another container '''
        foo_inst = Foo('my_foo')
        bar_inst1 = Bar('my_bar1', list(range(10)), 'value1', 10, foo=foo_inst)
        # bar_inst2.foo should link to bar_inst1.foo
        bar_inst2 = Bar('my_bar2', list(range(10)), 'value1', 10, foo=foo_inst)

        foo_builder = self.foo_mapper.build(foo_inst, self.manager)
        bar1_builder = self.bar_mapper.build(bar_inst1, self.manager)
        bar2_builder = self.bar_mapper.build(bar_inst2, self.manager)

        foo_expected = GroupBuilder('my_foo')

        inner_foo_builder = GroupBuilder('my_foo',
                                         attributes={
                                             'data_type': 'Foo',
                                             'namespace': CORE_NAMESPACE,
                                             'object_id': foo_inst.object_id
                                         })
        bar1_expected = GroupBuilder(
            'my_bar1',
            datasets={'data': DatasetBuilder('data', list(range(10)))},
            groups={'foo': inner_foo_builder},
            attributes={
                'attr1': 'value1',
                'attr2': 10
            })
        link_foo_builder = LinkBuilder(builder=inner_foo_builder)
        bar2_expected = GroupBuilder(
            'my_bar2',
            datasets={'data': DatasetBuilder('data', list(range(10)))},
            links={'foo': link_foo_builder},
            attributes={
                'attr1': 'value1',
                'attr2': 10
            })
        self.assertBuilderEqual(foo_builder, foo_expected)
        self.assertBuilderEqual(bar1_builder, bar1_expected)
        self.assertBuilderEqual(bar2_builder, bar2_expected)

    @unittest.expectedFailure
    def test_build_broken_link_parent(self):
        ''' Test that building a container with a broken link that has a parent raises an error. '''
        foo_inst = Foo('my_foo')
        Bar('my_bar1', list(range(10)), 'value1', 10,
            foo=foo_inst)  # foo_inst.parent is this bar
        # bar_inst2.foo should link to bar_inst1.foo
        bar_inst2 = Bar('my_bar2', list(range(10)), 'value1', 10, foo=foo_inst)

        # TODO bar_inst.foo.parent exists but is never built - this is a tricky edge case that should raise an error
        with self.assertRaises(OrphanContainerBuildError):
            self.bar_mapper.build(bar_inst2, self.manager)

    def test_build_broken_link_no_parent(self):
        ''' Test that building a container with a broken link that has no parent raises an error. '''
        foo_inst = Foo('my_foo')
        bar_inst1 = Bar('my_bar1', list(range(10)), 'value1', 10,
                        foo=foo_inst)  # foo_inst.parent is this bar
        # bar_inst2.foo should link to bar_inst1.foo
        bar_inst2 = Bar('my_bar2', list(range(10)), 'value1', 10, foo=foo_inst)
        bar_inst1.remove_foo()

        msg = (
            "my_bar2 (my_bar2): Linked Foo 'my_foo' has no parent. Remove the link or ensure the linked container "
            "is added properly.")
        with self.assertRaisesWith(OrphanContainerBuildError, msg):
            self.bar_mapper.build(bar_inst2, self.manager)
Example #27
0
 def test_override_type_numeric_to_uint(self):
     spec = DatasetSpec('an example dataset', 'numeric', name='data')
     res = ObjectMapper.convert_dtype(spec, np.uint32(1), 'uint8')
     self.assertTupleEqual(res, (np.uint32(1), np.uint32))
Example #28
0
 def test_override_type_numeric_to_uint_list(self):
     spec = DatasetSpec('an example dataset', 'numeric', name='data')
     res = ObjectMapper.convert_dtype(spec, np.uint32((1, 2, 3)), 'uint8')
     np.testing.assert_array_equal(res[0], np.uint32((1, 2, 3)))
     self.assertEqual(res[1], np.uint32)
Example #29
0
 def test_override_type_none_to_bool(self):
     spec = DatasetSpec('an example dataset', None, name='data')
     res = ObjectMapper.convert_dtype(spec, True, 'bool')
     self.assertTupleEqual(res, (True, np.bool_))
Example #30
0
class TestDataMap(TestCase):
    def setUp(self):
        self.setUpBazSpec()
        self.spec_catalog = SpecCatalog()
        self.spec_catalog.register_spec(self.baz_spec, 'test.yaml')
        self.namespace = SpecNamespace('a test namespace',
                                       CORE_NAMESPACE, [{
                                           'source': 'test.yaml'
                                       }],
                                       version='0.1.0',
                                       catalog=self.spec_catalog)
        self.namespace_catalog = NamespaceCatalog()
        self.namespace_catalog.add_namespace(CORE_NAMESPACE, self.namespace)
        self.type_map = TypeMap(self.namespace_catalog)
        self.type_map.register_container_type(CORE_NAMESPACE, 'Baz', Baz)
        self.type_map.register_map(Baz, ObjectMapper)
        self.manager = BuildManager(self.type_map)
        self.mapper = ObjectMapper(self.baz_spec)

    def setUpBazSpec(self):
        self.baz_spec = DatasetSpec(
            'an Baz type',
            'int',
            name='MyBaz',
            data_type_def='Baz',
            shape=[None],
            attributes=[
                AttributeSpec('baz_attr', 'an example string attribute',
                              'text')
            ])

    def test_build(self):
        ''' Test default mapping functionality when no attributes are nested '''
        container = Baz('my_baz', list(range(10)),
                        'abcdefghijklmnopqrstuvwxyz')
        builder = self.mapper.build(container, self.manager)
        expected = DatasetBuilder(
            'my_baz',
            list(range(10)),
            attributes={'baz_attr': 'abcdefghijklmnopqrstuvwxyz'})
        self.assertDictEqual(builder, expected)

    def test_append(self):
        with h5py.File('test.h5', 'w') as file:
            test_ds = file.create_dataset('test_ds',
                                          data=[1, 2, 3],
                                          chunks=True,
                                          maxshape=(None, ))
            container = Baz('my_baz', test_ds, 'abcdefghijklmnopqrstuvwxyz')
            container.append(4)
            np.testing.assert_array_equal(container[:], [1, 2, 3, 4])
        os.remove('test.h5')

    def test_extend(self):
        with h5py.File('test.h5', 'w') as file:
            test_ds = file.create_dataset('test_ds',
                                          data=[1, 2, 3],
                                          chunks=True,
                                          maxshape=(None, ))
            container = Baz('my_baz', test_ds, 'abcdefghijklmnopqrstuvwxyz')
            container.extend([4, 5])
            np.testing.assert_array_equal(container[:], [1, 2, 3, 4, 5])
        os.remove('test.h5')