From 24127ff1a761af9a576f6c2ac925cae506d71e02 Mon Sep 17 00:00:00 2001 From: Yaroslav Halchenko Date: Mon, 20 Nov 2023 11:22:25 -0500 Subject: [PATCH] ENH: give informative assertion message when multiple values are found --- heudiconv/heuristics/reproin.py | 20 +++++++++++------ heudiconv/heuristics/test_reproin.py | 32 ++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 13 deletions(-) diff --git a/heudiconv/heuristics/reproin.py b/heudiconv/heuristics/reproin.py index 5ddde1be..0d919aa5 100644 --- a/heudiconv/heuristics/reproin.py +++ b/heudiconv/heuristics/reproin.py @@ -637,12 +637,14 @@ def from_series_info(name: str) -> Optional[str]: # For scouts -- we want only dicoms # https://github.com/nipy/heudiconv/issues/145 outtype: tuple[str, ...] - if "_Scout" in s.series_description or ( - datatype == "anat" - and datatype_suffix - and datatype_suffix.startswith("scout") - ) or ( - s.series_description.lower() == s.protocol_name.lower() + "_setter" + if ( + "_Scout" in s.series_description + or ( + datatype == "anat" + and datatype_suffix + and datatype_suffix.startswith("scout") + ) + or (s.series_description.lower() == s.protocol_name.lower() + "_setter") ): outtype = ("dicom",) else: @@ -725,7 +727,11 @@ def get_unique(seqinfos: list[SeqInfo], attr: str) -> Any: """ values = set(getattr(si, attr) for si in seqinfos) - assert len(values) == 1 + if len(values) != 1: + raise AssertionError( + f"Was expecting a single value for attribute {attr!r} " + f"but got: {', '.join(sorted(values))}" + ) return values.pop() diff --git a/heudiconv/heuristics/test_reproin.py b/heudiconv/heuristics/test_reproin.py index 2007df38..45b42cfc 100644 --- a/heudiconv/heuristics/test_reproin.py +++ b/heudiconv/heuristics/test_reproin.py @@ -7,6 +7,8 @@ from typing import NamedTuple from unittest.mock import patch +import pytest + from . import reproin from .reproin import ( filter_files, @@ -14,12 +16,20 @@ fix_dbic_protocol, fixup_subjectid, get_dups_marked, + get_unique, md5sum, parse_series_spec, sanitize_str, ) +class FakeSeqInfo(NamedTuple): + accession_number: str + study_description: str + field1: str + field2: str + + def test_get_dups_marked() -> None: no_dups: dict[tuple[str, tuple[str, ...], None], list[int]] = { ("some", ("foo",), None): [1] @@ -97,12 +107,6 @@ class FakeSeqInfo(NamedTuple): def test_fix_dbic_protocol() -> None: - class FakeSeqInfo(NamedTuple): - accession_number: str - study_description: str - field1: str - field2: str - accession_number = "A003" seq1 = FakeSeqInfo( accession_number, @@ -235,3 +239,19 @@ def test_parse_series_spec() -> None: "session": "01", "dir": "AP", } + + +def test_get_unique() -> None: + accession_number = "A003" + acqs = [ + FakeSeqInfo(accession_number, "mystudy", "nochangeplease", "nochangeeither"), + FakeSeqInfo(accession_number, "mystudy2", "nochangeplease", "nochangeeither"), + ] + + assert get_unique(acqs, "accession_number") == accession_number # type: ignore[arg-type] + with pytest.raises(AssertionError) as ce: + get_unique(acqs, "study_description") # type: ignore[arg-type] + assert ( + str(ce.value) + == "Was expecting a single value for attribute 'study_description' but got: mystudy, mystudy2" + )