Skip to content

Instantly share code, notes, and snippets.

@Tishka17
Last active October 19, 2023 09:51
Show Gist options
  • Save Tishka17/d355f0d26b7563b8cd622d75f826e75c to your computer and use it in GitHub Desktop.
Save Tishka17/d355f0d26b7563b8cd622d75f826e75c to your computer and use it in GitHub Desktop.
Error handling dock
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