From b0a59a4f29df6d5c7bf282b2b1608d87a8376c71 Mon Sep 17 00:00:00 2001 From: Matt Stone Date: Wed, 4 Mar 2026 08:50:18 -0800 Subject: [PATCH] refactor: Improve error messages in CounterPivotTable and DelimitedList Include annotation types and quote field names in error messages for easier debugging. Co-Authored-By: Rahul Kaushal --- fgmetric/collections/_counter_pivot_table.py | 7 ++++--- fgmetric/collections/_delimited_list.py | 3 ++- tests/test_collections.py | 9 ++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/fgmetric/collections/_counter_pivot_table.py b/fgmetric/collections/_counter_pivot_table.py index 7855521..1cfdbea 100644 --- a/fgmetric/collections/_counter_pivot_table.py +++ b/fgmetric/collections/_counter_pivot_table.py @@ -70,7 +70,7 @@ def _get_counter_fieldname(cls) -> str | None: if len(counter_fieldnames) > 1: raise TypeError( "Only one Counter per model is currently supported. " - f"Found multiple fields with Counter types: {', '.join(counter_fieldnames)}" + f"Found multiple Counter fields: {', '.join(counter_fieldnames)}" ) counter_fieldname: str | None = counter_fieldnames[0] if counter_fieldnames else None @@ -78,7 +78,7 @@ def _get_counter_fieldname(cls) -> str | None: if counter_fieldname: counter_field_info: FieldInfo = cls.model_fields[counter_fieldname] if is_optional(counter_field_info.annotation): - raise TypeError(f"Optional Counters are not supported: {counter_fieldname}") + raise TypeError(f"Optional Counter fields are not supported: '{counter_fieldname}'") return counter_fieldname @@ -109,7 +109,8 @@ def _get_counter_enum(cls) -> type[StrEnum] | None: # noqa: C901 enum_cls: type[StrEnum] = args[0] else: raise TypeError( - f"Counter fields must have a StrEnum type parameter: {cls._counter_fieldname}" + f"Counter fields must have a StrEnum type parameter," + f" got {info.annotation} for field '{cls._counter_fieldname}'" ) return enum_cls diff --git a/fgmetric/collections/_delimited_list.py b/fgmetric/collections/_delimited_list.py index 7977c17..2fabb60 100644 --- a/fgmetric/collections/_delimited_list.py +++ b/fgmetric/collections/_delimited_list.py @@ -101,7 +101,8 @@ def _require_single_character_collection_delimiter(cls) -> None: """Require collection delimiters to be single characters.""" if len(cls.collection_delimiter) != 1: raise ValueError( - f"Class collection delimiter must be a single character: {cls.collection_delimiter}" + "collection_delimiter must be a single character," + f" got: {cls.collection_delimiter!r}" ) @final diff --git a/tests/test_collections.py b/tests/test_collections.py index b5bd379..b142b11 100644 --- a/tests/test_collections.py +++ b/tests/test_collections.py @@ -258,7 +258,10 @@ class FakeMetric(Metric): name: str counts: Counter[str] - assert str(excinfo.value) == "Counter fields must have a StrEnum type parameter: counts" + assert str(excinfo.value) == ( + "Counter fields must have a StrEnum type parameter," + " got collections.Counter[str] for field 'counts'" + ) def test_counter_pivot_table_raises_if_multiple_counters() -> None: @@ -280,7 +283,7 @@ class FakeMetric(Metric): assert str(excinfo.value) == ( "Only one Counter per model is currently supported. " - "Found multiple fields with Counter types: foo_counts, bar_counts" + "Found multiple Counter fields: foo_counts, bar_counts" ) @@ -296,4 +299,4 @@ class FakeMetric(Metric): name: str counts: Counter[FakeEnum] | None - assert str(excinfo.value) == "Optional Counters are not supported: counts" + assert str(excinfo.value) == "Optional Counter fields are not supported: 'counts'"