"""Mapping errors."""
from typing import Any as _Any
[docs]
class MappingError(Exception):
"""Base exception class for all mapping-related issues."""
def __init__(self, msg: str, *, ref: str = "") -> None:
super().__init__(msg)
link = "https://id-translation.readthedocs.io/en/stable/documentation/mapping-primer.html"
if ref:
link += f"#{ref}"
self.add_note(f"Hint: See {link} for help.")
func = "id_translation.logging.enable_verbose_debug_messages"
if __debug__:
from id_translation.logging import enable_verbose_debug_messages # noqa: PLC0415
expected = enable_verbose_debug_messages.__module__ + "." + enable_verbose_debug_messages.__name__
assert func == expected # noqa: S101
self.add_note(f"Hint: Use `{func}` for detailed output.")
[docs]
class UnmappedValuesError(MappingError):
"""Raised when there are unmapped values left after filtering and on_unmapped='raise'."""
[docs]
class UnmappedExplicitNamesError(MappingError): # TODO(2.0.0): Inherit from UnmappedValuesError.
"""Raised when names explicitly provided by the user could not be mapped."""
def __init__(self, msg: str, *, names: list[_Any], unmapped: set[_Any]) -> None:
super().__init__(msg)
self.names = names
self.unmapped = unmapped
self.add_note("Note: This error is NOT controlled by the `Mapper.on_unmapped` property.")
self.add_note(f"Hint: Remove {len(unmapped)} unmapped name(s) from the provided {names=} to continue.")
[docs]
class ScoringDisabledError(MappingError):
"""Indicates that the scoring logic has been disabled. Raised by :func:`.score_functions.disabled`."""
def __init__(self, value: _Any, candidates: _Any, context: _Any) -> None:
super().__init__(
"Scoring disabled.\n"
f"The Mapper is working in strict override-only mode, so the {value=} in {context=} "
f"cannot be mapped to any of the {candidates=}. Possible solutions:\n"
" * Add an override or filter for this value, or\n"
" * Set strict=False (silently refuse to map instead of raising), or\n"
" * Choose an appropriate score function to use.",
ref="override-only-mapping",
)
self.value = value
self.candidates = candidates
self.context = context
[docs]
class AmbiguousScoreError(MappingError):
"""Indicates that the scoring logic has produces ambiguous scores."""
def __init__(self, kind: str, key: _Any, match0: _Any, match1: _Any, cardinality: str, scores: str) -> None:
hint = f"\n{scores}\nInspect the matrix above for details. You may wish to use a different scoring method."
super().__init__(
f"Ambiguous mapping of {kind}={key!r}; matches ({match0}) and ({match1}) "
f"are in conflict since {cardinality=}.{hint}"
)
[docs]
class UserMappingError(MappingError):
"""A user-defined mapping function did something forbidden."""
def __init__(self, msg: str, value: _Any, candidates: set[_Any]) -> None:
super().__init__(msg)
self.value = value
self.candidates = candidates
[docs]
class CardinalityError(MappingError):
"""Base class for cardinality issues."""
[docs]
class MappingWarning(UserWarning):
"""Base warning class for all mapping-related issues."""
[docs]
class UnmappedValuesWarning(MappingWarning):
"""Raised when there are unmapped values left after filtering and on_unmapped='raise'."""
[docs]
class UserMappingWarning(MappingWarning):
"""A user-defined mapping function did something strange."""
[docs]
class BadFilterError(MappingError):
"""Invalid filter."""