Skip to content

Commit 22286a0

Browse files
committed
feat: add deprecation warning decorator system
- add warn_deprecation decorator for method deprecation warnings - track shown warnings to prevent duplicate messages - support configurable suppression via suppress_deprecation_warnings - integrate with apicall configuration for warning control
1 parent ffe325f commit 22286a0

File tree

1 file changed

+68
-0
lines changed

1 file changed

+68
-0
lines changed

src/typesense/logger.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,74 @@
11
"""Logging configuration for the Typesense Python client."""
22

3+
import functools
34
import logging
5+
import sys
6+
7+
if sys.version_info >= (3, 11):
8+
import typing
9+
else:
10+
import typing_extensions as typing
411

512
logger = logging.getLogger("typesense")
613
logger.setLevel(logging.WARN)
14+
15+
_deprecation_warnings: typing.Dict[str, bool] = {}
16+
17+
18+
def warn_deprecation(
19+
message: str,
20+
*,
21+
flag_name: typing.Union[str, None] = None,
22+
) -> typing.Callable[
23+
[typing.Callable[..., typing.Any]], typing.Callable[..., typing.Any]
24+
]:
25+
"""
26+
Decorator to warn about deprecation when a method is called.
27+
28+
This decorator will log a deprecation warning once per flag_name when the
29+
decorated method is called. The warning is only shown once to avoid spam.
30+
31+
Args:
32+
message: The deprecation warning message to display.
33+
flag_name: Optional name for the warning flag. If not provided, a default
34+
name will be generated based on the function's module and name.
35+
36+
Returns:
37+
A decorator function that wraps the target method.
38+
39+
Example:
40+
>>> @warn_deprecation("This method is deprecated", flag_name="my_method")
41+
... def my_method(self):
42+
... return "result"
43+
"""
44+
45+
def decorator(
46+
func: typing.Callable[..., typing.Any],
47+
) -> typing.Callable[..., typing.Any]:
48+
if flag_name is None:
49+
flag = f"{func.__module__}.{func.__qualname__}"
50+
else:
51+
flag = flag_name
52+
53+
@functools.wraps(func)
54+
def wrapper(*args: typing.Any, **kwargs: typing.Any) -> typing.Any:
55+
suppress_warnings = False
56+
if (
57+
args
58+
and len(args) > 1
59+
and args[1]
60+
and args[1].__class__.__name__ == "ApiCall"
61+
and hasattr(args[1], "config")
62+
):
63+
suppress_warnings = getattr(
64+
args[1].config, "suppress_deprecation_warnings", False
65+
)
66+
67+
if not suppress_warnings and not _deprecation_warnings.get(flag, False):
68+
logger.warning(f"Deprecation warning: {message}")
69+
_deprecation_warnings[flag] = True
70+
return func(*args, **kwargs)
71+
72+
return wrapper
73+
74+
return decorator

0 commit comments

Comments
 (0)