Skip to content

Commit 8f06e53

Browse files
add message parameter to @deprecated
1 parent 1fa68d8 commit 8f06e53

24 files changed

+182
-248
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Changelog
22
## Pedantic 2.4.0
33
- migrate from unittest to pytest
4-
- exclude tests from package
4+
- exclude tests from package deployment
5+
- add an optional `message` argument to `@deprecated` decorator
56

67
## Pedantic 2.3.3
78
- [fixed validation error message in MinLength validator](https://github.com/LostInDarkMath/pedantic-python-decorators/issues/111)

docs/pedantic/decorators/fn_deco_deprecated.html

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,37 +45,53 @@ <h1 class="title">Module <code>pedantic.decorators.fn_deco_deprecated</code></h1
4545
<h2 class="section-title" id="header-functions">Functions</h2>
4646
<dl>
4747
<dt id="pedantic.decorators.fn_deco_deprecated.deprecated"><code class="name flex">
48-
<span>def <span class="ident">deprecated</span></span>(<span>func: Callable[..., ~ReturnType]) ‑> Callable[..., ~ReturnType]</span>
48+
<span>def <span class="ident">deprecated</span></span>(<span>func: Callable[..., ~ReturnType] | None = None, message: str = '') ‑> Callable[..., ~ReturnType] | Callable[[Callable[..., ~ReturnType]], Callable[..., ~ReturnType]]</span>
4949
</code></dt>
5050
<dd>
5151
<details class="source">
5252
<summary>
5353
<span>Expand source code</span>
5454
</summary>
55-
<pre><code class="python">def deprecated(func: F) -&gt; F:
55+
<pre><code class="python">def deprecated(func: F | None = None, message: str = &#39;&#39;) -&gt; F | Callable[[F], F]:
5656
&#34;&#34;&#34;
5757
Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.
58+
You can specify an optional reason or message to display with the warning.
5859

5960
Example:
60-
6161
&gt;&gt;&gt; @deprecated
6262
... def my_function(a, b, c):
6363
... pass
64-
&gt;&gt;&gt; my_function(5, 4, 3)
64+
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
65+
&gt;&gt;&gt; @deprecated(message=&#39;Will be removed soon. Please use my_function_new_instead.&#39;)
66+
... def my_function(a, b, c):
67+
... pass
68+
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
6569
&#34;&#34;&#34;
6670

67-
@wraps(func)
68-
def wrapper(*args: Any, **kwargs: Any) -&gt; ReturnType:
69-
_raise_warning(msg=f&#39;Call to deprecated function {func.__qualname__}.&#39;, category=DeprecationWarning)
70-
return func(*args, **kwargs)
71-
return wrapper</code></pre>
71+
def decorator(fun: F) -&gt; F:
72+
@wraps(fun)
73+
def wrapper(*args: Any, **kwargs: Any) -&gt; ReturnType:
74+
msg = f&#39;Call to deprecated function {fun.__qualname__}.&#39;
75+
76+
if message:
77+
msg += f&#39;\nReason: {message}&#39;
78+
79+
warnings.warn(message=msg, category=DeprecationWarning, stacklevel=2)
80+
return fun(*args, **kwargs)
81+
return wrapper
82+
return decorator if func is None else decorator(func)</code></pre>
7283
</details>
73-
<div class="desc"><p>Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.</p>
84+
<div class="desc"><p>Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.
85+
You can specify an optional reason or message to display with the warning.</p>
7486
<p>Example:</p>
7587
<pre><code class="language-python-repl">&gt;&gt;&gt; @deprecated
7688
... def my_function(a, b, c):
7789
... pass
78-
&gt;&gt;&gt; my_function(5, 4, 3)
90+
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
91+
&gt;&gt;&gt; @deprecated(message='Will be removed soon. Please use my_function_new_instead.')
92+
... def my_function(a, b, c):
93+
... pass
94+
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
7995
</code></pre></div>
8096
</dd>
8197
</dl>

docs/pedantic/index.html

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,6 @@ <h2 class="section-title" id="header-submodules">Sub-modules</h2>
6464
<dd>
6565
<div class="desc"></div>
6666
</dd>
67-
<dt><code class="name"><a title="pedantic.helper_methods" href="helper_methods.html">pedantic.helper_methods</a></code></dt>
68-
<dd>
69-
<div class="desc"></div>
70-
</dd>
7167
<dt><code class="name"><a title="pedantic.mixins" href="mixins/index.html">pedantic.mixins</a></code></dt>
7268
<dd>
7369
<div class="desc"></div>
@@ -102,7 +98,6 @@ <h2 class="section-title" id="header-submodules">Sub-modules</h2>
10298
<li><code><a title="pedantic.examples" href="examples/index.html">pedantic.examples</a></code></li>
10399
<li><code><a title="pedantic.exceptions" href="exceptions.html">pedantic.exceptions</a></code></li>
104100
<li><code><a title="pedantic.get_context" href="get_context.html">pedantic.get_context</a></code></li>
105-
<li><code><a title="pedantic.helper_methods" href="helper_methods.html">pedantic.helper_methods</a></code></li>
106101
<li><code><a title="pedantic.mixins" href="mixins/index.html">pedantic.mixins</a></code></li>
107102
<li><code><a title="pedantic.models" href="models/index.html">pedantic.models</a></code></li>
108103
<li><code><a title="pedantic.type_checking_logic" href="type_checking_logic/index.html">pedantic.type_checking_logic</a></code></li>

pedantic/decorators/cls_deco_frozen_dataclass.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,3 @@ def validate_types(self, *, _context: Dict[str, Type] = None) -> None:
142142
return decorator
143143

144144
return decorator(cls_=cls)
145-
146-
147-
if __name__ == '__main__':
148-
import doctest
149-
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)

pedantic/decorators/fn_deco_count_calls.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,3 @@ def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
3030

3131
wrapper.num_calls = 0
3232
return wrapper
33-
34-
35-
if __name__ == "__main__":
36-
import doctest
37-
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,40 @@
1+
import warnings
12
from functools import wraps
2-
from typing import Any
3+
from typing import Any, Callable, overload
34

45
from pedantic.constants import F, ReturnType
5-
from pedantic.helper_methods import _raise_warning
66

7+
@overload
8+
def deprecated(func: F) -> F: ...
79

8-
def deprecated(func: F) -> F:
10+
@overload
11+
def deprecated(*, message: str = '') -> Callable[[F], F]: ...
12+
13+
def deprecated(func: F | None = None, message: str = '') -> F | Callable[[F], F]:
914
"""
1015
Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.
16+
You can specify an optional reason or message to display with the warning.
1117
1218
Example:
13-
1419
>>> @deprecated
1520
... def my_function(a, b, c):
1621
... pass
17-
>>> my_function(5, 4, 3)
22+
>>> my_function(5, 4, 3) # doctest: +SKIP
23+
>>> @deprecated(message='Will be removed soon. Please use my_function_new_instead.')
24+
... def my_function(a, b, c):
25+
... pass
26+
>>> my_function(5, 4, 3) # doctest: +SKIP
1827
"""
1928

20-
@wraps(func)
21-
def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
22-
_raise_warning(msg=f'Call to deprecated function {func.__qualname__}.', category=DeprecationWarning)
23-
return func(*args, **kwargs)
24-
return wrapper
29+
def decorator(fun: F) -> F:
30+
@wraps(fun)
31+
def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
32+
msg = f'Call to deprecated function {fun.__qualname__}.'
2533

34+
if message:
35+
msg += f'\nReason: {message}'
2636

27-
if __name__ == "__main__":
28-
import doctest
29-
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
37+
warnings.warn(message=msg, category=DeprecationWarning, stacklevel=2)
38+
return fun(*args, **kwargs)
39+
return wrapper
40+
return decorator if func is None else decorator(func)

pedantic/decorators/fn_deco_does_same_as_function.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,3 @@ async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
5252
return wrapper
5353

5454
return decorator
55-
56-
57-
if __name__ == "__main__":
58-
import doctest
59-
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)

pedantic/decorators/fn_deco_in_subprocess.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,3 @@ def _inner(tx: Connection, fun: Callable[..., Union[T, Awaitable[T]]], *a, **kw_
120120
tx.send(SubprocessError(ex=ex))
121121
else:
122122
tx.send(res)
123-
124-
125-
if __name__ == '__main__':
126-
import doctest
127-
128-
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)

pedantic/decorators/fn_deco_mock.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,3 @@ async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
3636
else:
3737
return wrapper
3838
return decorator
39-
40-
41-
if __name__ == "__main__":
42-
import doctest
43-
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)

pedantic/decorators/fn_deco_overrides.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,3 @@ def decorator(func: F) -> F:
2929
f'Base class "{base_class.__name__}" does not have such a method "{name}".')
3030
return func
3131
return decorator
32-
33-
34-
if __name__ == "__main__":
35-
import doctest
36-
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)

0 commit comments

Comments
 (0)