Skip to content

Commit e115bce

Browse files
rlyclaude
andcommitted
Add link_resources and get_external_resources to HERDManager
Move linked HERD functionality from NWBFile to HERDManager base class so any HERDManager subclass can manage a secondary linked HERD alongside the primary one. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent cea011f commit e115bce

3 files changed

Lines changed: 58 additions & 1 deletion

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
## HDMF Unreleased
44

55
### Enhancements
6-
- Made `HERDManager` an abstract interface (ABC) with an abstract `external_resources` property. Subclasses must now declare `external_resources` in their `__fields__` to satisfy the interface. Updated `__gather_fields` to allow auto-generated properties to override inherited abstract properties. @rly [#1431](https://github.com/hdmf-dev/hdmf/pull/1431)
6+
- Made `HERDManager` an abstract interface (ABC) with an abstract `external_resources` property. Subclasses must now declare `external_resources` in their `__fields__` to satisfy the interface. Updated `__gather_fields` to allow auto-generated properties to override inherited abstract properties. Added `link_resources` and `get_external_resources` methods to `HERDManager` for managing a linked HERD separate from the primary one. @rly [#1431](https://github.com/hdmf-dev/hdmf/pull/1431)
77

88
## HDMF 5.0.1 (March 16, 2026)
99

src/hdmf/container.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ class MyFile(HERDManager, Container):
5454
external resources.
5555
"""
5656

57+
def __init__(self, **kwargs):
58+
super().__init__(**kwargs)
59+
self._linked_external_resources = None
60+
5761
@property
5862
@abstractmethod
5963
def external_resources(self):
@@ -64,6 +68,29 @@ def external_resources(self):
6468
def external_resources(self, val):
6569
pass
6670

71+
def link_resources(self, external_resources):
72+
"""Link an external HERD object as the external resources for this container.
73+
74+
The linked HERD will not be written on export; the original HERD
75+
(if any) is preserved in the exported file. Use
76+
``get_external_resources(linked=True)`` to access the linked HERD.
77+
"""
78+
self._linked_external_resources = external_resources
79+
80+
def get_external_resources(self, linked=False):
81+
"""Return the HERD external resources object for this container.
82+
83+
Parameters
84+
----------
85+
linked : bool, optional
86+
If True, return the linked HERD set via ``link_resources``.
87+
If False (default), return the HERD set via ``__init__`` or the
88+
``external_resources`` attribute.
89+
"""
90+
if linked:
91+
return self._linked_external_resources
92+
return self.external_resources
93+
6794

6895
class AbstractContainer(metaclass=ExtenderMeta):
6996
# The name of the class attribute that subclasses use to autogenerate properties

tests/unit/test_container.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,36 @@ def test_mixin_external_resources_is_child(self):
6060
self.assertIn(er, container.children)
6161
self.assertIs(er.parent, container)
6262

63+
def test_link_resources(self):
64+
"""Test linking an external HERD object."""
65+
container = ContainerWithHERD(name='test')
66+
linked_herd = HERD()
67+
container.link_resources(linked_herd)
68+
self.assertIs(container.get_external_resources(linked=True), linked_herd)
69+
70+
def test_get_external_resources_default(self):
71+
"""Test get_external_resources returns the primary HERD by default."""
72+
container = ContainerWithHERD(name='test')
73+
er = HERD()
74+
container.external_resources = er
75+
self.assertIs(container.get_external_resources(), er)
76+
self.assertIs(container.get_external_resources(linked=False), er)
77+
78+
def test_get_external_resources_linked_default_none(self):
79+
"""Test get_external_resources(linked=True) returns None when no linked HERD is set."""
80+
container = ContainerWithHERD(name='test')
81+
self.assertIsNone(container.get_external_resources(linked=True))
82+
83+
def test_link_resources_does_not_affect_primary(self):
84+
"""Test that linking a HERD does not overwrite the primary external_resources."""
85+
container = ContainerWithHERD(name='test')
86+
primary = HERD()
87+
linked = HERD()
88+
container.external_resources = primary
89+
container.link_resources(linked)
90+
self.assertIs(container.get_external_resources(), primary)
91+
self.assertIs(container.get_external_resources(linked=True), linked)
92+
6393

6494
class TestContainer(TestCase):
6595

0 commit comments

Comments
 (0)