Skip to content

Commit

Permalink
4.1.5
Browse files Browse the repository at this point in the history
1.Improve the `logger` parameter to support custom loggers.
2.Correct multiple descriptive errors.

1.改进 `logger` 参数以支持自定义日志记录器。
2.更正多处描述性错误。
  • Loading branch information
2018-11-27 committed Oct 12, 2024
1 parent 84c25e4 commit bb8be31
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 49 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
[<img alt="LOGO" src="https://python.org/favicon.ico" height="21" width="21"/>](http://gqylpy.com)
[![Release](https://img.shields.io/github/release/gqylpy/exceptionx.svg?style=flat-square")](https://github.com/gqylpy/exceptionx/releases/latest)
[![Python Versions](https://img.shields.io/pypi/pyversions/exceptionx)](https://pypi.org/project/exceptionx)
[![License](https://img.shields.io/pypi/l/exceptionx)](https://github.com/gqylpy/exceptionx/blob/master/LICENSE)
[![License](https://img.shields.io/pypi/l/exceptionx)](https://github.com/gqylpy/exceptionx/blob/main/LICENSE)
[![Downloads](https://static.pepy.tech/badge/exceptionx)](https://pepy.tech/project/exceptionx)

# exceptionx
English | [中文](https://github.com/gqylpy/exceptionx/blob/master/README_CN.md)
English | [中文](https://github.com/gqylpy/exceptionx/blob/main/README_CN.md)

__exceptionx__ is a flexible and convenient Python exception handling library that allows you to dynamically create exception classes and provides various exception handling mechanisms.
> The predecessor of exceptionx is [gqylpy-exception](https://github.com/gqylpy/gqylpy-exception).
Expand Down
2 changes: 1 addition & 1 deletion README_CN.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[<img alt="LOGO" src="https://python.org/favicon.ico" height="21" width="21"/>](http://gqylpy.com)
[![Release](https://img.shields.io/github/release/gqylpy/exceptionx.svg?style=flat-square")](https://github.com/gqylpy/exceptionx/releases/latest)
[![Python Versions](https://img.shields.io/pypi/pyversions/exceptionx)](https://pypi.org/project/exceptionx)
[![License](https://img.shields.io/pypi/l/exceptionx)](https://github.com/gqylpy/exceptionx/blob/master/LICENSE)
[![License](https://img.shields.io/pypi/l/exceptionx)](https://github.com/gqylpy/exceptionx/blob/main/LICENSE)
[![Downloads](https://static.pepy.tech/badge/exceptionx)](https://pepy.tech/project/exceptionx)

# exceptionx
Expand Down
53 changes: 30 additions & 23 deletions exceptionx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,32 @@
import sys
import typing

from typing import Type, TypeVar, Optional, Union, Tuple, Dict, Callable, Any
from typing import Type, TypeVar, Protocol, Optional, Tuple, Dict, Callable, Any

if sys.version_info >= (3, 10):
from typing import TypeAlias
else:
TypeAlias = TypeVar('TypeAlias')

if typing.TYPE_CHECKING:
import logging
import threading


class HasWarningMethod(Protocol):
def warning(self, msg: Any): ...


class HasErrorMethod(Protocol):
def error(self, msg: Any): ...


ETypes: TypeAlias = \
TypeVar('ETypes', Type[Exception], Tuple[Type[Exception], ...])

ELogger: TypeAlias = TypeVar('ELogger', 'logging.Logger', 'gqylpy_log')
ECallback: TypeAlias = TypeVar('ECallback', bound=Callable[..., None])

WrappedClosure: TypeAlias = TypeVar('WrappedClosure', bound=Callable[..., Any])
Second: TypeAlias = TypeVar('Second', bound=Union[int, float, str])
Second: TypeAlias = TypeVar('Second', int, float, str)


class Error(Exception):
Expand Down Expand Up @@ -96,15 +103,15 @@ def __getattr__(ename: str, /) -> Type[Error]:
def TryExcept(
etype: ETypes,
/, *,
emsg: Optional[str] = None,
silent: Optional[bool] = None,
raw: Optional[bool] = None,
invert: Optional[bool] = None,
last_tb: Optional[bool] = None,
logger: Optional[ELogger] = None,
ereturn: Optional[Any] = None,
ecallback: Optional[ECallback] = None,
eexit: Optional[bool] = None
emsg: Optional[str] = None,
silent: Optional[bool] = None,
raw: Optional[bool] = None,
invert: Optional[bool] = None,
last_tb: Optional[bool] = None,
logger: Optional[HasErrorMethod] = None,
ereturn: Optional[Any] = None,
ecallback: Optional[ECallback] = None,
eexit: Optional[bool] = None
) -> WrappedClosure:
"""
`TryExcept` is a decorator that handles exceptions raised by the function it
Expand Down Expand Up @@ -177,7 +184,7 @@ def Retry(
raw: Optional[bool] = None,
invert: Optional[bool] = None,
last_tb: Optional[bool] = None,
logger: Optional[ELogger] = None
logger: Optional[HasWarningMethod] = None
) -> WrappedClosure:
"""
`Retry` is a decorator that retries exceptions raised by the function it
Expand Down Expand Up @@ -260,17 +267,17 @@ def Retry(
def TryContext(
etype: ETypes,
/, *,
emsg: Optional[str] = None,
silent: Optional[bool] = None,
raw: Optional[bool] = None,
invert: Optional[bool] = None,
last_tb: Optional[bool] = None,
logger: Optional[ELogger] = None,
ecallback: Optional[ECallback] = None,
eexit: Optional[bool] = None
emsg: Optional[str] = None,
silent: Optional[bool] = None,
raw: Optional[bool] = None,
invert: Optional[bool] = None,
last_tb: Optional[bool] = None,
logger: Optional[HasErrorMethod] = None,
ecallback: Optional[ECallback] = None,
eexit: Optional[bool] = None
) -> None:
"""
TryContext is a context manager that handles exceptions raised within the
`TryContext` is a context manager that handles exceptions raised within the
context.
>>> with TryContext(ValueError):
Expand Down
55 changes: 33 additions & 22 deletions exceptionx/i exceptionx.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@
from contextlib import contextmanager

from types import FrameType, TracebackType
from typing import \
TypeVar, Type, Final, Optional, Union, Tuple, Callable, NoReturn, Any

from typing import (
Type, TypeVar, Final, Protocol, Optional, Union, Tuple, Callable, NoReturn,
Any
)

if sys.version_info >= (3, 9):
from typing import Annotated
Expand All @@ -29,14 +32,22 @@ def __getitem__(self, *a): ...
else:
TypeAlias = TypeVar('TypeAlias')


class HasWarningMethod(Protocol):
def warning(self, msg: Any): ...


class HasErrorMethod(Protocol):
def error(self, msg: Any): ...


Wrapped = WrappedClosure = TypeVar('Wrapped', bound=Callable[..., Any])
WrappedReturn: TypeAlias = TypeVar('WrappedReturn')

ETypes: TypeAlias = Union[Type[Exception], Tuple[Type[Exception], ...]]
ELogger: TypeAlias = Union[logging.Logger, 'gqylpy_log']
ETypes: TypeAlias = Union[Type[Exception], Tuple[Type[Exception], ...]]
ELogger: TypeAlias = Union[HasWarningMethod, HasErrorMethod]
ECallback: TypeAlias = Callable[..., None]

Second: TypeAlias = TypeVar('Second', bound=Union[int, float, str])
Second: TypeAlias = Union[int, float, str]

UNIQUE: Final[Annotated[object, 'A unique object.']] = object()

Expand Down Expand Up @@ -506,29 +517,29 @@ def get_logger(logger: logging.Logger) -> Callable[[str], None]:
if logger is None:
return stderr

is_glog_module: bool = getattr(logger, '__package__', None) == 'gqylpy_log'

if not (isinstance(logger, logging.Logger) or is_glog_module):
raise ValueError(
'parameter "logger" must be an instance of "logging.Logger", '
f'not "{logger.__class__.__name__}".'
)

previous_frame: FrameType = sys._getframe(1)

if previous_frame.f_back.f_code is Retry.__init__.__code__:
caller = logger.warning
name = 'warning'
else:
caller = logger.error
name = 'error'

if previous_frame.f_code is TryContext.__wrapped__.__code__:
stacklevel = 3
else:
if not ((method := getattr(logger, name, None)) and callable(method)):
raise __getattr__('ParameterError')(
f'parameter "logger" must have a "{name}" method.'
)

if isinstance(logger, logging.Logger):
stacklevel = 4
if is_glog_module:
stacklevel += 1
elif getattr(logger, '__package__', None) == 'gqylpy_log':
stacklevel = 5
else:
return method

if previous_frame.f_code is TryContext.__wrapped__.__code__:
stacklevel -= 1

return functools.partial(caller, stacklevel=stacklevel)
return functools.partial(method, stacklevel=stacklevel)


def get_einfo(e: Exception, /, *, raw: bool, last_tb: bool) -> str:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setuptools.setup(
name='exceptionx',
version='4.1.4',
version='4.1.5',
author='Unnamed great master',
author_email='<gqylpy@outlook.com>',
license='MIT',
Expand Down

0 comments on commit bb8be31

Please sign in to comment.