Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Always use parent names in autogenerated child spec names #130

Merged
merged 3 commits into from
Aug 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 2 additions & 6 deletions src/hdmf/build/map.py
Original file line number Diff line number Diff line change
Expand Up @@ -598,12 +598,12 @@ def __get_fields(cls, name_stack, all_names, spec):
if spec.name is None:
name = cls.convert_dt_name(spec)
name_stack.append(name)
if name in all_names:
name = "_".join(name_stack)
name = '__'.join(name_stack)
all_names[name] = spec
if isinstance(spec, BaseStorageSpec):
if not (spec.data_type_def is None and spec.data_type_inc is None):
# don't get names for components in data_types
name_stack.pop()
return
for subspec in spec.attributes:
cls.__get_fields(name_stack, all_names, subspec)
Expand Down Expand Up @@ -643,10 +643,6 @@ def __map_spec(self, spec):
def map_attr(self, **kwargs):
""" Map an attribute to spec. Use this to override default behavior """
attr_name, spec = getargs('attr_name', 'spec', kwargs)
if hasattr(spec, 'name') and spec.name is not None:
n = spec.name
elif hasattr(spec, 'data_type_def') and spec.data_type_def is not None:
n = spec.data_type_def # noqa: F841
self.__spec2attr[spec] = attr_name
self.__attr2spec[attr_name] = spec

Expand Down
36 changes: 34 additions & 2 deletions tests/unit/build_tests/test_io_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,16 @@
from tests.unit.test_utils import Foo, FooBucket, CORE_NAMESPACE


class FooMapper(ObjectMapper):
"""Maps nested 'attr2' attribute on dataset 'my_data' to Foo.attr2 in constructor and attribute map
"""

def __init__(self, spec):
super(FooMapper, self).__init__(spec)
my_data_spec = spec.get_dataset('my_data')
self.map_spec('attr2', my_data_spec.get_attribute('attr2'))


class TestBase(unittest.TestCase):

def setUp(self):
Expand All @@ -37,7 +47,7 @@ def setUp(self):
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_map(Foo, ObjectMapper)
self.type_map.register_map(Foo, FooMapper)
self.manager = BuildManager(self.type_map)


Expand Down Expand Up @@ -130,7 +140,7 @@ def setUp(self):

self.spec_catalog.register_spec(self.bucket_spec, 'test.yaml')
self.type_map.register_container_type(CORE_NAMESPACE, 'FooBucket', FooBucket)
self.type_map.register_map(FooBucket, ObjectMapper)
self.type_map.register_map(FooBucket, self.setUpBucketMapper())
self.manager = BuildManager(self.type_map)

def setUpBucketBuilder(self):
Expand All @@ -139,6 +149,9 @@ def setUpBucketBuilder(self):
def setUpBucketSpec(self):
raise unittest.SkipTest('Abstract Base Class')

def setUpBucketMapper(self):
raise unittest.SkipTest('Abstract Base Class')

def test_build(self):
''' Test default mapping for an Container that has an Container as an attribute value '''
builder = self.manager.build(self.foo_bucket)
Expand Down Expand Up @@ -171,6 +184,9 @@ def setUpBucketSpec(self):
data_type_inc='Foo',
quantity=ZERO_OR_MANY)])

def setUpBucketMapper(self):
return ObjectMapper


class TestNestedContainersSubgroup(TestNestedBase):
'''
Expand All @@ -197,6 +213,14 @@ def setUpBucketSpec(self):
data_type_def='FooBucket',
groups=[tmp_spec])

def setUpBucketMapper(self):
class BucketMapper(ObjectMapper):
def __init__(self, spec):
super(BucketMapper, self).__init__(spec)
self.map_spec('foos', spec.get_group('foo_holder').get_data_type('Foo'))

return BucketMapper


class TestNestedContainersSubgroupSubgroup(TestNestedBase):
'''
Expand Down Expand Up @@ -225,6 +249,14 @@ def setUpBucketSpec(self):
data_type_def='FooBucket',
groups=[tmp_spec])

def setUpBucketMapper(self):
class BucketMapper(ObjectMapper):
def __init__(self, spec):
super(BucketMapper, self).__init__(spec)
self.map_spec('foos', spec.get_group('foo_holder_holder').get_group('foo_holder').get_data_type('Foo'))

return BucketMapper


class TestTypeMap(TestBase):

Expand Down
15 changes: 14 additions & 1 deletion tests/unit/build_tests/test_io_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ def test_build(self):
expected = GroupBuilder('my_bar', datasets={'data': DatasetBuilder(
'data', list(range(10)), attributes={'attr2': 10})},
attributes={'attr1': 'value1'})
self._remap_nested_attr()
builder = self.mapper.build(container_inst, self.manager)
self.assertDictEqual(builder, expected)

Expand All @@ -359,15 +360,27 @@ def test_construct(self):
'data', list(range(10)), attributes={'attr2': 10})},
attributes={'attr1': 'value1', 'data_type': 'Bar', 'namespace': CORE_NAMESPACE,
'object_id': expected.object_id})
self._remap_nested_attr()
container = self.mapper.construct(builder, self.manager)
self.assertEqual(container, expected)

def test_default_mapping_keys(self):
attr_map = self.mapper.get_attr_names(self.bar_spec)
keys = set(attr_map.keys())
expected = {'attr1', 'data', 'attr2'}
expected = {'attr1', 'data', 'data__attr2'}
self.assertSetEqual(keys, expected)

def test_remap_keys(self):
self._remap_nested_attr()
self.assertEqual(self.mapper.get_attr_spec('attr2'),
self.mapper.spec.get_dataset('data').get_attribute('attr2'))
self.assertEqual(self.mapper.get_attr_spec('attr1'), self.mapper.spec.get_attribute('attr1'))
self.assertEqual(self.mapper.get_attr_spec('data'), self.mapper.spec.get_dataset('data'))

def _remap_nested_attr(self):
data_spec = self.mapper.spec.get_dataset('data')
self.mapper.map_spec('attr2', data_spec.get_attribute('attr2'))


class TestObjectMapperNoNesting(TestObjectMapper):

Expand Down
7 changes: 7 additions & 0 deletions tests/unit/test_io_hdf5_h5tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,12 @@ def _get_manager():
data_type_def='FooBucket',
groups=[tmp_spec])

class FooMapper(ObjectMapper):
def __init__(self, spec):
super(FooMapper, self).__init__(spec)
my_data_spec = spec.get_dataset('my_data')
self.map_spec('attr2', my_data_spec.get_attribute('attr2'))

class BucketMapper(ObjectMapper):
def __init__(self, spec):
super(BucketMapper, self).__init__(spec)
Expand Down Expand Up @@ -461,6 +467,7 @@ def __init__(self, spec):
type_map.register_container_type(CORE_NAMESPACE, 'FooBucket', FooBucket)
type_map.register_container_type(CORE_NAMESPACE, 'FooFile', FooFile)

type_map.register_map(Foo, FooMapper)
type_map.register_map(FooBucket, BucketMapper)
type_map.register_map(FooFile, FileMapper)

Expand Down