Source code for pkgcore.config.errors

# potentially use an intermediate base for user config errors,
# separate base for instantiation?

"""Exceptions raised by the config code."""

__all__ = (
    "TypeDefinitionError",
    "ConfigurationError",
    "ParsingError",
    "CollapseInheritOnly",
    "ComplexInstantiationError",
    "QuoteInterpretationError",
)

from ..exceptions import PkgcoreException, PkgcoreUserException


def _identify_functor_source(functor):
    module = getattr(functor, "__module__", None)
    if module is None:
        return functor.__name__
    return f"{module}.{functor.__name__}"


class ConfigError(PkgcoreException):
    """Generic config exception."""


class UserConfigError(ConfigError, PkgcoreUserException):
    """Generic config exception with user relevant error."""


[docs] class TypeDefinitionError(ConfigError): """Fatal error in type construction."""
[docs] class ConfigurationError(ConfigError): """Fatal error in parsing a config section. :type stack: sequence of strings. :ivar stack: messages describing where this ConfigurationError originated. configuration-related code catching ConfigurationError that wants to raise its own ConfigurationError should modify (usually append to) the stack and then re-raise the original exception (this makes sure the traceback is preserved). """ def __init__(self, message): super().__init__(message) self.stack = [message] def __str__(self): return ":\n".join(reversed(self.stack))
[docs] class ParsingError(ConfigurationError, PkgcoreUserException): """Generic file parsing exception.""" def __init__(self, message=None, exception=None): if message is not None: super().__init__(message) elif exception is not None: super().__init__(str(exception)) else: raise ValueError("specify at least one of message and exception") self.message = message self.exc = exception def __str__(self): msg = f"parsing failed: {self.message}" if self.exc is not None: msg += f"\n{self.exc}" return msg
[docs] class CollapseInheritOnly(ConfigurationError): """Attempt was made to collapse an uncollapsable section. Separate exception because pconfig catches it separately. """
class InstantiationError(ConfigurationError): _txt = "Failed instantiating section %r%s" def __init__(self, section_name, message=None): self.section_name = section_name self.message = message def __str__(self): s = self.message if s is None: s = "" else: s = ": %s" % (s,) return self._txt % (self.section_name, s) class AutoloadInstantiationError(InstantiationError): _txt = "Failed loading autoload section %r%s"
[docs] class ComplexInstantiationError(ConfigurationError): """Exception occurred during instantiation. :ivar callable: callable object which failed during instantiation. :ivar pargs: positional args passed to callable. :ivar kwargs: keyword args passed to callable. :ivar exc: original exception object or None. A well-behaved configurable callable should raise this exception if instantiation failed, providing one or both of message and exception. The other fields will be filled in by central. If the callable raises something else central will wrap it in this, but that will lose the traceback. """ def __init__( self, message=None, exception=None, callable_obj=None, pargs=None, kwargs=None ): if message is not None: super().__init__(message) elif exception is not None: super().__init__(str(exception)) else: raise ValueError("specify at least one of message and exception") self.message = message self.callable = callable_obj self.pargs = pargs self.kwargs = kwargs self.exc = exception def __str__(self): # self.callable should be set here (nothing should try to catch # and str() this before central had a chance to fill it in) if self.message is not None: if self.callable is None: message = f"{self.message!r}, callable unset!" else: message = ( f"{self.message!r} instantiating " f"{self.callable.__module__}.{self.callable.__name__}" ) # The weird repr(str(exc)) used here quotes the message nicely. elif self.callable is not None: message = ( f"Caught exception {str(self.exc)!r} " f"instantiating {self.callable.__module__}.{self.callable.__name__}" ) else: message = f"Caught exception {str(self.exc)!r}, callable unset!" return ":\n".join(reversed([message] + self.stack[1:]))
[docs] class QuoteInterpretationError(ConfigurationError): """Quoting of a var was screwed up.""" def __init__(self, string): super().__init__(f"parsing of {string!r} failed") self.str = string