Last active
October 19, 2023 09:51
-
-
Save Tishka17/d355f0d26b7563b8cd622d75f826e75c to your computer and use it in GitHub Desktop.
Error handling dock
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from enum import Enum | |
from logging import getLogger, basicConfig, INFO | |
from typing import Any, Optional | |
logger = getLogger(__name__) | |
class ErrorType(Enum): | |
def __add__(self, other): | |
return self | |
def __radd__(self, other): | |
return self.__add__(other) | |
class _ErrorDockLog: | |
def __init__(self, error_dock: "ErrorDock", logger_name: str): | |
self.error_dock = error_dock | |
self.logger_name = logger_name | |
def __enter__(self): | |
self.logger = self.error_dock.logger | |
self.error_dock.logger = getLogger(self.logger_name) | |
self.error_dock.__enter__() | |
def __exit__(self, exc_type, exc_val, exc_tb): | |
self.error_dock.__exit__(exc_type, exc_val, exc_tb) | |
self.error_dock.logger = self.logger | |
class ErrorDock: | |
def __init__(self): | |
self.status_stack = [None] | |
self.logger = logger | |
def error(self, text: str, *args: Any, error: Any = None) -> None: | |
self.logger.error(text, *args) | |
self._invalidate(error=error) | |
def __call__(self, name): | |
return _ErrorDockLog(self, name) | |
def __enter__(self): | |
self.status_stack.append(None) | |
return self | |
def _exception_error(self, exc_type, exc_val) -> Optional[ErrorType]: | |
return None | |
def __exit__(self, exc_type, exc_val, exc_tb): | |
status = self.status_stack.pop() | |
if exc_type: | |
status = self._exception_error(exc_type, exc_val) | |
self.status_stack[-1] += status | |
@property | |
def is_valid(self): | |
return not self.status_stack[-1] | |
@property | |
def current_error(self): | |
return self.status_stack[-1] | |
@property | |
def is_valid_all(self): | |
return not any(self.status_stack) | |
def _invalidate(self, error=True): | |
self.status_stack[-1] += error | |
class RealErrorType(ErrorType): | |
UNKNOWN = "UNKNOWN" | |
FORBIDDEN = "FORBIDDEN" | |
NOT_FOUND = "NOT_FOUND" | |
def __add__(self, other): | |
if self is RealErrorType.FORBIDDEN: | |
return self | |
if other is None: | |
return self | |
if self == other: | |
return self | |
return RealErrorType.UNKNOWN | |
class RealErrorDock(ErrorDock): | |
def forbidden(self): | |
self.error("Forbidden", error=RealErrorType.FORBIDDEN) | |
def not_found(self): | |
self.error("NotFound", error=RealErrorType.NOT_FOUND) | |
def _exception_error(self, exc_type, exc_val) -> Optional[ErrorType]: | |
return RealErrorType.UNKNOWN | |
basicConfig( | |
level=INFO, | |
format="%(asctime)s - %(levelname)s - %(name)s - %(message)s", | |
) | |
dock = RealErrorDock() | |
with dock("mylogger"): | |
dock.not_found() | |
with dock: | |
with dock("other_logger"): | |
dock.forbidden() | |
print("Error:", dock.current_error) | |
dock.not_found() | |
print("Error:", dock.current_error) | |
print("is_valid:", dock.is_valid) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment