From 3dee7899ce122c53017f97bbcc6be9e91b22e5a2 Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Sun, 5 Oct 2025 21:33:25 -0400 Subject: [PATCH 1/4] Add strain field to subject metadata and corresponding test case --- dandi/consts.py | 1 + dandi/tests/fixtures.py | 1 + dandi/tests/test_metadata.py | 1 + 3 files changed, 3 insertions(+) diff --git a/dandi/consts.py b/dandi/consts.py index ff065e7cc..5518d8d38 100644 --- a/dandi/consts.py +++ b/dandi/consts.py @@ -27,6 +27,7 @@ "genotype", "sex", "species", + "strain", "subject_id", ) diff --git a/dandi/tests/fixtures.py b/dandi/tests/fixtures.py index d246109ab..541da8ac2 100644 --- a/dandi/tests/fixtures.py +++ b/dandi/tests/fixtures.py @@ -110,6 +110,7 @@ def simple2_nwb( date_of_birth=datetime(2016, 12, 1, tzinfo=tzutc()), sex="U", species="Mus musculus", + strain="C57BL/6J", ), **simple1_nwb_metadata, ) diff --git a/dandi/tests/test_metadata.py b/dandi/tests/test_metadata.py index 5c20acf0d..1015f3a9e 100644 --- a/dandi/tests/test_metadata.py +++ b/dandi/tests/test_metadata.py @@ -898,6 +898,7 @@ def test_nwb2asset(simple2_nwb: Path) -> None: identifier="http://purl.obolibrary.org/obo/NCBITaxon_10090", name="Mus musculus - House mouse", ), + strain=StrainType(schemaKey="StrainType", name="C57BL/6J"), ), ], variableMeasured=[], From e3710012082de53f6990df5176859eb37e2d51c8 Mon Sep 17 00:00:00 2001 From: Ben Dichter Date: Sun, 5 Oct 2025 21:35:30 -0400 Subject: [PATCH 2/4] Add StrainType import to test_metadata.py --- dandi/tests/test_metadata.py | 1 + 1 file changed, 1 insertion(+) diff --git a/dandi/tests/test_metadata.py b/dandi/tests/test_metadata.py index 1015f3a9e..749d8343e 100644 --- a/dandi/tests/test_metadata.py +++ b/dandi/tests/test_metadata.py @@ -24,6 +24,7 @@ SexType, Software, SpeciesType, + StrainType ) from dandischema.models import Dandiset as DandisetMeta from dateutil.tz import tzutc From 4026e84508eff4d7800d8005624557eb96084f08 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 6 Oct 2025 10:22:03 -0400 Subject: [PATCH 3/4] BF: need to account for change of size due to strain added, just replaced with ANY_INT for contentSize check --- dandi/tests/test_metadata.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dandi/tests/test_metadata.py b/dandi/tests/test_metadata.py index 749d8343e..9754448f6 100644 --- a/dandi/tests/test_metadata.py +++ b/dandi/tests/test_metadata.py @@ -6,7 +6,7 @@ import shutil from typing import Any -from anys import ANY_AWARE_DATETIME, AnyFullmatch, AnyIn +from anys import ANY_AWARE_DATETIME, ANY_INT, AnyFullmatch, AnyIn from dandischema.consts import DANDI_SCHEMA_VERSION from dandischema.metadata import validate from dandischema.models import ( @@ -24,7 +24,7 @@ SexType, Software, SpeciesType, - StrainType + StrainType, ) from dandischema.models import Dandiset as DandisetMeta from dateutil.tz import tzutc @@ -874,7 +874,7 @@ def test_nwb2asset(simple2_nwb: Path) -> None: ], ), ], - contentSize=ByteSize(19664), + contentSize=ANY_INT, encodingFormat="application/x-nwb", digest={DigestType.dandi_etag: "dddddddddddddddddddddddddddddddd-1"}, path=str(simple2_nwb), From b0b07c6699587ca359e286838004fa2775ed2792 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 6 Oct 2025 10:44:16 -0400 Subject: [PATCH 4/4] Provide custom rendering for DandiBaseModel inequalities to simplify handling --- dandi/pytest_plugin.py | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/dandi/pytest_plugin.py b/dandi/pytest_plugin.py index 26ad6da21..e78577bb7 100644 --- a/dandi/pytest_plugin.py +++ b/dandi/pytest_plugin.py @@ -1,5 +1,6 @@ from __future__ import annotations +from dandischema.models import DandiBaseModel from pytest import Config, Item, Parser from .tests.fixtures import * # noqa: F401, F403 # lgtm [py/polluting-import] @@ -28,9 +29,7 @@ def pytest_configure(config): "ai_generated", ] for marker in markers: - config.addinivalue_line( - "markers", marker - ) + config.addinivalue_line("markers", marker) def pytest_collection_modifyitems(items: list[Item], config: Config) -> None: @@ -46,3 +45,24 @@ def pytest_collection_modifyitems(items: list[Item], config: Config) -> None: deselected_items.append(item) config.hook.pytest_deselected(items=deselected_items) items[:] = selected_items + + +def pytest_assertrepr_compare(op, left, right): + """Custom comparison representation for your classes.""" + if ( + isinstance(left, DandiBaseModel) + and isinstance(right, DandiBaseModel) + and op == "==" + ): + ldict, rdict = dict(left), dict(right) + if ldict == rdict: + return [ + "dict representations of models are equal, but values aren't!", + f"Left: {left!r}", + f"Right: {right!r}", + ] + else: + # Rely on pytest just "recursing" into interpreting the dict fails + # TODO: could be further improved by account for ANY values etc + assert ldict == rdict # for easier comprehension of diffs + return None