If you try to define a neurodata_type that references itself, e.g.
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
Cell In [1], line 1
----> 1 from ndx_biosample import Sample
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/ndx_biosample/__init__.py:27
22 load_namespaces(ndx_biosample_specpath)
24 # TODO: import your classes here or define your class using get_class to make
25 # them accessible at the package level
26 #BaseType = get_class('BaseType', 'ndx-biosample')
---> 27 Sample = get_class('Sample', 'ndx-biosample')
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:649, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
647 def func_call(*args, **kwargs):
648 pargs = _check_args(args, kwargs)
--> 649 return func(**pargs)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/pynwb/__init__.py:185, in get_class(**kwargs)
162 """
163 Parse the YAML file for a given neurodata_type that is a subclass of NWBContainer and automatically generate its
164 python API. This will work for most containers, but is known to not work for descendants of MultiContainerInterface
(...)
182
183 """
184 neurodata_type, namespace = getargs('neurodata_type', 'namespace', kwargs)
--> 185 return __TYPE_MAP.get_dt_container_cls(neurodata_type, namespace)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
643 def func_call(*args, **kwargs):
644 pargs = _check_args(args, kwargs)
--> 645 return func(args[0], **pargs)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:518, in TypeMap.get_dt_container_cls(self, **kwargs)
516 if cls is None and autogen: # dynamically generate a class
517 spec = self.__ns_catalog.get_spec(namespace, data_type)
--> 518 self.__check_dependent_types(spec, namespace)
519 parent_cls = self.__get_parent_cls(namespace, data_type, spec)
520 attr_names = self.__default_mapper_cls.get_attr_names(spec)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:544, in TypeMap.__check_dependent_types(self, spec, namespace)
542 if isinstance(spec, GroupSpec):
543 for child_spec in (spec.groups + spec.datasets + spec.links):
--> 544 __check_dependent_types_helper(child_spec, namespace)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:531, in TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper(spec, namespace)
529 if isinstance(spec, (GroupSpec, DatasetSpec)):
530 if spec.data_type_inc is not None:
--> 531 self.get_dt_container_cls(spec.data_type_inc, namespace) # TODO handle recursive definitions
532 if spec.data_type_def is not None: # nested type definition
533 self.get_dt_container_cls(spec.data_type_def, namespace)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
643 def func_call(*args, **kwargs):
644 pargs = _check_args(args, kwargs)
--> 645 return func(args[0], **pargs)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:518, in TypeMap.get_dt_container_cls(self, **kwargs)
516 if cls is None and autogen: # dynamically generate a class
517 spec = self.__ns_catalog.get_spec(namespace, data_type)
--> 518 self.__check_dependent_types(spec, namespace)
519 parent_cls = self.__get_parent_cls(namespace, data_type, spec)
520 attr_names = self.__default_mapper_cls.get_attr_names(spec)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:544, in TypeMap.__check_dependent_types(self, spec, namespace)
542 if isinstance(spec, GroupSpec):
543 for child_spec in (spec.groups + spec.datasets + spec.links):
--> 544 __check_dependent_types_helper(child_spec, namespace)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:531, in TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper(spec, namespace)
529 if isinstance(spec, (GroupSpec, DatasetSpec)):
530 if spec.data_type_inc is not None:
--> 531 self.get_dt_container_cls(spec.data_type_inc, namespace) # TODO handle recursive definitions
532 if spec.data_type_def is not None: # nested type definition
533 self.get_dt_container_cls(spec.data_type_def, namespace)
[... skipping similar frames: docval.<locals>.dec.<locals>.func_call at line 645 (735 times), TypeMap.__check_dependent_types at line 544 (734 times), TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper at line 531 (734 times), TypeMap.get_dt_container_cls at line 518 (734 times)]
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:518, in TypeMap.get_dt_container_cls(self, **kwargs)
516 if cls is None and autogen: # dynamically generate a class
517 spec = self.__ns_catalog.get_spec(namespace, data_type)
--> 518 self.__check_dependent_types(spec, namespace)
519 parent_cls = self.__get_parent_cls(namespace, data_type, spec)
520 attr_names = self.__default_mapper_cls.get_attr_names(spec)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:544, in TypeMap.__check_dependent_types(self, spec, namespace)
542 if isinstance(spec, GroupSpec):
543 for child_spec in (spec.groups + spec.datasets + spec.links):
--> 544 __check_dependent_types_helper(child_spec, namespace)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:531, in TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper(spec, namespace)
529 if isinstance(spec, (GroupSpec, DatasetSpec)):
530 if spec.data_type_inc is not None:
--> 531 self.get_dt_container_cls(spec.data_type_inc, namespace) # TODO handle recursive definitions
532 if spec.data_type_def is not None: # nested type definition
533 self.get_dt_container_cls(spec.data_type_def, namespace)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
643 def func_call(*args, **kwargs):
644 pargs = _check_args(args, kwargs)
--> 645 return func(args[0], **pargs)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:517, in TypeMap.get_dt_container_cls(self, **kwargs)
515 cls = self.__get_container_cls(namespace, data_type)
516 if cls is None and autogen: # dynamically generate a class
--> 517 spec = self.__ns_catalog.get_spec(namespace, data_type)
518 self.__check_dependent_types(spec, namespace)
519 parent_cls = self.__get_parent_cls(namespace, data_type, spec)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
643 def func_call(*args, **kwargs):
644 pargs = _check_args(args, kwargs)
--> 645 return func(args[0], **pargs)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/spec/namespace.py:316, in NamespaceCatalog.get_spec(self, **kwargs)
314 if namespace not in self.__namespaces:
315 raise KeyError("'%s' not a namespace" % namespace)
--> 316 return self.__namespaces[namespace].get_spec(data_type)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
643 def func_call(*args, **kwargs):
644 pargs = _check_args(args, kwargs)
--> 645 return func(args[0], **pargs)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/spec/namespace.py:148, in SpecNamespace.get_spec(self, **kwargs)
146 """Get the Spec object for the given data type"""
147 data_type = getargs('data_type', kwargs)
--> 148 spec = self.__catalog.get_spec(data_type)
149 if spec is None:
150 raise ValueError("No specification for '%s' in namespace '%s'" % (data_type, self.name))
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:644, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs)
643 def func_call(*args, **kwargs):
--> 644 pargs = _check_args(args, kwargs)
645 return func(args[0], **pargs)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:616, in docval.<locals>.dec.<locals>._check_args(args, kwargs)
613 """Parse and check arguments to decorated function. Raise warnings and errors as appropriate."""
614 # this function was separated from func_call() in order to make stepping through lines of code using pdb
615 # easier
--> 616 parsed = __parse_args(
617 loc_val,
618 args[1:] if is_method else args,
619 kwargs,
620 enforce_type=enforce_type,
621 enforce_shape=enforce_shape,
622 allow_extra=allow_extra,
623 allow_positional=allow_positional
624 )
626 parse_warnings = parsed.get('future_warnings')
627 if parse_warnings:
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:221, in __parse_args(validator, args, kwargs, enforce_type, enforce_shape, allow_extra, allow_positional)
218 try:
219 # check for duplicates in docval
220 names = [x['name'] for x in validator]
--> 221 duplicated = [item for item, count in collections.Counter(names).items()
222 if count > 1]
223 if duplicated:
224 raise ValueError(
225 'The following names are duplicated: {}'.format(duplicated))
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/collections/__init__.py:593, in Counter.__init__(self, iterable, **kwds)
582 '''Create a new, empty Counter object. And if given, count elements
583 from an input iterable. Or, initialize the count from another mapping
584 of elements to their counts.
(...)
590
591 '''
592 super().__init__()
--> 593 self.update(iterable, **kwds)
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/collections/__init__.py:670, in Counter.update(self, iterable, **kwds)
662 # The regular dict.update() operation makes no sense here because the
663 # replace behavior results in the some of original untouched counts
664 # being mixed-in with all of the other counts for a mismash that
665 # doesn't have a straight-forward interpretation in most counting
666 # contexts. Instead, we implement straight-addition. Both the inputs
667 # and outputs are allowed to contain zero and negative counts.
669 if iterable is not None:
--> 670 if isinstance(iterable, _collections_abc.Mapping):
671 if self:
672 self_get = self.get
File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/abc.py:119, in ABCMeta.__instancecheck__(cls, instance)
117 def __instancecheck__(cls, instance):
118 """Override for isinstance(instance, cls)."""
--> 119 return _abc_instancecheck(cls, instance)
RecursionError: maximum recursion depth exceeded in comparison
What happened?
If you try to define a neurodata_type that references itself, e.g.
then when you run
get_classyou get aRecursionError:--------------------------------------------------------------------------- RecursionError Traceback (most recent call last) Cell In [1], line 1 ----> 1 from ndx_biosample import Sample File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/ndx_biosample/__init__.py:27 22 load_namespaces(ndx_biosample_specpath) 24 # TODO: import your classes here or define your class using get_class to make 25 # them accessible at the package level 26 #BaseType = get_class('BaseType', 'ndx-biosample') ---> 27 Sample = get_class('Sample', 'ndx-biosample') File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:649, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs) 647 def func_call(*args, **kwargs): 648 pargs = _check_args(args, kwargs) --> 649 return func(**pargs) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/pynwb/__init__.py:185, in get_class(**kwargs) 162 """ 163 Parse the YAML file for a given neurodata_type that is a subclass of NWBContainer and automatically generate its 164 python API. This will work for most containers, but is known to not work for descendants of MultiContainerInterface (...) 182 183 """ 184 neurodata_type, namespace = getargs('neurodata_type', 'namespace', kwargs) --> 185 return __TYPE_MAP.get_dt_container_cls(neurodata_type, namespace) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs) 643 def func_call(*args, **kwargs): 644 pargs = _check_args(args, kwargs) --> 645 return func(args[0], **pargs) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:518, in TypeMap.get_dt_container_cls(self, **kwargs) 516 if cls is None and autogen: # dynamically generate a class 517 spec = self.__ns_catalog.get_spec(namespace, data_type) --> 518 self.__check_dependent_types(spec, namespace) 519 parent_cls = self.__get_parent_cls(namespace, data_type, spec) 520 attr_names = self.__default_mapper_cls.get_attr_names(spec) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:544, in TypeMap.__check_dependent_types(self, spec, namespace) 542 if isinstance(spec, GroupSpec): 543 for child_spec in (spec.groups + spec.datasets + spec.links): --> 544 __check_dependent_types_helper(child_spec, namespace) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:531, in TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper(spec, namespace) 529 if isinstance(spec, (GroupSpec, DatasetSpec)): 530 if spec.data_type_inc is not None: --> 531 self.get_dt_container_cls(spec.data_type_inc, namespace) # TODO handle recursive definitions 532 if spec.data_type_def is not None: # nested type definition 533 self.get_dt_container_cls(spec.data_type_def, namespace) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs) 643 def func_call(*args, **kwargs): 644 pargs = _check_args(args, kwargs) --> 645 return func(args[0], **pargs) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:518, in TypeMap.get_dt_container_cls(self, **kwargs) 516 if cls is None and autogen: # dynamically generate a class 517 spec = self.__ns_catalog.get_spec(namespace, data_type) --> 518 self.__check_dependent_types(spec, namespace) 519 parent_cls = self.__get_parent_cls(namespace, data_type, spec) 520 attr_names = self.__default_mapper_cls.get_attr_names(spec) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:544, in TypeMap.__check_dependent_types(self, spec, namespace) 542 if isinstance(spec, GroupSpec): 543 for child_spec in (spec.groups + spec.datasets + spec.links): --> 544 __check_dependent_types_helper(child_spec, namespace) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:531, in TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper(spec, namespace) 529 if isinstance(spec, (GroupSpec, DatasetSpec)): 530 if spec.data_type_inc is not None: --> 531 self.get_dt_container_cls(spec.data_type_inc, namespace) # TODO handle recursive definitions 532 if spec.data_type_def is not None: # nested type definition 533 self.get_dt_container_cls(spec.data_type_def, namespace) [... skipping similar frames: docval.<locals>.dec.<locals>.func_call at line 645 (735 times), TypeMap.__check_dependent_types at line 544 (734 times), TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper at line 531 (734 times), TypeMap.get_dt_container_cls at line 518 (734 times)] File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:518, in TypeMap.get_dt_container_cls(self, **kwargs) 516 if cls is None and autogen: # dynamically generate a class 517 spec = self.__ns_catalog.get_spec(namespace, data_type) --> 518 self.__check_dependent_types(spec, namespace) 519 parent_cls = self.__get_parent_cls(namespace, data_type, spec) 520 attr_names = self.__default_mapper_cls.get_attr_names(spec) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:544, in TypeMap.__check_dependent_types(self, spec, namespace) 542 if isinstance(spec, GroupSpec): 543 for child_spec in (spec.groups + spec.datasets + spec.links): --> 544 __check_dependent_types_helper(child_spec, namespace) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:531, in TypeMap.__check_dependent_types.<locals>.__check_dependent_types_helper(spec, namespace) 529 if isinstance(spec, (GroupSpec, DatasetSpec)): 530 if spec.data_type_inc is not None: --> 531 self.get_dt_container_cls(spec.data_type_inc, namespace) # TODO handle recursive definitions 532 if spec.data_type_def is not None: # nested type definition 533 self.get_dt_container_cls(spec.data_type_def, namespace) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs) 643 def func_call(*args, **kwargs): 644 pargs = _check_args(args, kwargs) --> 645 return func(args[0], **pargs) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/build/manager.py:517, in TypeMap.get_dt_container_cls(self, **kwargs) 515 cls = self.__get_container_cls(namespace, data_type) 516 if cls is None and autogen: # dynamically generate a class --> 517 spec = self.__ns_catalog.get_spec(namespace, data_type) 518 self.__check_dependent_types(spec, namespace) 519 parent_cls = self.__get_parent_cls(namespace, data_type, spec) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs) 643 def func_call(*args, **kwargs): 644 pargs = _check_args(args, kwargs) --> 645 return func(args[0], **pargs) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/spec/namespace.py:316, in NamespaceCatalog.get_spec(self, **kwargs) 314 if namespace not in self.__namespaces: 315 raise KeyError("'%s' not a namespace" % namespace) --> 316 return self.__namespaces[namespace].get_spec(data_type) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:645, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs) 643 def func_call(*args, **kwargs): 644 pargs = _check_args(args, kwargs) --> 645 return func(args[0], **pargs) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/spec/namespace.py:148, in SpecNamespace.get_spec(self, **kwargs) 146 """Get the Spec object for the given data type""" 147 data_type = getargs('data_type', kwargs) --> 148 spec = self.__catalog.get_spec(data_type) 149 if spec is None: 150 raise ValueError("No specification for '%s' in namespace '%s'" % (data_type, self.name)) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:644, in docval.<locals>.dec.<locals>.func_call(*args, **kwargs) 643 def func_call(*args, **kwargs): --> 644 pargs = _check_args(args, kwargs) 645 return func(args[0], **pargs) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:616, in docval.<locals>.dec.<locals>._check_args(args, kwargs) 613 """Parse and check arguments to decorated function. Raise warnings and errors as appropriate.""" 614 # this function was separated from func_call() in order to make stepping through lines of code using pdb 615 # easier --> 616 parsed = __parse_args( 617 loc_val, 618 args[1:] if is_method else args, 619 kwargs, 620 enforce_type=enforce_type, 621 enforce_shape=enforce_shape, 622 allow_extra=allow_extra, 623 allow_positional=allow_positional 624 ) 626 parse_warnings = parsed.get('future_warnings') 627 if parse_warnings: File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/site-packages/hdmf/utils.py:221, in __parse_args(validator, args, kwargs, enforce_type, enforce_shape, allow_extra, allow_positional) 218 try: 219 # check for duplicates in docval 220 names = [x['name'] for x in validator] --> 221 duplicated = [item for item, count in collections.Counter(names).items() 222 if count > 1] 223 if duplicated: 224 raise ValueError( 225 'The following names are duplicated: {}'.format(duplicated)) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/collections/__init__.py:593, in Counter.__init__(self, iterable, **kwds) 582 '''Create a new, empty Counter object. And if given, count elements 583 from an input iterable. Or, initialize the count from another mapping 584 of elements to their counts. (...) 590 591 ''' 592 super().__init__() --> 593 self.update(iterable, **kwds) File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/collections/__init__.py:670, in Counter.update(self, iterable, **kwds) 662 # The regular dict.update() operation makes no sense here because the 663 # replace behavior results in the some of original untouched counts 664 # being mixed-in with all of the other counts for a mismash that 665 # doesn't have a straight-forward interpretation in most counting 666 # contexts. Instead, we implement straight-addition. Both the inputs 667 # and outputs are allowed to contain zero and negative counts. 669 if iterable is not None: --> 670 if isinstance(iterable, _collections_abc.Mapping): 671 if self: 672 self_get = self.get File ~/opt/miniconda3/envs/conda_py3.9/lib/python3.9/abc.py:119, in ABCMeta.__instancecheck__(cls, instance) 117 def __instancecheck__(cls, instance): 118 """Override for isinstance(instance, cls).""" --> 119 return _abc_instancecheck(cls, instance) RecursionError: maximum recursion depth exceeded in comparisonSteps to Reproduce
Traceback
Operating System
macOS
Python Executable
Conda
Python Version
3.9
Package Versions
No response
Code of Conduct