From fcd52c07f347c7ff51a87265c7aa3e2cb68b32d1 Mon Sep 17 00:00:00 2001 From: Ryan Ly Date: Tue, 11 May 2021 09:26:35 -0700 Subject: [PATCH] Use parent class fieldsname instead of '__fields__' (#598) * Use parent class fieldsname instead of '__fields__' Fix #591 * Update changelog, prep for 2.5.2 * Fix broken tests --- CHANGELOG.md | 4 +++- src/hdmf/build/classgenerator.py | 10 +++++----- tests/unit/build_tests/test_classgenerator.py | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e1eb05f94..d34e2a668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,11 @@ # HDMF Changelog -## Upcoming +## HDMF 2.5.2 (May 11, 2021) ### Bug fix - Add explicit `setuptools` requirement. @hrnciar (#596) +- Fix issue with generated custom classes that use a custom fields name (e.g., PyNWB uses `__nwbfields__` instead + of `__fields__`). @rly (#598) ## HDMF 2.5.1 (April 23, 2021) diff --git a/src/hdmf/build/classgenerator.py b/src/hdmf/build/classgenerator.py index 55f7cc830..edd95a6e7 100644 --- a/src/hdmf/build/classgenerator.py +++ b/src/hdmf/build/classgenerator.py @@ -208,7 +208,7 @@ def apply_generator_to_field(cls, field_spec, bases, type_map): @classmethod def process_field_spec(cls, classdict, docval_args, parent_cls, attr_name, not_inherited_fields, type_map, spec): """Add __fields__ to the classdict and update the docval args for the field spec with the given attribute name. - :param classdict: The dict to update with __fields__. + :param classdict: The dict to update with __fields__ (or a different parent_cls._fieldsname). :param docval_args: The list of docval arguments. :param parent_cls: The parent class. :param attr_name: The attribute name of the field spec for the container class to generate. @@ -224,7 +224,7 @@ def process_field_spec(cls, classdict, docval_args, parent_cls, attr_name, not_i fields_conf['child'] = True # if getattr(field_spec, 'value', None) is not None: # TODO set the fixed value on the class? # fields_conf['settable'] = False - classdict.setdefault('__fields__', list()).append(fields_conf) + classdict.setdefault(parent_cls._fieldsname, list()).append(fields_conf) docval_arg = dict( name=attr_name, @@ -262,15 +262,15 @@ def _add_to_docval_args(cls, docval_args, arg): @classmethod def post_process(cls, classdict, bases, docval_args, spec): """Convert classdict['__fields__'] to tuple and update docval args for a fixed name and default name. - :param classdict: The class dictionary to convert. + :param classdict: The class dictionary to convert with '__fields__' key (or a different bases[0]._fieldsname) :param bases: The list of base classes. :param docval_args: The dict of docval arguments. :param spec: The spec for the container class to generate. """ # convert classdict['__fields__'] from list to tuple if present - fields = classdict.get('__fields__') + fields = classdict.get(bases[0]._fieldsname) if fields is not None: - classdict['__fields__'] = tuple(fields) + classdict[bases[0]._fieldsname] = tuple(fields) # if spec provides a fixed name for this type, remove the 'name' arg from docval_args so that values cannot # be passed for a name positional or keyword arg diff --git a/tests/unit/build_tests/test_classgenerator.py b/tests/unit/build_tests/test_classgenerator.py index 7e99c4142..0297eb018 100644 --- a/tests/unit/build_tests/test_classgenerator.py +++ b/tests/unit/build_tests/test_classgenerator.py @@ -783,7 +783,7 @@ def test_post_process_fixed_name(self): ) classdict = {} - bases = [] + bases = [Container] docval_args = [{'name': 'name', 'type': str, 'doc': 'name'}, {'name': 'attr1', 'type': ('array_data', 'data'), 'doc': 'a string attribute', 'shape': [None]}] @@ -810,7 +810,7 @@ def test_post_process_default_name(self): ) classdict = {} - bases = [] + bases = [Container] docval_args = [{'name': 'name', 'type': str, 'doc': 'name'}, {'name': 'attr1', 'type': ('array_data', 'data'), 'doc': 'a string attribute', 'shape': [None]}]