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.
"""

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 ""


class PintError(Exception):
    """Base exception for all Pint errors."""


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__


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"
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__
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." ) 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." ) class UnitStrippedWarning(UserWarning, PintError): pass