Skip to content

math_spec.errors

What the language says back about a file: the errors it raises, and the advice it gives.

ADVICE_KINDS = frozenset(get_args(AdviceKind)) module-attribute #

AdviceKind = Literal['never-an-axis', 'unbounded'] module-attribute #

Advice(kind, subject, text) dataclass #

One thing the language advises about a file it accepts.

Never an error: each is what a half-written model looks like too. A consumer prints it, or filters on kind and subject; the text is the language's, so no consumer writes its own.

ATTRIBUTE DESCRIPTION
kind

The pass that said it.

TYPE: AdviceKind

subject

The declaration it is about — a dimension name, a variable name.

TYPE: str

text

The sentence, naming the rewrite.

TYPE: str

kind instance-attribute #

subject instance-attribute #

text instance-attribute #

DimensionError #

Bases: LanguageError

A dim-set rule was violated. Raised at load time, before any data.

LanguageError #

Bases: MathSpecError

The model is not sayable in the language, or does not obey its rules.

MathSpecError #

Bases: ValueError

Base class for every error this package raises on purpose.

PiecewiseExpansionError #

Bases: LanguageError

A piecewise block references something that doesn't exist or collides.

SchemaError #

Bases: LanguageError

What a load refuses: an unknown key, a bad dtype, a duplicate YAML key, an unparseable or unresolvable expression.

did_you_mean(name, known, *, label='Declared') #

The repair clause for an unrecognised name: the near miss, or the set.

Source code in src/math_spec/errors.py
def did_you_mean(name: str, known: Iterable[str], *, label: str = 'Declared') -> str:
    """The repair clause for an unrecognised name: the near miss, or the set."""
    candidates = sorted(known)
    near = difflib.get_close_matches(name, candidates, n=1, cutoff=0.6)
    if near:
        return f"Did you mean '{near[0]}'?"
    return f'{label}: {", ".join(candidates) or "nothing"}.'

schema_error(exc) #

A pydantic ValidationError as one of ours.

Returns the original :class:LanguageError subclass where exactly one error carries one, and a :class:SchemaError otherwise.

Source code in src/math_spec/errors.py
def schema_error(exc: ValidationError) -> LanguageError:
    """A pydantic ``ValidationError`` as one of ours.

    Returns the original :class:`LanguageError` subclass where exactly one
    error carries one, and a :class:`SchemaError` otherwise.
    """
    errors = exc.errors()
    lines = []
    for error in errors:
        message = error.get('msg', '').removeprefix('Value error, ')
        where = '.'.join(str(part) for part in error.get('loc', ()))
        lines.append(f'{where}: {message}' if where else message)
    text = '\n'.join(lines) or str(exc)

    if len(errors) == 1:
        original = errors[0].get('ctx', {}).get('error')
        if isinstance(original, LanguageError):
            return type(original)(text)
    return SchemaError(text)