Source code for pint.errors

"""
    pint.errors
    ~~~~~~~~~~~

    Functions and classes related to unit definitions and conversions.

    :copyright: 2016 by Pint Authors, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
"""

from __future__ import annotations

OFFSET_ERROR_DOCS_HTML = "https://pint.readthedocs.io/en/latest/nonmult.html"
LOG_ERROR_DOCS_HTML = "https://pint.readthedocs.io/en/latest/nonmult.html"


def _file_prefix(filename=None, lineno=None):
    if filename and lineno is not None:
        return f"While opening {filename}, in line {lineno}: "
    elif filename:
        return f"While opening {filename}: "
    elif lineno is not None:
        return f"In line {lineno}: "
    else:
        return ""


[docs]class PintError(Exception): """Base exception for all Pint errors."""
[docs]class DefinitionSyntaxError(SyntaxError, PintError): """Raised when a textual definition has a syntax error.""" def __init__(self, msg, *, filename=None, lineno=None): super().__init__(msg) self.filename = filename self.lineno = lineno def __str__(self): return _file_prefix(self.filename, self.lineno) + str(self.args[0]) @property def __dict__(self): # SyntaxError.filename and lineno are special fields that don't appear in # the __dict__. This messes up pickling and deepcopy, as well # as any other Python library that expects sane behaviour. return {"filename": self.filename, "lineno": self.lineno} def __reduce__(self): return DefinitionSyntaxError, self.args, self.__dict__
[docs]class RedefinitionError(ValueError, PintError): """Raised when a unit or prefix is redefined.""" def __init__(self, name, definition_type, *, filename=None, lineno=None): super().__init__(name, definition_type) self.filename = filename self.lineno = lineno def __str__(self): msg = f"Cannot redefine '{self.args[0]}' ({self.args[1]})" return _file_prefix(self.filename, self.lineno) + msg def __reduce__(self): return RedefinitionError, self.args, self.__dict__
[docs]class UndefinedUnitError(AttributeError, PintError): """Raised when the units are not defined in the unit registry.""" def __init__(self, *unit_names): if len(unit_names) == 1 and not isinstance(unit_names[0], str): unit_names = unit_names[0] super().__init__(*unit_names) def __str__(self): if len(self.args) == 1: return f"'{self.args[0]}' is not defined in the unit registry" return f"{self.args} are not defined in the unit registry"
[docs]class PintTypeError(TypeError, PintError): pass
[docs]class DimensionalityError(PintTypeError): """Raised when trying to convert between incompatible units.""" def __init__(self, units1, units2, dim1="", dim2="", *, extra_msg=""): super().__init__() self.units1 = units1 self.units2 = units2 self.dim1 = dim1 self.dim2 = dim2 self.extra_msg = extra_msg def __str__(self): if self.dim1 or self.dim2: dim1 = f" ({self.dim1})" dim2 = f" ({self.dim2})" else: dim1 = "" dim2 = "" return ( f"Cannot convert from '{self.units1}'{dim1} to " f"'{self.units2}'{dim2}{self.extra_msg}" ) def __reduce__(self): return TypeError.__new__, (DimensionalityError,), self.__dict__
[docs]class OffsetUnitCalculusError(PintTypeError): """Raised on ambiguous operations with offset units.""" def __str__(self): return ( "Ambiguous operation with offset unit (%s)." % ", ".join(str(u) for u in self.args) + " See " + OFFSET_ERROR_DOCS_HTML + " for guidance." )
[docs]class LogarithmicUnitCalculusError(PintTypeError): """Raised on inappropriate operations with logarithmic units.""" def __str__(self): return ( "Ambiguous operation with logarithmic unit (%s)." % ", ".join(str(u) for u in self.args) + " See " + LOG_ERROR_DOCS_HTML + " for guidance." )
[docs]class UnitStrippedWarning(UserWarning, PintError): pass