Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ jobs:
python -m pip install --upgrade pip
pip install -U coveralls
pip install -e .[dev]
- name: Run tests
- name: Run tests with pytest
run: |
coverage run --branch pedantic/tests/tests_main.py
pytest --doctest-modules --cov=pedantic --cov-branch --cov-report= --cov-report=term
- name: Coveralls
uses: coverallsapp/github-action@v2.2.3
uses: coverallsapp/github-action@v2.3.6
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
file: .coverage
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
# Changelog
## Pedantic 2.4.0
- migrate from unittest to pytest
- exclude tests from package deployment
- add an optional `message` argument to `@deprecated` decorator

## Pedantic 2.3.3
- [fixed validation error message in MinLength validator](https://github.com/LostInDarkMath/pedantic-python-decorators/issues/111)
- removed unused scripts
Expand Down
38 changes: 27 additions & 11 deletions docs/pedantic/decorators/fn_deco_deprecated.html
Original file line number Diff line number Diff line change
Expand Up @@ -45,37 +45,53 @@ <h1 class="title">Module <code>pedantic.decorators.fn_deco_deprecated</code></h1
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="pedantic.decorators.fn_deco_deprecated.deprecated"><code class="name flex">
<span>def <span class="ident">deprecated</span></span>(<span>func: Callable[..., ~ReturnType]) ‑> Callable[..., ~ReturnType]</span>
<span>def <span class="ident">deprecated</span></span>(<span>func: Callable[..., ~ReturnType] | None = None, message: str = '') ‑> Callable[..., ~ReturnType] | Callable[[Callable[..., ~ReturnType]], Callable[..., ~ReturnType]]</span>
</code></dt>
<dd>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">def deprecated(func: F) -&gt; F:
<pre><code class="python">def deprecated(func: F | None = None, message: str = &#39;&#39;) -&gt; F | Callable[[F], F]:
&#34;&#34;&#34;
Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.
You can specify an optional reason or message to display with the warning.

Example:

&gt;&gt;&gt; @deprecated
... def my_function(a, b, c):
... pass
&gt;&gt;&gt; my_function(5, 4, 3)
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
&gt;&gt;&gt; @deprecated(message=&#39;Will be removed soon. Please use my_function_new_instead.&#39;)
... def my_function(a, b, c):
... pass
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
&#34;&#34;&#34;

@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -&gt; ReturnType:
_raise_warning(msg=f&#39;Call to deprecated function {func.__qualname__}.&#39;, category=DeprecationWarning)
return func(*args, **kwargs)
return wrapper</code></pre>
def decorator(fun: F) -&gt; F:
@wraps(fun)
def wrapper(*args: Any, **kwargs: Any) -&gt; ReturnType:
msg = f&#39;Call to deprecated function {fun.__qualname__}.&#39;

if message:
msg += f&#39;\nReason: {message}&#39;

warnings.warn(message=msg, category=DeprecationWarning, stacklevel=2)
return fun(*args, **kwargs)
return wrapper
return decorator if func is None else decorator(func)</code></pre>
</details>
<div class="desc"><p>Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.</p>
<div class="desc"><p>Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.
You can specify an optional reason or message to display with the warning.</p>
<p>Example:</p>
<pre><code class="language-python-repl">&gt;&gt;&gt; @deprecated
... def my_function(a, b, c):
... pass
&gt;&gt;&gt; my_function(5, 4, 3)
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
&gt;&gt;&gt; @deprecated(message='Will be removed soon. Please use my_function_new_instead.')
... def my_function(a, b, c):
... pass
&gt;&gt;&gt; my_function(5, 4, 3) # doctest: +SKIP
</code></pre></div>
</dd>
</dl>
Expand Down
4 changes: 2 additions & 2 deletions docs/pedantic/decorators/fn_deco_retry.html
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ <h2 class="section-title" id="header-functions">Functions</h2>
&gt;&gt;&gt; @retry(attempts=3, exceptions=(ValueError, TypeError))
... def foo():
... raise ValueError(&#39;Some error&#39;)
&gt;&gt;&gt; foo()
&gt;&gt;&gt; foo() # doctest: +SKIP
&#34;&#34;&#34;

def decorator(func: C) -&gt; C:
Expand Down Expand Up @@ -102,7 +102,7 @@ <h2 id="example">Example</h2>
<pre><code class="language-python-repl">&gt;&gt;&gt; @retry(attempts=3, exceptions=(ValueError, TypeError))
... def foo():
... raise ValueError('Some error')
&gt;&gt;&gt; foo()
&gt;&gt;&gt; foo() # doctest: +SKIP
</code></pre></div>
</dd>
<dt id="pedantic.decorators.fn_deco_retry.retry_func"><code class="name flex">
Expand Down
18 changes: 10 additions & 8 deletions docs/pedantic/decorators/fn_deco_validate/validators/max.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ <h2 class="section-title" id="header-classes">Classes</h2>
def __init__(self, value: Union[int, float], include_boundary: bool = True) -&gt; None:
&#34;&#34;&#34;
&gt;&gt;&gt; Max(7, True).validate(7)
True
&gt;&gt;&gt; Max(7, False).validate(7)
False
7
&gt;&gt;&gt; Max(7, False).validate(7) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValidatorException: ...
&gt;&gt;&gt; Max(7, False).validate(6.999)
True
6.999
&#34;&#34;&#34;
self._value = value
self._include_boundary = include_boundary
Expand All @@ -80,11 +81,12 @@ <h2 class="section-title" id="header-classes">Classes</h2>
<div class="desc"><p>Helper class that provides a standard way to create an ABC using
inheritance.</p>
<pre><code class="language-python-repl">&gt;&gt;&gt; Max(7, True).validate(7)
True
&gt;&gt;&gt; Max(7, False).validate(7)
False
7
&gt;&gt;&gt; Max(7, False).validate(7) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValidatorException: ...
&gt;&gt;&gt; Max(7, False).validate(6.999)
True
6.999
</code></pre></div>
<h3>Ancestors</h3>
<ul class="hlist">
Expand Down
18 changes: 10 additions & 8 deletions docs/pedantic/decorators/fn_deco_validate/validators/min.html
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,12 @@ <h2 class="section-title" id="header-classes">Classes</h2>
def __init__(self, value: Union[int, float], include_boundary: bool = True) -&gt; None:
&#34;&#34;&#34;
&gt;&gt;&gt; Min(7, True).validate(7)
True
&gt;&gt;&gt; Min(7, False).validate(7)
False
7
&gt;&gt;&gt; Min(7, False).validate(7) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValidatorException: ...
&gt;&gt;&gt; Min(7, False).validate(7.001)
True
7.001
&#34;&#34;&#34;
self._value = value
self._include_boundary = include_boundary
Expand All @@ -80,11 +81,12 @@ <h2 class="section-title" id="header-classes">Classes</h2>
<div class="desc"><p>Helper class that provides a standard way to create an ABC using
inheritance.</p>
<pre><code class="language-python-repl">&gt;&gt;&gt; Min(7, True).validate(7)
True
&gt;&gt;&gt; Min(7, False).validate(7)
False
7
&gt;&gt;&gt; Min(7, False).validate(7) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
ValidatorException: ...
&gt;&gt;&gt; Min(7, False).validate(7.001)
True
7.001
</code></pre></div>
<h3>Ancestors</h3>
<ul class="hlist">
Expand Down
10 changes: 0 additions & 10 deletions docs/pedantic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ <h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="pedantic.helper_methods" href="helper_methods.html">pedantic.helper_methods</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="pedantic.mixins" href="mixins/index.html">pedantic.mixins</a></code></dt>
<dd>
<div class="desc"></div>
Expand All @@ -76,10 +72,6 @@ <h2 class="section-title" id="header-submodules">Sub-modules</h2>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="pedantic.tests" href="tests/index.html">pedantic.tests</a></code></dt>
<dd>
<div class="desc"></div>
</dd>
<dt><code class="name"><a title="pedantic.type_checking_logic" href="type_checking_logic/index.html">pedantic.type_checking_logic</a></code></dt>
<dd>
<div class="desc"></div>
Expand All @@ -106,10 +98,8 @@ <h2 class="section-title" id="header-submodules">Sub-modules</h2>
<li><code><a title="pedantic.examples" href="examples/index.html">pedantic.examples</a></code></li>
<li><code><a title="pedantic.exceptions" href="exceptions.html">pedantic.exceptions</a></code></li>
<li><code><a title="pedantic.get_context" href="get_context.html">pedantic.get_context</a></code></li>
<li><code><a title="pedantic.helper_methods" href="helper_methods.html">pedantic.helper_methods</a></code></li>
<li><code><a title="pedantic.mixins" href="mixins/index.html">pedantic.mixins</a></code></li>
<li><code><a title="pedantic.models" href="models/index.html">pedantic.models</a></code></li>
<li><code><a title="pedantic.tests" href="tests/index.html">pedantic.tests</a></code></li>
<li><code><a title="pedantic.type_checking_logic" href="type_checking_logic/index.html">pedantic.type_checking_logic</a></code></li>
</ul>
</li>
Expand Down
8 changes: 2 additions & 6 deletions docs/pedantic/mixins/with_decorated_methods.html
Original file line number Diff line number Diff line change
Expand Up @@ -117,10 +117,6 @@ <h3>Ancestors</h3>
<li>enum.ReprEnum</li>
<li>enum.Enum</li>
</ul>
<h3>Subclasses</h3>
<ul class="hlist">
<li><a title="pedantic.tests.test_with_decorated_methods.Decorators" href="../tests/test_with_decorated_methods.html#pedantic.tests.test_with_decorated_methods.Decorators">Decorators</a></li>
</ul>
</dd>
<dt id="pedantic.mixins.with_decorated_methods.WithDecoratedMethods"><code class="flex name class">
<span>class <span class="ident">WithDecoratedMethods</span></span>
Expand Down Expand Up @@ -152,7 +148,7 @@ <h3>Subclasses</h3>
... def m3(self) -&gt; None:
... print(&#39;bar&#39;)
&gt;&gt;&gt; instance = MyClass()
&gt;&gt;&gt; instance.get_decorated_functions()
&gt;&gt;&gt; instance.get_decorated_functions() # doctest: +SKIP
{
&lt;Decorators.FOO: &#39;_foo&#39;&gt;: {
&lt;bound method MyClass.m1 of &lt;__main__.MyClass object at 0x7fea7a6e2610&gt;&gt;: 42,
Expand Down Expand Up @@ -203,7 +199,7 @@ <h2 id="example">Example</h2>
... def m3(self) -&gt; None:
... print('bar')
&gt;&gt;&gt; instance = MyClass()
&gt;&gt;&gt; instance.get_decorated_functions()
&gt;&gt;&gt; instance.get_decorated_functions() # doctest: +SKIP
{
&lt;Decorators.FOO: '_foo'&gt;: {
&lt;bound method MyClass.m1 of &lt;__main__.MyClass object at 0x7fea7a6e2610&gt;&gt;: 42,
Expand Down
5 changes: 0 additions & 5 deletions pedantic/decorators/cls_deco_frozen_dataclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,3 @@ def validate_types(self, *, _context: Dict[str, Type] = None) -> None:
return decorator

return decorator(cls_=cls)


if __name__ == '__main__':
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_count_calls.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,3 @@ def wrapper(*args: Any, **kwargs: Any) -> ReturnType:

wrapper.num_calls = 0
return wrapper


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
37 changes: 24 additions & 13 deletions pedantic/decorators/fn_deco_deprecated.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,40 @@
import warnings
from functools import wraps
from typing import Any
from typing import Any, Callable, overload

from pedantic.constants import F, ReturnType
from pedantic.helper_methods import _raise_warning

@overload
def deprecated(func: F) -> F: ...

def deprecated(func: F) -> F:
@overload
def deprecated(*, message: str = '') -> Callable[[F], F]: ...

def deprecated(func: F | None = None, message: str = '') -> F | Callable[[F], F]:
"""
Use this decorator to mark a function as deprecated. It will raise a warning when the function is called.
You can specify an optional reason or message to display with the warning.

Example:

>>> @deprecated
... def my_function(a, b, c):
... pass
>>> my_function(5, 4, 3)
>>> my_function(5, 4, 3) # doctest: +SKIP
>>> @deprecated(message='Will be removed soon. Please use my_function_new_instead.')
... def my_function(a, b, c):
... pass
>>> my_function(5, 4, 3) # doctest: +SKIP
"""

@wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
_raise_warning(msg=f'Call to deprecated function {func.__qualname__}.', category=DeprecationWarning)
return func(*args, **kwargs)
return wrapper
def decorator(fun: F) -> F:
@wraps(fun)
def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
msg = f'Call to deprecated function {fun.__qualname__}.'

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

if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
warnings.warn(message=msg, category=DeprecationWarning, stacklevel=2)
return fun(*args, **kwargs)
return wrapper
return decorator if func is None else decorator(func)
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_does_same_as_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,3 @@ async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
return wrapper

return decorator


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
6 changes: 0 additions & 6 deletions pedantic/decorators/fn_deco_in_subprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,3 @@ def _inner(tx: Connection, fun: Callable[..., Union[T, Awaitable[T]]], *a, **kw_
tx.send(SubprocessError(ex=ex))
else:
tx.send(res)


if __name__ == '__main__':
import doctest

doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,3 @@ async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
else:
return wrapper
return decorator


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,3 @@ def decorator(func: F) -> F:
f'Base class "{base_class.__name__}" does not have such a method "{name}".')
return func
return decorator


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_pedantic.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,3 @@ async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
def pedantic_require_docstring(func: Optional[F] = None) -> F:
"""Shortcut for @pedantic(require_docstring=True) """
return pedantic(func=func, require_docstring=True)


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_rename_kwargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,3 @@ def wrapper(*args, **kwargs) -> ReturnType:
return func(*args, **result_kwargs)
return wrapper
return decorator


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_require_kwargs.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,3 @@ def wrapper(*args: Any, **kwargs: Any) -> ReturnType:
call.assert_uses_kwargs()
return func(*args, **kwargs)
return wrapper


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
2 changes: 1 addition & 1 deletion pedantic/decorators/fn_deco_retry.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def retry(
>>> @retry(attempts=3, exceptions=(ValueError, TypeError))
... def foo():
... raise ValueError('Some error')
>>> foo()
>>> foo() # doctest: +SKIP
"""

def decorator(func: C) -> C:
Expand Down
5 changes: 0 additions & 5 deletions pedantic/decorators/fn_deco_timer.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,3 @@ async def async_wrapper(*args: Any, **kwargs: Any) -> ReturnType:
return async_wrapper
else:
return wrapper


if __name__ == "__main__":
import doctest
doctest.testmod(verbose=False, optionflags=doctest.ELLIPSIS)
Loading