diff --git a/src/labapi/util/extract.py b/src/labapi/util/extract.py index 939fe12..7ed232b 100644 --- a/src/labapi/util/extract.py +++ b/src/labapi/util/extract.py @@ -118,8 +118,9 @@ def extract_etree(_etree: Element, schema: EtreeExtractorDict) -> dict[str, Any] try: items[leaf] = mapper(value) except ValueError as err: + mapper_name = getattr(mapper, "__name__", repr(mapper)) raise ExtractionError( - f"Could not map value {value!r} with {mapper.__name__} for " + f"Could not map value {value!r} with {mapper_name} for " f"{message_path!r} while parsing element at {etree_path}" ) from err diff --git a/tests/util/test_extract.py b/tests/util/test_extract.py index b5df0f0..cfaae73 100644 --- a/tests/util/test_extract.py +++ b/tests/util/test_extract.py @@ -225,6 +225,31 @@ def test_extract_etree_mapper_fails_raises(): extract_etree(element, format_dict) +def test_extract_etree_mapper_without_name_raises(): + """Test extract_etree raises ExtractionError properly when mapper has no __name__.""" + from functools import partial + + xml = """ + + not_an_int + + """ + element = etree.fromstring(bytes(xml, encoding="utf-8")) + mapper = partial(int, base=16) + format_dict: EtreeExtractorDict = { + "value": mapper, + } + + with pytest.raises( + ExtractionError, + match=( + r"Could not map value 'not_an_int' with .*partial.* for '.+/value' while " + r"parsing element at /root" + ), + ): + extract_etree(element, format_dict) + + def test_extract_etree_warns_on_duplicate_leaf_names(): """Test duplicate leaf extraction warns and last assignment wins.""" xml = """