Skip to content

Commit 3a172ad

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 3a172ad

File tree

1 file changed

+69
-0
lines changed

1 file changed

+69
-0
lines changed

src/typesense/logger.py

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

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

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

0 commit comments

Comments
 (0)