Skip to content
Closed
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
16 changes: 5 additions & 11 deletions src/spyglass/utils/dj_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,15 +259,9 @@ def _nwb_table_tuple(self) -> tuple:
resolved = getattr(self, "_nwb_table", None) or (
AnalysisNwbfile
if "-> AnalysisNwbfile" in self.definition
else Nwbfile if "-> Nwbfile" in self.definition else None
else Nwbfile
)

if not resolved:
raise NotImplementedError(
f"{self.__class__.__name__} does not have a "
"(Analysis)Nwbfile foreign key or _nwb_table attribute."
)

return (
resolved,
table_dict[resolved],
Expand All @@ -276,10 +270,10 @@ def _nwb_table_tuple(self) -> tuple:
def fetch_nwb(self, *attrs, **kwargs):
"""Fetch NWBFile object from relevant table.

Implementing class must have a foreign key reference to Nwbfile or
AnalysisNwbfile (i.e., "-> (Analysis)Nwbfile" in definition)
or a _nwb_table attribute. If both are present, the attribute takes
precedence.
Data source is determined as follows:
1. If _nwb_table attribute is present, use it (takes precedence)
2. If "-> AnalysisNwbfile" foreign key exists in definition, use AnalysisNwbfile
3. Otherwise, default to Nwbfile

Additional logic support Export table logging.
"""
Expand Down
92 changes: 89 additions & 3 deletions tests/utils/test_mixin.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,96 @@ def test_bad_prefix(caplog, dj_conn, Mixin):
assert "Schema prefix not in SHARED_MODULES" in caplog.text


def test_nwb_table_missing(schema_test, Mixin):
def test_nwb_table_defaults_to_nwbfile(schema_test, Mixin, common):
schema_test(Mixin)
with pytest.raises(NotImplementedError):
Mixin().fetch_nwb()
# Should default to Nwbfile instead of raising NotImplementedError
table, attr = Mixin()._nwb_table_tuple
assert table == common.Nwbfile, f"Expected Nwbfile as default, got {table}"
assert (
attr == "nwb_file_abs_path"
), f"Expected nwb_file_abs_path, got {attr}"


def test_nwb_table_tuple_comprehensive(schema_test, SpyglassMixin, common):
"""Test _nwb_table_tuple logic for all scenarios including the new default behavior."""
import datajoint as dj

AnalysisNwbfile = common.AnalysisNwbfile
Nwbfile = common.Nwbfile

# Test table with explicit _nwb_table attribute
class TableWithNwbTableAttr(SpyglassMixin, dj.Lookup):
definition = """
id : int
"""
_nwb_table = common.AnalysisNwbfile
contents = [(0,)]

schema_test(TableWithNwbTableAttr)
table, attr = TableWithNwbTableAttr()._nwb_table_tuple
assert table == common.AnalysisNwbfile, "Should use _nwb_table attribute"
assert attr == "analysis_file_abs_path", "Should use analysis file path"

# Test table with AnalysisNwbfile FK in definition
class TableWithAnalysisNwbfileFK(SpyglassMixin, dj.Lookup):
definition = """
-> AnalysisNwbfile
id : int
"""
contents = []

schema_test(TableWithAnalysisNwbfileFK)
table, attr = TableWithAnalysisNwbfileFK()._nwb_table_tuple
assert table == common.AnalysisNwbfile, "Should detect AnalysisNwbfile FK"
assert attr == "analysis_file_abs_path", "Should use analysis file path"

# Test table with explicit Nwbfile FK in definition
class TableWithNwbfileFK(SpyglassMixin, dj.Lookup):
definition = """
-> Nwbfile
id : int
"""
contents = []

schema_test(TableWithNwbfileFK)
table, attr = TableWithNwbfileFK()._nwb_table_tuple
assert table == common.Nwbfile, "Should detect Nwbfile FK"
assert attr == "nwb_file_abs_path", "Should use nwb file path"

# Test table with no FK reference (should default to Nwbfile)
class TableWithNoFK(SpyglassMixin, dj.Lookup):
definition = """
id : int
"""
contents = [(0,)]

schema_test(TableWithNoFK)
table, attr = TableWithNoFK()._nwb_table_tuple
assert table == common.Nwbfile, "Should default to Nwbfile when no FK found"
assert attr == "nwb_file_abs_path", "Should use nwb file path by default"


def test_nwb_table_precedence(schema_test, SpyglassMixin, common):
"""Test that _nwb_table attribute takes precedence over FK definitions."""
import datajoint as dj

AnalysisNwbfile = common.AnalysisNwbfile

# _nwb_table should override FK in definition
class TableWithBoth(SpyglassMixin, dj.Lookup):
definition = """
-> AnalysisNwbfile
id : int
"""
_nwb_table = common.Nwbfile # Should override the FK
contents = []

schema_test(TableWithBoth)
table, attr = TableWithBoth()._nwb_table_tuple
assert table == common.Nwbfile, "_nwb_table should take precedence over FK"
assert (
attr == "nwb_file_abs_path"
), "Should use nwb file path from _nwb_table"


def test_auto_increment(schema_test, Mixin):
Expand Down
Loading