Skip to content

[Bug]: Infinite recursion when registering/resolving data types that depend on each other #1364

@rly

Description

@rly

What happened?

In hdmf-dev/hdmf-common-schema#91:
the DynamicTable data type contains a collection of MeaningsTable objects.
MeaningsTable is a subtype of a DynamicTable.

When loading the namespace, we get a recursion error below. This is not an issue if the collection of MeaningsTable objects is added to a child type of DynamicTable, e.g., a new type DynamicTableWithMeanings, but this is not ideal.

I think this schema, where A contains B and B is a subtype of A (B includes A), should be allowed, though it may be tricky to implement. I think we should also allow the simpler case where A contains A (#794). I think both HDMF and MatNWB will need to be updated to handle these use cases. @oruebel @bendichter @ehennestad thoughts?

The refactor of spec resolution in https://github.com/hdmf-dev/hdmf/pull/1326/changes in src/hdmf/spec/namespace.py lines 445-449 will also need to handle this.

Steps to Reproduce

Use that branch of hdmf-common and run tests

Traceback

tests/unit/spec_tests/test_spec_catalog.py:4: in <module>
    from hdmf.testing import TestCase
src/hdmf/testing/__init__.py:1: in <module>
    from .testcase import TestCase, H5RoundTripMixin
src/hdmf/testing/testcase.py:10: in <module>
    from ..common import validate as common_validate, get_manager
src/hdmf/common/__init__.py:268: in <module>
    load_namespaces(__resources['namespace_path'])
src/hdmf/utils.py:596: in func_call
    return func(**pargs)
           ^^^^^^^^^^^^^
src/hdmf/common/__init__.py:136: in load_namespaces
    return __TYPE_MAP.load_namespaces(namespace_path)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/hdmf/utils.py:592: in func_call
    return func(args[0], **pargs)
           ^^^^^^^^^^^^^^^^^^^^^^
src/hdmf/build/manager.py:491: in load_namespaces
    deps = self.__ns_catalog.load_namespaces(**kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/hdmf/utils.py:592: in func_call
    return func(args[0], **pargs)
           ^^^^^^^^^^^^^^^^^^^^^^
src/hdmf/spec/namespace.py:585: in load_namespaces
    ret[ns['name']] = self.__load_namespace(ns, r, resolve=resolve)
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
src/hdmf/spec/namespace.py:473: in __load_namespace
    self.__register_type(ndt, inc_ns, catalog, registered_types)
src/hdmf/spec/namespace.py:496: in __register_type
    self.__register_dependent_types(spec, inc_ns, catalog, registered_types)
src/hdmf/spec/namespace.py:525: in __register_dependent_types
    __register_dependent_types_helper(child_spec, inc_ns, catalog, registered_types)
src/hdmf/spec/namespace.py:519: in __register_dependent_types_helper
    __register_dependent_types_helper(child_spec, inc_ns, catalog, registered_types)
src/hdmf/spec/namespace.py:512: in __register_dependent_types_helper
    self.__register_type(spec.data_type_inc, inc_ns, catalog, registered_types)
src/hdmf/spec/namespace.py:496: in __register_type
    self.__register_dependent_types(spec, inc_ns, catalog, registered_types)
src/hdmf/spec/namespace.py:522: in __register_dependent_types
    self.__register_type(spec.data_type_inc, inc_ns, catalog, registered_types)
src/hdmf/spec/namespace.py:496: in __register_type
    self.__register_dependent_types(spec, inc_ns, catalog, registered_types)
E   RecursionError: maximum recursion depth exceeded
!!! Recursion detected (same locals & position)

Operating System

macOS

Python Version

3.13

Package Versions

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    category: bugerrors in the code or code behaviorcategory: proposalproposed enhancements or new featurespriority: mediumnon-critical problem and/or affecting only a small set of users

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions