Source code for _delb.exceptions
# Copyright (C) 2018-'25 Frank Sachsenheim
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
"""These are the specific delb exceptions."""
from __future__ import annotations
from typing import Optional, TYPE_CHECKING, Any, Final
if TYPE_CHECKING:
from _delb.typing import Loader
[docs]
class DelbBaseException(Exception):
"""Base class for all of delb's exceptions."""
pass
[docs]
class AmbiguousTreeError(DelbBaseException):
"""
Raised when a single node shall be fetched or created by an XPath expression in a
tree where the target position can't be clearly determined.
"""
def __init__(self, message: str):
super().__init__(message)
[docs]
class FailedDocumentLoading(DelbBaseException):
def __init__(self, source: Any, excuses: dict[Loader, str | Exception]):
self.source: Final = source
self.excuses: Final = excuses
def __str__(self): # pragma: no cover
return f"Couldn't load {self.source!r} with these loaders: {self.excuses}"
[docs]
class InvalidCodePath(DelbBaseException, RuntimeError):
"""Raised when a code path that is not expected to be executed is reached."""
def __init__(self): # pragma: no cover
super().__init__(
"An unintended path was taken through the code. Please report this bug."
)
[docs]
class InvalidOperation(DelbBaseException):
"""Raised when an invalid operation is attempted by the client code."""
pass
[docs]
class ParsingError(DelbBaseException):
"""Base class for parsing related exceptions."""
pass
[docs]
class ParsingProcessingError(ParsingError):
"""Raised when a parsing operation cannot proceed in the actual context."""
pass
[docs]
class ParsingValidityError(ParsingError):
"""Raised non-well-formed phenomena are encountered."""
pass
[docs]
class XPathEvaluationError(DelbBaseException):
"""Raised when an XPath expression can't be properly evaluated."""
def __init__(self, message: str):
super().__init__(message)
[docs]
class XPathParsingError(DelbBaseException):
"""Raised when an XPath expression can't be parsed."""
def __init__(
self,
expression: Optional[str] = None,
position: Optional[int] = None,
message: Optional[str] = None,
):
self.expression = expression
self.position = position
self.message: Final = message
def __str__(self):
expression = self.expression
position = self.position
assert expression is not None
assert self.message is not None
assert position is not None
expression_length = len(expression)
snippet_end = min(position + 16, expression_length)
if expression_length > snippet_end:
snippet = f"`{expression[position:snippet_end]}…`"
else:
snippet = f"`{expression[position:snippet_end]}`"
if len(snippet) > 2:
return (
f"XPath parsing error at character {position} ({snippet}): "
f"{self.message}"
)
else:
return f"XPath parsing error at character {position}: {self.message}"
[docs]
class XPathUnsupportedStandardFeature(XPathParsingError):
"""Raised when an unsupported XPath expression feature is recognized."""
def __init__(self, position: int, feature_description: str):
super().__init__(
position=position,
message=f"{feature_description} is not supported with intention. "
"Please consult the documentation regarding the XPath implementation.",
)
__all__ = (
AmbiguousTreeError.__name__,
DelbBaseException.__name__,
FailedDocumentLoading.__name__,
InvalidCodePath.__name__,
InvalidOperation.__name__,
ParsingError.__name__,
ParsingProcessingError.__name__,
ParsingValidityError.__name__,
XPathEvaluationError.__name__,
XPathParsingError.__name__,
XPathUnsupportedStandardFeature.__name__,
)