Skip to content

Commit 3ad781a

Browse files
v1.3.0 (#90)
New minor release v1.3.0
2 parents 3f67ca7 + e9eed1e commit 3ad781a

20 files changed

Lines changed: 519 additions & 24 deletions

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 1.2.18
2+
current_version = 1.3.0
33
commit = True
44
tag = False
55
message = Prepare next version {new_version} (unreleased)

.github/workflows/python-package.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,16 @@
44
name: Python package
55

66
on:
7-
push:
8-
branches: [ master ]
97
pull_request:
10-
branches: [ master ]
8+
branches: ['master', 'main', 'develop', 'release/**', 'hotfix/**']
119

1210
jobs:
1311
pytest:
1412
strategy:
1513
fail-fast: false
1614
matrix:
1715
platform: [ ubuntu-latest, macos-latest, windows-latest ]
18-
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
16+
python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14" ]
1917

2018
runs-on: ${{ matrix.platform }}
2119

@@ -33,4 +31,3 @@ jobs:
3331
- name: Test with pytest
3432
run: |
3533
pytest tests/
36-

CHANGELOG.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,29 @@ and this project adheres to `Semantic Versioning <https://semver.org/spec/v2.0.0
1717
- I decided to keep the same version number because there is really no change in the source code
1818
(only in comment or documentation).
1919

20+
v1.3.0 (unreleased)
21+
===================
22+
23+
Minor release: Parameters deprecation
24+
25+
Added
26+
-----
27+
28+
- Add compatibility tests and adjustments for Wrapt v2.0. See PR #88 (musicinmybrain).
29+
30+
- Add experimental `@deprecated_params` decorator to mark function parameters as deprecated at call-time; emits warnings when deprecated parameters are used with optional messages and configurable warning categories. See PR #93.
31+
32+
Documentation
33+
-------------
34+
35+
- Update the Wrapt compatibility matrix to include Python 3.13 and 3.14. See PR #91
36+
37+
Changed
38+
-------
39+
40+
- Limit test coverage collection to the dedicated ``coverage`` tox environment to avoid collecting coverage across all test environments and reduce cross-environment coverage noise. See PR #92.
41+
42+
2043
v1.2.18 (2024-01-25)
2144
====================
2245

deprecated/__init__.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77
88
"""
99

10-
__version__ = "1.2.18"
11-
__author__ = u"Laurent LAPORTE <laurent.laporte.pro@gmail.com>"
12-
__date__ = "2025-01-27"
10+
__version__ = "1.3.0"
11+
__author__ = u"Laurent LAPORTE <tantale.solutions@gmail.com>"
12+
__date__ = "unreleased"
1313
__credits__ = "(c) Laurent LAPORTE"
1414

1515
from deprecated.classic import deprecated
16+
from deprecated.params import deprecated_params

deprecated/classic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
_routine_stacklevel = 2
2424
_class_stacklevel = 2
25-
except ImportError:
25+
except ImportError: # pragma: no cover
2626
_routine_stacklevel = 3
2727
if platform.python_implementation() == "PyPy":
2828
_class_stacklevel = 2
@@ -200,7 +200,7 @@ def wrapper_function(wrapped_, instance_, args_, kwargs_):
200200

201201
return wrapper_function(wrapped)
202202

203-
else:
203+
else: # pragma: no cover
204204
raise TypeError(repr(type(wrapped)))
205205

206206
return wrapped

deprecated/params.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# coding: utf-8
2+
"""
3+
Parameters deprecation
4+
======================
5+
6+
.. _Tantale's Blog: https://tantale.github.io/
7+
.. _Deprecated Parameters: https://tantale.github.io/articles/deprecated_params/
8+
9+
This module introduces a :class:`deprecated_params` decorator to specify that one (or more)
10+
parameter(s) are deprecated: when the user executes a function with a deprecated parameter,
11+
he will see a warning message in the console.
12+
13+
The decorator is customizable, the user can specify the deprecated parameter names
14+
and associate to each of them a message providing the reason of the deprecation.
15+
As with the :func:`~deprecated.classic.deprecated` decorator, the user can specify
16+
a version number (using the *version* parameter) and also define the warning message category
17+
(a subclass of :class:`Warning`) and when to display the messages (using the *action* parameter).
18+
19+
The complete study concerning the implementation of this decorator is available on the `Tantale's blog`_,
20+
on the `Deprecated Parameters`_ page.
21+
"""
22+
import collections
23+
import functools
24+
import warnings
25+
26+
try:
27+
# noinspection PyPackageRequirements
28+
import inspect2 as inspect
29+
except ImportError:
30+
import inspect
31+
32+
33+
class DeprecatedParams(object):
34+
"""
35+
Decorator used to decorate a function which at least one
36+
of the parameters is deprecated.
37+
"""
38+
39+
def __init__(self, param, reason="", category=DeprecationWarning):
40+
self.messages = {} # type: dict[str, str]
41+
self.category = category
42+
self.populate_messages(param, reason=reason)
43+
44+
def populate_messages(self, param, reason=""):
45+
if isinstance(param, dict):
46+
self.messages.update(param)
47+
elif isinstance(param, str):
48+
fmt = "'{param}' parameter is deprecated"
49+
reason = reason or fmt.format(param=param)
50+
self.messages[param] = reason
51+
else:
52+
raise TypeError(param)
53+
54+
def check_params(self, signature, *args, **kwargs):
55+
binding = signature.bind(*args, **kwargs)
56+
bound = collections.OrderedDict(binding.arguments, **binding.kwargs)
57+
return [param for param in bound if param in self.messages]
58+
59+
def warn_messages(self, messages):
60+
# type: (list[str]) -> None
61+
for message in messages:
62+
warnings.warn(message, category=self.category, stacklevel=3)
63+
64+
def __call__(self, f):
65+
# type: (callable) -> callable
66+
signature = inspect.signature(f)
67+
68+
@functools.wraps(f)
69+
def wrapper(*args, **kwargs):
70+
invalid_params = self.check_params(signature, *args, **kwargs)
71+
self.warn_messages([self.messages[param] for param in invalid_params])
72+
return f(*args, **kwargs)
73+
74+
return wrapper
75+
76+
77+
#: Decorator used to decorate a function which at least one
78+
#: of the parameters is deprecated.
79+
deprecated_params = DeprecatedParams

docs/source/_static/rusty-tools-background.svg

Lines changed: 1 addition & 1 deletion
Loading

docs/source/api.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,8 @@ This part of the documentation covers all the interfaces of the Deprecated Libra
1111
.. automodule:: deprecated.classic
1212
:members:
1313

14+
.. automodule:: deprecated.params
15+
:members:
16+
1417
.. automodule:: deprecated.sphinx
1518
:members:

docs/source/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@
6161
# built documents.
6262
#
6363
# The full version, including alpha/beta/rc tags.
64-
release = "1.2.18"
64+
release = "1.3.0"
6565
# The short X.Y version.
6666
version = release.rpartition('.')[0]
6767

docs/source/installation.rst

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,107 @@ function wrappers and decorator functions.
1717

1818
.. _Wrapt: http://wrapt.readthedocs.io/en/latest/
1919

20+
The table below shows the compatibility matrix between Python versions and the `wrapt` versions that have been
21+
tested to date. Recent versions are listed first.
22+
23+
.. list-table:: Compatibility matrix (tested versions)
24+
:header-rows: 1
25+
:widths: 25 9 9 9 9 9 9 9 9 9
26+
27+
* - Python / wrapt
28+
- 2.0
29+
- 1.17
30+
- 1.16
31+
- 1.15
32+
- 1.14
33+
- 1.13
34+
- 1.12
35+
- 1.11
36+
- 1.10
37+
* - py3.14
38+
- ✓
39+
- ✓
40+
- ✗
41+
- ✗
42+
- ✗
43+
- ✗
44+
- ✗
45+
- ✗
46+
- ✗
47+
* - py3.13
48+
- ✓
49+
- ✓
50+
- ✗
51+
- ✗
52+
- ✗
53+
- ✗
54+
- ✗
55+
- ✗
56+
- ✗
57+
* - py3.12
58+
- ✓
59+
- ✓
60+
- ✓
61+
- ✗
62+
- ✗
63+
- ✗
64+
- ✗
65+
- ✗
66+
- ✗
67+
* - py3.11
68+
- ✓
69+
- ✓
70+
- ✓
71+
- ✓
72+
- ✓
73+
- ✗
74+
- ✗
75+
- ✗
76+
- ✗
77+
* - py3.10
78+
- ✓
79+
- ✓
80+
- ✓
81+
- ✓
82+
- ✓
83+
- ✓
84+
- ✓
85+
- ✓
86+
- ✓
87+
* - py3.9
88+
- ✓
89+
- ✓
90+
- ✓
91+
- ✓
92+
- ✓
93+
- ✓
94+
- ✓
95+
- ✓
96+
- ✓
97+
* - py3.8
98+
- ?
99+
- ?
100+
- ?
101+
- ?
102+
- ✓
103+
- ✓
104+
- ✓
105+
- ✓
106+
- ✓
107+
* - py3.7
108+
- ?
109+
- ?
110+
- ?
111+
- ?
112+
- ✓
113+
- ✓
114+
- ✓
115+
- ✓
116+
- ✓
117+
118+
Legend: ✓ = tested and compatible ; ✗ = incompatible, ? = untested but expected to work
119+
120+
20121
Development dependencies
21122
~~~~~~~~~~~~~~~~~~~~~~~~
22123

0 commit comments

Comments
 (0)