prepare results wrapping for error handling architecture
This commit is contained in:
@@ -1,13 +1,19 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any, Final
|
||||
import typing as t
|
||||
from collections.abc import Callable
|
||||
from functools import wraps
|
||||
from typing import Any, Final
|
||||
|
||||
from delta_barth.constants import DEFAULT_API_ERR_CODE, DEFAULT_INTERNAL_ERR_CODE
|
||||
from delta_barth.types import DataPipeStates, Status
|
||||
|
||||
if TYPE_CHECKING:
|
||||
if t.TYPE_CHECKING:
|
||||
from delta_barth.types import DelBarApiError, StatusDescription
|
||||
|
||||
P = t.ParamSpec("P")
|
||||
T = t.TypeVar("T")
|
||||
|
||||
|
||||
class UnspecifiedRequestType(Exception):
|
||||
"""exception raised if for a given API endpoint a not defined operation is requested"""
|
||||
@@ -21,6 +27,12 @@ class FeaturesMissingError(Exception):
|
||||
"""exception raised if needed features are missing"""
|
||||
|
||||
|
||||
# ** Exceptions for result wrappers
|
||||
class WAccessResultDespiteError(Exception):
|
||||
"""wrapped results exception: raised if result is accessed, even though
|
||||
there was an error in the underlying procedure"""
|
||||
|
||||
|
||||
# ** Exceptions for unwrap of error value
|
||||
class UDataProcessingError(Exception):
|
||||
"""unwrap exception: all data related errors (e.g. wrong format, non-sufficient quality)"""
|
||||
@@ -88,8 +100,17 @@ class StatusHandler:
|
||||
|
||||
self._pipe_states = DataPipeStates(**parsed_errors)
|
||||
|
||||
def error(
|
||||
def exception_to_error(
|
||||
self,
|
||||
exception: Exception,
|
||||
code: int = DEFAULT_INTERNAL_ERR_CODE,
|
||||
) -> Status:
|
||||
description = exception.__class__.__name__
|
||||
message = str(exception)
|
||||
return self.error(description, message, code)
|
||||
|
||||
@staticmethod
|
||||
def error(
|
||||
description: str,
|
||||
message: str = "",
|
||||
code: int = DEFAULT_INTERNAL_ERR_CODE,
|
||||
@@ -108,8 +129,8 @@ class StatusHandler:
|
||||
message=message,
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def api_error(
|
||||
self,
|
||||
error: DelBarApiError,
|
||||
) -> Status:
|
||||
description = "Es ist ein Fehler bei der Kommunikation mit dem API-Server aufgetreten"
|
||||
@@ -148,3 +169,68 @@ class StatusHandler:
|
||||
|
||||
|
||||
STATUS_HANDLER: Final[StatusHandler] = StatusHandler()
|
||||
|
||||
|
||||
# ** result wrapping
|
||||
class NotSet:
|
||||
__slots__ = tuple()
|
||||
|
||||
def __init__(self) -> None: ...
|
||||
|
||||
def __str__(self) -> str:
|
||||
return ">Not set<"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return f"{self.__class__.__name__}()"
|
||||
|
||||
|
||||
class ResultWrapper(t.Generic[T]):
|
||||
def __init__(
|
||||
self,
|
||||
result: T | NotSet,
|
||||
exception: Exception | None,
|
||||
code_on_error: int,
|
||||
) -> None:
|
||||
self._result = result
|
||||
status: Status = STATUS_HANDLER.SUCCESS
|
||||
if exception is not None:
|
||||
status = STATUS_HANDLER.exception_to_error(exception, code=code_on_error)
|
||||
self.status = status
|
||||
|
||||
@property
|
||||
def result(self) -> T:
|
||||
if isinstance(self._result, NotSet):
|
||||
raise WAccessResultDespiteError(
|
||||
"Can not access result because an error occurred during procedure"
|
||||
)
|
||||
return self._result
|
||||
|
||||
def __str__(self) -> str:
|
||||
return f"Status(result: {self._result}, status: {self.status})"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
return self.__str__()
|
||||
|
||||
|
||||
def wrap_result(
|
||||
code_on_error: int = DEFAULT_API_ERR_CODE,
|
||||
) -> Callable[[Callable[P, T]], Callable[P, ResultWrapper[T]]]:
|
||||
def wrap_result(func: Callable[P, T]) -> Callable[P, ResultWrapper[T]]:
|
||||
@wraps(func)
|
||||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> ResultWrapper[T]:
|
||||
status: ResultWrapper[T]
|
||||
try:
|
||||
res = func(*args, **kwargs)
|
||||
status = ResultWrapper(
|
||||
result=res, exception=None, code_on_error=code_on_error
|
||||
)
|
||||
except Exception as err:
|
||||
status = ResultWrapper(
|
||||
result=NotSet(), exception=err, code_on_error=code_on_error
|
||||
)
|
||||
|
||||
return status
|
||||
|
||||
return wrapper
|
||||
|
||||
return wrap_result
|
||||
|
||||
Reference in New Issue
Block a user