deprecated-parameters 0.1.0.dev2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deprecated_parameters-0.1.0.dev2/LICENSE.rst +21 -0
- deprecated_parameters-0.1.0.dev2/PKG-INFO +57 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters/__init__.py +10 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters/_decorator.py +151 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters/_mypy.py +79 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters/py.typed +0 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters.egg-info/PKG-INFO +57 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters.egg-info/SOURCES.txt +13 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters.egg-info/dependency_links.txt +1 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters.egg-info/requires.txt +12 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters.egg-info/top_level.txt +2 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters_tests/__main__.py +22 -0
- deprecated_parameters-0.1.0.dev2/deprecated_parameters_tests/test_decorator.py +125 -0
- deprecated_parameters-0.1.0.dev2/pyproject.toml +113 -0
- deprecated_parameters-0.1.0.dev2/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-present, Mauricio Villegas <mauricio@omnius.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: deprecated-parameters
|
|
3
|
+
Version: 0.1.0.dev2
|
|
4
|
+
Summary: Deprecation of parameters in function and method signatures.
|
|
5
|
+
Author-email: Mauricio Villegas <mauricio@omnius.com>
|
|
6
|
+
License: The MIT License (MIT)
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025-present, Mauricio Villegas <mauricio@omnius.com>
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: GitHub, https://github.com/mauvilsa/deprecated-parameters
|
|
29
|
+
Project-URL: PyPI, https://pypi.org/project/deprecated-parameters
|
|
30
|
+
Platform: Any
|
|
31
|
+
Classifier: Development Status :: 1 - Planning
|
|
32
|
+
Classifier: Programming Language :: Python
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Intended Audience :: Developers
|
|
42
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
43
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
44
|
+
Classifier: Operating System :: MacOS
|
|
45
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
46
|
+
Requires-Python: >=3.8
|
|
47
|
+
Description-Content-Type: text/x-rst
|
|
48
|
+
License-File: LICENSE.rst
|
|
49
|
+
Provides-Extra: mypy
|
|
50
|
+
Requires-Dist: mypy>=1.15.0; extra == "mypy"
|
|
51
|
+
Provides-Extra: test
|
|
52
|
+
Requires-Dist: pytest>=6.2.5; extra == "test"
|
|
53
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
54
|
+
Provides-Extra: dev
|
|
55
|
+
Requires-Dist: pre-commit>=2.19.0; extra == "dev"
|
|
56
|
+
Requires-Dist: tox>=3.25.0; extra == "dev"
|
|
57
|
+
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import inspect
|
|
2
|
+
import warnings
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from functools import wraps
|
|
5
|
+
from typing import Callable, Dict, List, Literal, Optional, TypeVar, Union
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"ParameterRemove",
|
|
9
|
+
"ParameterRename",
|
|
10
|
+
"DeprecatedParameters",
|
|
11
|
+
"deprecated_parameters",
|
|
12
|
+
"get_deprecated_parameters",
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
default_when = "the future"
|
|
16
|
+
default_remove_message = 'Argument "%(old_name)s" to "%(func)s" is deprecated and will be removed in %(when)s'
|
|
17
|
+
default_rename_message = (
|
|
18
|
+
'Argument "%(old_name)s" to "%(func)s" is deprecated, it has been renamed to "%(new_name)s" '
|
|
19
|
+
'and "%(old_name)s" will be removed in %(when)s'
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
F = TypeVar("F", bound=Callable)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class ParameterDeprecation:
|
|
26
|
+
def __init__(
|
|
27
|
+
self,
|
|
28
|
+
*args,
|
|
29
|
+
when,
|
|
30
|
+
message,
|
|
31
|
+
transform,
|
|
32
|
+
) -> None:
|
|
33
|
+
if args:
|
|
34
|
+
raise TypeError(f"{self.__class__.__name__} does not accept positional arguments.")
|
|
35
|
+
self.when = when
|
|
36
|
+
self.message = message
|
|
37
|
+
self.transform = transform
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class ParameterRemove(ParameterDeprecation):
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
*args,
|
|
44
|
+
old_name: str,
|
|
45
|
+
when: str = default_when,
|
|
46
|
+
message: str = default_remove_message,
|
|
47
|
+
transform: Literal["remove", None] = "remove",
|
|
48
|
+
) -> None:
|
|
49
|
+
if transform not in ["remove", None]:
|
|
50
|
+
raise ValueError("transform must be 'remove' or None.")
|
|
51
|
+
self.old_name = old_name
|
|
52
|
+
super().__init__(*args, when=when, message=message, transform=transform)
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ParameterRename(ParameterDeprecation):
|
|
56
|
+
def __init__(
|
|
57
|
+
self,
|
|
58
|
+
*args,
|
|
59
|
+
new_name: str,
|
|
60
|
+
old_name: str,
|
|
61
|
+
when: str = default_when,
|
|
62
|
+
message: str = default_rename_message,
|
|
63
|
+
transform: Literal["reassign", None] = "reassign",
|
|
64
|
+
) -> None:
|
|
65
|
+
if transform not in ["reassign", None]:
|
|
66
|
+
raise ValueError("transform must be 'reassign' or None.")
|
|
67
|
+
self.new_name = new_name
|
|
68
|
+
self.old_name = old_name
|
|
69
|
+
super().__init__(*args, when=when, message=message, transform=transform)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class DeprecatedParameters:
|
|
74
|
+
removed: List[ParameterRemove]
|
|
75
|
+
renamed: List[ParameterRename]
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
_deprecations_register: Dict[str, DeprecatedParameters] = {}
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
def get_deprecated_parameters(func: Callable, /) -> Optional[DeprecatedParameters]:
|
|
82
|
+
return _deprecations_register.get(f"{func.__module__}.{func.__qualname__}")
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def deprecated_parameters(*deprecations: Union[ParameterRemove, ParameterRename]) -> Callable[[F], F]:
|
|
86
|
+
"""
|
|
87
|
+
A decorator to mark parameters of a function or method as deprecated.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
deprecations: parameter deprecation instances.
|
|
91
|
+
|
|
92
|
+
Returns:
|
|
93
|
+
The decorated function with registered parameter deprecations.
|
|
94
|
+
"""
|
|
95
|
+
if len(deprecations) == 0:
|
|
96
|
+
raise ValueError("At least one deprecation must be provided.")
|
|
97
|
+
|
|
98
|
+
def decorator(func):
|
|
99
|
+
fullname = f"{func.__module__}.{func.__qualname__}"
|
|
100
|
+
if fullname in _deprecations_register:
|
|
101
|
+
raise ValueError("The @deprecated_parameters decorator can only be applied once per callable.")
|
|
102
|
+
|
|
103
|
+
deprecation = DeprecatedParameters(
|
|
104
|
+
removed=[x for x in deprecations if isinstance(x, ParameterRemove)],
|
|
105
|
+
renamed=[x for x in deprecations if isinstance(x, ParameterRename)],
|
|
106
|
+
)
|
|
107
|
+
|
|
108
|
+
if deprecation.renamed:
|
|
109
|
+
params = list(inspect.signature(func).parameters.keys())
|
|
110
|
+
for rename in deprecation.renamed:
|
|
111
|
+
if rename.new_name not in params:
|
|
112
|
+
raise ValueError(f"Parameter '{rename.new_name}' not found in signature of {func}.")
|
|
113
|
+
|
|
114
|
+
_deprecations_register[fullname] = deprecation
|
|
115
|
+
|
|
116
|
+
@wraps(func)
|
|
117
|
+
def wrapper(*args, **kwargs):
|
|
118
|
+
for removal in deprecation.removed:
|
|
119
|
+
if removal.old_name in kwargs:
|
|
120
|
+
warnings.warn(
|
|
121
|
+
removal.message % {"func": func.__name__, "old_name": removal.old_name, "when": removal.when},
|
|
122
|
+
category=DeprecationWarning,
|
|
123
|
+
)
|
|
124
|
+
if removal.transform == "remove":
|
|
125
|
+
del kwargs[removal.old_name]
|
|
126
|
+
|
|
127
|
+
for rename in deprecation.renamed:
|
|
128
|
+
if rename.old_name in kwargs:
|
|
129
|
+
warnings.warn(
|
|
130
|
+
rename.message
|
|
131
|
+
% {
|
|
132
|
+
"func": func.__name__,
|
|
133
|
+
"old_name": rename.old_name,
|
|
134
|
+
"new_name": rename.new_name,
|
|
135
|
+
"when": rename.when,
|
|
136
|
+
},
|
|
137
|
+
category=DeprecationWarning,
|
|
138
|
+
)
|
|
139
|
+
if rename.transform == "reassign":
|
|
140
|
+
positionals = list(inspect.signature(func).parameters.keys())[: len(args)]
|
|
141
|
+
if rename.new_name in kwargs or rename.new_name in positionals:
|
|
142
|
+
raise ValueError(
|
|
143
|
+
f"Unable to reassign '{rename.old_name}' because '{rename.new_name}' is also set."
|
|
144
|
+
)
|
|
145
|
+
kwargs[rename.new_name] = kwargs.pop(rename.old_name)
|
|
146
|
+
|
|
147
|
+
return func(*args, **kwargs)
|
|
148
|
+
|
|
149
|
+
return wrapper
|
|
150
|
+
|
|
151
|
+
return decorator
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
from importlib.util import find_spec
|
|
2
|
+
from typing import Callable, Union
|
|
3
|
+
|
|
4
|
+
from ._decorator import default_remove_message, default_rename_message, default_when, deprecated_parameters
|
|
5
|
+
|
|
6
|
+
__all__ = [
|
|
7
|
+
"mypy_plugin",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
decorator_fullname = f"{deprecated_parameters.__module__}.{deprecated_parameters.__qualname__}"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if find_spec("mypy"):
|
|
14
|
+
from mypy.nodes import CallExpr
|
|
15
|
+
from mypy.plugin import FunctionSigContext, MethodSigContext, Plugin
|
|
16
|
+
from mypy.types import FunctionLike
|
|
17
|
+
|
|
18
|
+
def get_deprecation_value(deprecation: CallExpr, arg_name: str, default=None):
|
|
19
|
+
for value, name in zip(deprecation.args, deprecation.arg_names):
|
|
20
|
+
if name == arg_name:
|
|
21
|
+
assert hasattr(value, "value")
|
|
22
|
+
return value.value
|
|
23
|
+
if default is not None:
|
|
24
|
+
return default
|
|
25
|
+
raise ValueError(f"Argument '{arg_name}' not found in deprecation {deprecation}.")
|
|
26
|
+
|
|
27
|
+
def signature_hook(ctx: Union[FunctionSigContext, MethodSigContext]) -> FunctionLike:
|
|
28
|
+
assert hasattr(ctx.context, "callee")
|
|
29
|
+
decorators = getattr(ctx.context.callee.node, "original_decorators", [])
|
|
30
|
+
if any(d.callee.fullname == decorator_fullname for d in decorators):
|
|
31
|
+
assert hasattr(ctx.context, "arg_names")
|
|
32
|
+
decorator = next(d for d in decorators if d.callee.fullname == decorator_fullname)
|
|
33
|
+
for deprecation in decorator.args:
|
|
34
|
+
if deprecation.callee.name == "ParameterRemove":
|
|
35
|
+
old_name = get_deprecation_value(deprecation, "old_name")
|
|
36
|
+
if old_name in ctx.context.arg_names:
|
|
37
|
+
message = get_deprecation_value(deprecation, "message", default_remove_message)
|
|
38
|
+
when = get_deprecation_value(deprecation, "when", default_when)
|
|
39
|
+
ctx.api.fail(
|
|
40
|
+
message % {"func": ctx.context.callee.name, "old_name": old_name, "when": when},
|
|
41
|
+
ctx.context,
|
|
42
|
+
)
|
|
43
|
+
elif deprecation.callee.name == "ParameterRename":
|
|
44
|
+
old_name = get_deprecation_value(deprecation, "old_name")
|
|
45
|
+
if old_name in ctx.context.arg_names:
|
|
46
|
+
message = get_deprecation_value(deprecation, "message", default_rename_message)
|
|
47
|
+
when = get_deprecation_value(deprecation, "when", default_when)
|
|
48
|
+
new_name = get_deprecation_value(deprecation, "new_name")
|
|
49
|
+
ctx.api.fail(
|
|
50
|
+
message
|
|
51
|
+
% {
|
|
52
|
+
"func": ctx.context.callee.name,
|
|
53
|
+
"old_name": old_name,
|
|
54
|
+
"new_name": new_name,
|
|
55
|
+
"when": when,
|
|
56
|
+
},
|
|
57
|
+
ctx.context,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
return ctx.default_signature
|
|
61
|
+
|
|
62
|
+
def function_signature_hook(ctx: FunctionSigContext) -> FunctionLike:
|
|
63
|
+
return signature_hook(ctx)
|
|
64
|
+
|
|
65
|
+
def method_signature_hook(ctx: MethodSigContext) -> FunctionLike:
|
|
66
|
+
return signature_hook(ctx)
|
|
67
|
+
|
|
68
|
+
class MypyDeprecatedParametersPlugin(Plugin):
|
|
69
|
+
"""A mypy plugin to check for deprecated parameters in functions and methods."""
|
|
70
|
+
|
|
71
|
+
def get_function_signature_hook(self, fullname: str) -> Callable[[FunctionSigContext], FunctionLike] | None:
|
|
72
|
+
return function_signature_hook
|
|
73
|
+
|
|
74
|
+
def get_method_signature_hook(self, fullname: str) -> Callable[[MethodSigContext], FunctionLike] | None:
|
|
75
|
+
return method_signature_hook
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def mypy_plugin(version: str):
|
|
79
|
+
return MypyDeprecatedParametersPlugin
|
|
File without changes
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: deprecated-parameters
|
|
3
|
+
Version: 0.1.0.dev2
|
|
4
|
+
Summary: Deprecation of parameters in function and method signatures.
|
|
5
|
+
Author-email: Mauricio Villegas <mauricio@omnius.com>
|
|
6
|
+
License: The MIT License (MIT)
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2025-present, Mauricio Villegas <mauricio@omnius.com>
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: GitHub, https://github.com/mauvilsa/deprecated-parameters
|
|
29
|
+
Project-URL: PyPI, https://pypi.org/project/deprecated-parameters
|
|
30
|
+
Platform: Any
|
|
31
|
+
Classifier: Development Status :: 1 - Planning
|
|
32
|
+
Classifier: Programming Language :: Python
|
|
33
|
+
Classifier: Programming Language :: Python :: 3
|
|
34
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
35
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
36
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
37
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
41
|
+
Classifier: Intended Audience :: Developers
|
|
42
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
43
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
44
|
+
Classifier: Operating System :: MacOS
|
|
45
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
46
|
+
Requires-Python: >=3.8
|
|
47
|
+
Description-Content-Type: text/x-rst
|
|
48
|
+
License-File: LICENSE.rst
|
|
49
|
+
Provides-Extra: mypy
|
|
50
|
+
Requires-Dist: mypy>=1.15.0; extra == "mypy"
|
|
51
|
+
Provides-Extra: test
|
|
52
|
+
Requires-Dist: pytest>=6.2.5; extra == "test"
|
|
53
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "test"
|
|
54
|
+
Provides-Extra: dev
|
|
55
|
+
Requires-Dist: pre-commit>=2.19.0; extra == "dev"
|
|
56
|
+
Requires-Dist: tox>=3.25.0; extra == "dev"
|
|
57
|
+
Requires-Dist: build>=0.10.0; extra == "dev"
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
LICENSE.rst
|
|
2
|
+
pyproject.toml
|
|
3
|
+
deprecated_parameters/__init__.py
|
|
4
|
+
deprecated_parameters/_decorator.py
|
|
5
|
+
deprecated_parameters/_mypy.py
|
|
6
|
+
deprecated_parameters/py.typed
|
|
7
|
+
deprecated_parameters.egg-info/PKG-INFO
|
|
8
|
+
deprecated_parameters.egg-info/SOURCES.txt
|
|
9
|
+
deprecated_parameters.egg-info/dependency_links.txt
|
|
10
|
+
deprecated_parameters.egg-info/requires.txt
|
|
11
|
+
deprecated_parameters.egg-info/top_level.txt
|
|
12
|
+
deprecated_parameters_tests/__main__.py
|
|
13
|
+
deprecated_parameters_tests/test_decorator.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Run all unit tests in package."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import sys
|
|
5
|
+
import warnings
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def run_tests():
|
|
12
|
+
filter_action = "default"
|
|
13
|
+
warnings.simplefilter(filter_action)
|
|
14
|
+
os.environ["PYTHONWARNINGS"] = filter_action
|
|
15
|
+
testing_package = Path(__file__).parent
|
|
16
|
+
exit_code = pytest.main(["-v", "-s", f"--rootdir={testing_package.parent}", "--pyargs", str(testing_package)])
|
|
17
|
+
if exit_code != 0:
|
|
18
|
+
sys.exit(True)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
run_tests()
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from deprecated_parameters import deprecated_parameters, ParameterRemove, ParameterRename
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def test_parameter_remove_missing_required():
|
|
9
|
+
with pytest.raises(TypeError, match="missing 1 required keyword-only argument: 'old_name'"):
|
|
10
|
+
ParameterRemove()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_parameter_rename_missing_required():
|
|
14
|
+
with pytest.raises(TypeError, match="missing 1 required keyword-only argument: 'new_name'"):
|
|
15
|
+
ParameterRename(old_name="old_name")
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def test_deprecated_parameters_decorator_positional_only():
|
|
19
|
+
with pytest.raises(TypeError, match="deprecated_parameters.. got an unexpected keyword argument"):
|
|
20
|
+
@deprecated_parameters(deprecations=[])
|
|
21
|
+
def func_positional_only():
|
|
22
|
+
pass
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def test_deprecated_parameters_decorator_empty():
|
|
26
|
+
with pytest.raises(ValueError, match="At least one deprecation must be provided"):
|
|
27
|
+
@deprecated_parameters()
|
|
28
|
+
def func_decorator_empty():
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def test_deprecated_parameters_decorator_multiple():
|
|
33
|
+
with pytest.raises(ValueError, match="@deprecated_parameters decorator can only be applied once per callable"):
|
|
34
|
+
@deprecated_parameters(
|
|
35
|
+
ParameterRemove(old_name="old_name"),
|
|
36
|
+
)
|
|
37
|
+
@deprecated_parameters(
|
|
38
|
+
ParameterRename(old_name="old_name", new_name="new_name"),
|
|
39
|
+
)
|
|
40
|
+
def func_decorator_multiple(new_name: str):
|
|
41
|
+
pass
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@deprecated_parameters(
|
|
45
|
+
ParameterRemove(old_name="removed"),
|
|
46
|
+
)
|
|
47
|
+
def func_keyword_parameter_remove():
|
|
48
|
+
pass
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_func_keyword_parameter_remove():
|
|
52
|
+
with warnings.catch_warnings(record=True) as w:
|
|
53
|
+
func_keyword_parameter_remove(removed=1)
|
|
54
|
+
assert len(w) == 1
|
|
55
|
+
assert issubclass(w[-1].category, DeprecationWarning)
|
|
56
|
+
assert 'Argument "removed" to "func_keyword_parameter_remove" is deprecated ' in str(w[-1].message)
|
|
57
|
+
|
|
58
|
+
with warnings.catch_warnings(record=True) as w:
|
|
59
|
+
func_keyword_parameter_remove()
|
|
60
|
+
assert len(w) == 0
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
@deprecated_parameters(
|
|
64
|
+
ParameterRename(old_name="before", new_name="now"),
|
|
65
|
+
)
|
|
66
|
+
def func_keyword_parameter_rename(*, now: int):
|
|
67
|
+
return now
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def test_func_keyword_parameter_rename():
|
|
71
|
+
with warnings.catch_warnings(record=True) as w:
|
|
72
|
+
assert func_keyword_parameter_rename(before=7) == 7
|
|
73
|
+
assert len(w) == 1
|
|
74
|
+
assert issubclass(w[-1].category, DeprecationWarning)
|
|
75
|
+
assert 'Argument "before" to "func_keyword_parameter_rename" is deprecated' in str(w[-1].message)
|
|
76
|
+
assert 'it has been renamed to "now" and "before" will be removed in the future' in str(w[-1].message)
|
|
77
|
+
|
|
78
|
+
with warnings.catch_warnings(record=True) as w:
|
|
79
|
+
assert func_keyword_parameter_rename(now=6) == 6
|
|
80
|
+
assert len(w) == 0
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class KeywordParameterRemove:
|
|
84
|
+
@deprecated_parameters(
|
|
85
|
+
ParameterRemove(old_name="removed"),
|
|
86
|
+
)
|
|
87
|
+
def method_keyword_parameter_remove(self):
|
|
88
|
+
pass
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def test_method_keyword_parameter_remove():
|
|
92
|
+
instance = KeywordParameterRemove()
|
|
93
|
+
|
|
94
|
+
with warnings.catch_warnings(record=True) as w:
|
|
95
|
+
instance.method_keyword_parameter_remove(removed=1)
|
|
96
|
+
assert len(w) == 1
|
|
97
|
+
assert issubclass(w[-1].category, DeprecationWarning)
|
|
98
|
+
assert 'Argument "removed" to "method_keyword_parameter_remove" is deprecated' in str(w[-1].message)
|
|
99
|
+
|
|
100
|
+
with warnings.catch_warnings(record=True) as w:
|
|
101
|
+
instance.method_keyword_parameter_remove()
|
|
102
|
+
assert len(w) == 0
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class KeywordParameterRename:
|
|
106
|
+
@deprecated_parameters(
|
|
107
|
+
ParameterRename(old_name="before", new_name="now"),
|
|
108
|
+
)
|
|
109
|
+
def method_keyword_parameter_rename(self, *, now: int):
|
|
110
|
+
return now
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def test_method_keyword_parameter_rename():
|
|
114
|
+
instance = KeywordParameterRename()
|
|
115
|
+
|
|
116
|
+
with warnings.catch_warnings(record=True) as w:
|
|
117
|
+
assert instance.method_keyword_parameter_rename(before=9) == 9
|
|
118
|
+
assert len(w) == 1
|
|
119
|
+
assert issubclass(w[-1].category, DeprecationWarning)
|
|
120
|
+
assert 'Argument "before" to "method_keyword_parameter_rename" is deprecated' in str(w[-1].message)
|
|
121
|
+
assert 'it has been renamed to "now" and "before" will be removed in the future' in str(w[-1].message)
|
|
122
|
+
|
|
123
|
+
with warnings.catch_warnings(record=True) as w:
|
|
124
|
+
assert instance.method_keyword_parameter_rename(now=8) == 8
|
|
125
|
+
assert len(w) == 0
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
[project]
|
|
7
|
+
name = "deprecated-parameters"
|
|
8
|
+
dynamic = ["version"]
|
|
9
|
+
description = "Deprecation of parameters in function and method signatures."
|
|
10
|
+
authors = [
|
|
11
|
+
{name = "Mauricio Villegas", email = "mauricio@omnius.com"},
|
|
12
|
+
]
|
|
13
|
+
readme = "README.rst"
|
|
14
|
+
license = {file = "LICENSE.rst"}
|
|
15
|
+
requires-python = ">=3.8"
|
|
16
|
+
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 1 - Planning",
|
|
19
|
+
"Programming Language :: Python",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Programming Language :: Python :: 3.8",
|
|
23
|
+
"Programming Language :: Python :: 3.9",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Programming Language :: Python :: 3.12",
|
|
27
|
+
"Programming Language :: Python :: 3.13",
|
|
28
|
+
"Intended Audience :: Developers",
|
|
29
|
+
"License :: OSI Approved :: MIT License",
|
|
30
|
+
"Operating System :: POSIX :: Linux",
|
|
31
|
+
"Operating System :: MacOS",
|
|
32
|
+
"Operating System :: Microsoft :: Windows",
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
[project.optional-dependencies]
|
|
37
|
+
mypy = [
|
|
38
|
+
"mypy>=1.15.0",
|
|
39
|
+
]
|
|
40
|
+
test = [
|
|
41
|
+
"pytest>=6.2.5",
|
|
42
|
+
"pytest-cov>=4.0.0",
|
|
43
|
+
]
|
|
44
|
+
dev = [
|
|
45
|
+
"pre-commit>=2.19.0",
|
|
46
|
+
"tox>=3.25.0",
|
|
47
|
+
"build>=0.10.0",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[project.urls]
|
|
51
|
+
GitHub = "https://github.com/mauvilsa/deprecated-parameters"
|
|
52
|
+
PyPI = "https://pypi.org/project/deprecated-parameters"
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
[tool.setuptools]
|
|
56
|
+
platforms = ["Any"]
|
|
57
|
+
packages = ["deprecated_parameters", "deprecated_parameters_tests"]
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.dynamic]
|
|
60
|
+
version = {attr = "deprecated_parameters.__version__"}
|
|
61
|
+
|
|
62
|
+
[tool.setuptools.package-data]
|
|
63
|
+
deprecated_parameters = ["py.typed"]
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
[tool.pytest.ini_options]
|
|
67
|
+
addopts = "-s"
|
|
68
|
+
testpaths = ["deprecated_parameters_tests"]
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
[tool.coverage.run]
|
|
72
|
+
relative_files = true
|
|
73
|
+
source = ["deprecated_parameters"]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
[tool.mypy]
|
|
77
|
+
warn_unused_ignores = true
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
[tool.ruff]
|
|
81
|
+
line-length = 120
|
|
82
|
+
|
|
83
|
+
[tool.ruff.lint]
|
|
84
|
+
select = [
|
|
85
|
+
"E", "W", # https://pypi.org/project/pycodestyle
|
|
86
|
+
"F", # https://pypi.org/project/pyflakes
|
|
87
|
+
"I", # https://pypi.org/project/isort
|
|
88
|
+
]
|
|
89
|
+
|
|
90
|
+
[tool.ruff.lint.pydocstyle]
|
|
91
|
+
convention = "google"
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
[tool.black]
|
|
95
|
+
line-length = 120
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
[tool.typos.default.extend-identifiers]
|
|
99
|
+
Villegas = "Villegas"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
[tool.tox]
|
|
103
|
+
legacy_tox_ini = """
|
|
104
|
+
[tox]
|
|
105
|
+
envlist = py{38,39,310,311,312,313}
|
|
106
|
+
skip_missing_interpreters = true
|
|
107
|
+
|
|
108
|
+
[testenv]
|
|
109
|
+
extras = test
|
|
110
|
+
changedir = deprecated_parameters_tests
|
|
111
|
+
commands = python -m pytest {posargs}
|
|
112
|
+
usedevelop = true
|
|
113
|
+
"""
|