Skip to content

Commit eb01705

Browse files
committed
Fixed supress warning problems
1 parent 3557688 commit eb01705

File tree

2 files changed

+64
-85
lines changed

2 files changed

+64
-85
lines changed

classmods/_decorators.py

Lines changed: 48 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import logging
22
from functools import wraps
3-
from typing import Callable, Literal, Optional, ParamSpec, Tuple, TypeAlias, TypeVar, Union, overload
3+
from typing import Any, Callable, Literal, Optional, ParamSpec, Tuple, Type, TypeAlias, TypeVar, Union, overload
44

55
LOG_LEVEL: TypeAlias = Literal['CRITICAL', 'ERROR', 'WARNING', 'INFO', 'DEBUG', 'NOTSET', 'DEFAULT']
66

77
P = ParamSpec("P")
88
R = TypeVar("R")
9+
T = TypeVar("T")
910

1011
def logwrap(
1112
before: Optional[Tuple[LOG_LEVEL, str]] | str | bool = None,
@@ -33,25 +34,25 @@ def logwrap(
3334
after: Tuple of log level and message to log after function call or string with default of `INFO` level.
3435
3536
Examples:
36-
>>> @logwrap(before=('INFO', '{func} starting, args={args} kwargs={kwargs}'), after=('INFO', '{func} ended'))
37-
... def my_func(my_arg, my_kwarg=None):
38-
... ...
39-
... my_func('hello', my_kwarg=123)
40-
Info - my_func Starting, args=('hello',), kwargs={'my_kwarg': 123}
41-
Info - my_func Ended
42-
43-
>>> @logwrap(before=True, after=True)
44-
... def my_new_func():
45-
... ...
46-
... my_new_func()
47-
Debug - Calling my_new_func - args:(), kwargs:{}
48-
Info - Function my_new_func ended
49-
50-
>>> @logwrap(on_exception=True)
51-
... def error_func():
52-
... raise Exception('My exception msg')
53-
... error_func()
54-
Error - Error on error_func: My exception msg
37+
>>> @logwrap(before=('INFO', '{func} starting, args={args} kwargs={kwargs}'), after=('INFO', '{func} ended'))
38+
... def my_func(my_arg, my_kwarg=None):
39+
... ...
40+
... my_func('hello', my_kwarg=123)
41+
Info - my_func Starting, args=('hello',), kwargs={'my_kwarg': 123}
42+
Info - my_func Ended
43+
44+
>>> @logwrap(before=True, after=True)
45+
... def my_new_func():
46+
... ...
47+
... my_new_func()
48+
Debug - Calling my_new_func - args:(), kwargs:{}
49+
Info - Function my_new_func ended
50+
51+
>>> @logwrap(on_exception=True)
52+
... def error_func():
53+
... raise Exception('My exception msg')
54+
... error_func()
55+
Error - Error on error_func: My exception msg
5556
"""
5657
def normalize(
5758
default_level: LOG_LEVEL,
@@ -121,75 +122,49 @@ def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
121122

122123

123124
@overload
124-
def suppress_errors(mode: Literal["exception"]) -> Callable[[Callable[..., R]], Callable[..., Union[R, Exception]]]: ...
125+
def suppress_errors(fallback: type[Exception]) -> Callable[[Callable[..., R]], Callable[..., Union[R, Exception]]]: ...
125126
@overload
126-
def suppress_errors(mode: Literal["true"]) -> Callable[[Callable[..., R]], Callable[..., Union[R, Literal[True]]]]: ...
127-
@overload
128-
def suppress_errors(mode: Literal["false"]) -> Callable[[Callable[..., R]], Callable[..., Union[R, Literal[False]]]]: ...
129-
@overload
130-
def suppress_errors(mode: Literal["exception", "true", "false"]): ...
131-
def suppress_errors(
132-
mode: Literal["exception", "true", "false"]
133-
) -> Callable[
134-
[Callable[..., R]],
135-
Callable[..., Union[R, bool, Exception]]
136-
]:
127+
def suppress_errors(fallback: T) -> Callable[[Callable[..., R]], Callable[..., Union[R, T]]]: ...
128+
129+
def suppress_errors(fallback: Any) -> Callable[[Callable[..., R]], Callable[..., Union[R, Any]]]:
137130
"""
138131
A decorator that suppresses exceptions raised by the wrapped function and returns
139-
a fallback value instead, based on the selected mode.
140-
141-
This decorator is useful when you want to avoid raising exceptions and handle errors
142-
gracefully by returning a consistent fallback value.
132+
a fallback value instead.
143133
144134
Parameters:
145-
mode (Literal["true", "false", "exception"]): Determines what to return when an exception is caught.
146-
- "true": Returns `True` if an exception occurs.
147-
- "false": Returns `False` if an exception occurs.
148-
- "exception": Returns the caught exception object instead of raising it.
135+
fallback: Determines what to return when an exception is caught.
136+
- Exception class (like Exception): Returns the caught exception object
137+
- Any other value: Returns that value when exception occurs
149138
150139
Returns:
151-
Callable: A decorated version of the original function, with modified error behavior.
152-
The return type becomes a union of the original return type and the fallback.
140+
Callable: A decorated version of the original function that returns either:
141+
- The original return value, or
142+
- The fallback value/exception
153143
154144
Example:
155-
>>> @suppress_exception("exception")
156-
... def is_connected() -> bool:
157-
... socket.sendall(b'', MSG_DONTWAIT)
158-
... return True
159-
>>> is_connected()
160-
OSError(...)
161-
162-
>>> @suppress_exception("true")
163-
... def has_problems() -> bool:
164-
... device.test_connection()
165-
... return false
166-
>>> has_problems()
167-
True
168-
169-
>>> @suppress_exception("false")
170-
... def is_connected() -> bool:
171-
... socket.sendall(b'', MSG_DONTWAIT)
172-
... return True
173-
>>> is_connected()
174-
True
145+
>>> @suppress_errors(Exception)
146+
... def risky_op() -> int:
147+
... return 1 / 0
148+
>>> result = risky_op() # Returns ZeroDivisionError
149+
150+
>>> @suppress_errors(False)
151+
... def safe_op() -> bool:
152+
... raise ValueError("error")
153+
>>> result = safe_op() # Returns False
175154
176155
Notes:
177156
- Only standard Python exceptions (derived from `Exception`) are caught.
178157
- Does not suppress `KeyboardInterrupt`, `SystemExit`, or `GeneratorExit`.
179158
- The decorator preserves the original function's metadata (name, docstring, etc.).
180-
181-
Raises:
182-
ValueError: If the provided mode is not one of the allowed values.
183159
"""
184-
def decorator(func: Callable[..., R]) -> Callable[..., Union[R, bool, Exception]]:
160+
def decorator(func: Callable[..., R]) -> Callable[..., Union[R, Any]]:
185161
@wraps(func)
186-
def wrapper(*args, **kwargs):
187-
try: return func(*args, **kwargs)
162+
def wrapper(*args: Any, **kwargs: Any) -> Union[R, Any]:
163+
try:
164+
return func(*args, **kwargs)
188165
except Exception as e:
189-
if mode == "exception": return e
190-
elif mode == "true": return True
191-
elif mode == "false": return False
192-
else: raise ValueError(f"Invalid mode: {mode}")
193-
166+
if fallback is Exception:
167+
return e
168+
return fallback
194169
return wrapper
195170
return decorator

test/test_decorators.py

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,30 @@
11
from classmods import suppress_errors
22

3-
@suppress_errors('exception')
4-
def return_exception() -> bool:
3+
@suppress_errors(Exception)
4+
def return_exception():
55
raise Exception('This is test Error')
66

7-
@suppress_errors('true')
8-
def return_true() -> bool:
7+
@suppress_errors(True)
8+
def return_true():
99
raise Exception('This is test Error')
1010

11-
@suppress_errors('false')
12-
def return_false() -> bool:
11+
@suppress_errors(False)
12+
def return_false():
1313
raise Exception('This is test Error')
1414

15+
@suppress_errors('Failed')
16+
def return_any():
17+
raise Exception('This is test Error')
1518

16-
def test_return_exception():
19+
def test_supress_error():
1720
result = return_exception()
18-
assert isinstance(result, Exception)
21+
assert isinstance(result, Exception), 'Expected Exception'
1922

20-
def test_true():
2123
result = return_true()
22-
assert result is True
24+
assert result is True, f"Expected True, got {result}"
2325

24-
def test_false():
2526
result = return_false()
26-
assert result is False
27+
assert result is False, f"Expected False, got {result}"
28+
29+
result = return_any()
30+
assert result == 'Failed', f"Expected 'Failed', got {result}"

0 commit comments

Comments
 (0)