Skip to content

Commit 5e5b950

Browse files
authored
add deprecation period to deprecated_args_alias (#1477)
1 parent 1278a0f commit 5e5b950

File tree

6 files changed

+144
-21
lines changed

6 files changed

+144
-21
lines changed

can/interface.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,11 @@ class Bus(BusABC): # pylint: disable=abstract-method
100100
"""
101101

102102
@staticmethod
103-
@util.deprecated_args_alias( # Deprecated since python-can 4.2
104-
bustype="interface", context="config_context"
103+
@util.deprecated_args_alias(
104+
deprecation_start="4.2.0",
105+
deprecation_end="5.0.0",
106+
bustype="interface",
107+
context="config_context",
105108
)
106109
def __new__( # type: ignore
107110
cls: Any,

can/interfaces/ixxat/canlib_vcinpl.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ class IXXATBus(BusABC):
417417
}
418418

419419
@deprecated_args_alias(
420+
deprecation_start="4.0.0",
421+
deprecation_end="5.0.0",
420422
UniqueHardwareId="unique_hardware_id",
421423
rxFifoSize="rx_fifo_size",
422424
txFifoSize="tx_fifo_size",

can/interfaces/ixxat/canlib_vcinpl2.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ class IXXATBus(BusABC):
417417
"""
418418

419419
@deprecated_args_alias(
420+
deprecation_start="4.0.0",
421+
deprecation_end="5.0.0",
420422
UniqueHardwareId="unique_hardware_id",
421423
rxFifoSize="rx_fifo_size",
422424
txFifoSize="tx_fifo_size",

can/interfaces/vector/canlib.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,11 @@ class VectorBus(BusABC):
7575
tseg2Dbr="tseg2_dbr",
7676
)
7777

78-
@deprecated_args_alias(**deprecated_args)
78+
@deprecated_args_alias(
79+
deprecation_start="4.0.0",
80+
deprecation_end="5.0.0",
81+
**deprecated_args,
82+
)
7983
def __init__(
8084
self,
8185
channel: Union[int, Sequence[int], str],

can/util.py

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,26 +295,47 @@ def channel2int(channel: Optional[typechecking.Channel]) -> Optional[int]:
295295
return None
296296

297297

298-
def deprecated_args_alias(**aliases):
298+
def deprecated_args_alias( # type: ignore
299+
deprecation_start: str, deprecation_end: Optional[str] = None, **aliases
300+
):
299301
"""Allows to rename/deprecate a function kwarg(s) and optionally
300302
have the deprecated kwarg(s) set as alias(es)
301303
302304
Example::
303305
304-
@deprecated_args_alias(oldArg="new_arg", anotherOldArg="another_new_arg")
306+
@deprecated_args_alias("1.2.0", oldArg="new_arg", anotherOldArg="another_new_arg")
305307
def library_function(new_arg, another_new_arg):
306308
pass
307309
308-
@deprecated_args_alias(oldArg="new_arg", obsoleteOldArg=None)
310+
@deprecated_args_alias(
311+
deprecation_start="1.2.0",
312+
deprecation_end="3.0.0",
313+
oldArg="new_arg",
314+
obsoleteOldArg=None,
315+
)
309316
def library_function(new_arg):
310317
pass
311318
319+
:param deprecation_start:
320+
The *python-can* version, that introduced the :class:`DeprecationWarning`.
321+
:param deprecation_end:
322+
The *python-can* version, that marks the end of the deprecation period.
323+
:param aliases:
324+
keyword arguments, that map the deprecated argument names
325+
to the new argument names or ``None``.
326+
312327
"""
313328

314329
def deco(f):
315330
@functools.wraps(f)
316331
def wrapper(*args, **kwargs):
317-
_rename_kwargs(f.__name__, kwargs, aliases)
332+
_rename_kwargs(
333+
func_name=f.__name__,
334+
start=deprecation_start,
335+
end=deprecation_end,
336+
kwargs=kwargs,
337+
aliases=aliases,
338+
)
318339
return f(*args, **kwargs)
319340

320341
return wrapper
@@ -323,21 +344,35 @@ def wrapper(*args, **kwargs):
323344

324345

325346
def _rename_kwargs(
326-
func_name: str, kwargs: Dict[str, str], aliases: Dict[str, str]
347+
func_name: str,
348+
start: str,
349+
end: Optional[str],
350+
kwargs: Dict[str, str],
351+
aliases: Dict[str, str],
327352
) -> None:
328353
"""Helper function for `deprecated_args_alias`"""
329354
for alias, new in aliases.items():
330355
if alias in kwargs:
356+
deprecation_notice = (
357+
f"The '{alias}' argument is deprecated since python-can v{start}"
358+
)
359+
if end:
360+
deprecation_notice += (
361+
f", and scheduled for removal in python-can v{end}"
362+
)
363+
deprecation_notice += "."
364+
331365
value = kwargs.pop(alias)
332366
if new is not None:
333-
warnings.warn(f"{alias} is deprecated; use {new}", DeprecationWarning)
367+
deprecation_notice += f" Use '{new}' instead."
368+
334369
if new in kwargs:
335370
raise TypeError(
336-
f"{func_name} received both {alias} (deprecated) and {new}"
371+
f"{func_name} received both '{alias}' (deprecated) and '{new}'."
337372
)
338373
kwargs[new] = value
339-
else:
340-
warnings.warn(f"{alias} is deprecated", DeprecationWarning)
374+
375+
warnings.warn(deprecation_notice, DeprecationWarning)
341376

342377

343378
def time_perfcounter_correlation() -> Tuple[float, float]:

test/test_util.py

Lines changed: 86 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,26 @@
33
import unittest
44
import warnings
55

6-
from can.util import _create_bus_config, _rename_kwargs, channel2int
6+
import pytest
7+
8+
from can.util import (
9+
_create_bus_config,
10+
_rename_kwargs,
11+
channel2int,
12+
deprecated_args_alias,
13+
)
714

815

916
class RenameKwargsTest(unittest.TestCase):
1017
expected_kwargs = dict(a=1, b=2, c=3, d=4)
1118

12-
def _test(self, kwargs, aliases):
19+
def _test(self, start: str, end: str, kwargs, aliases):
1320

1421
# Test that we do get the DeprecationWarning when called with deprecated kwargs
15-
with self.assertWarnsRegex(DeprecationWarning, "is deprecated"):
16-
_rename_kwargs("unit_test", kwargs, aliases)
22+
with self.assertWarnsRegex(
23+
DeprecationWarning, "is deprecated.*?" + start + ".*?" + end
24+
):
25+
_rename_kwargs("unit_test", start, end, kwargs, aliases)
1726

1827
# Test that the aliases contains the deprecated values and
1928
# the obsolete kwargs have been removed
@@ -25,30 +34,98 @@ def _test(self, kwargs, aliases):
2534
# Cause all warnings to always be triggered.
2635
warnings.simplefilter("error", DeprecationWarning)
2736
try:
28-
_rename_kwargs("unit_test", kwargs, aliases)
37+
_rename_kwargs("unit_test", start, end, kwargs, aliases)
2938
finally:
3039
warnings.resetwarnings()
3140

3241
def test_rename(self):
3342
kwargs = dict(old_a=1, old_b=2, c=3, d=4)
3443
aliases = {"old_a": "a", "old_b": "b"}
35-
self._test(kwargs, aliases)
44+
self._test("1.0", "2.0", kwargs, aliases)
3645

3746
def test_obsolete(self):
3847
kwargs = dict(a=1, b=2, c=3, d=4, z=10)
3948
aliases = {"z": None}
40-
self._test(kwargs, aliases)
49+
self._test("1.0", "2.0", kwargs, aliases)
4150

4251
def test_rename_and_obsolete(self):
4352
kwargs = dict(old_a=1, old_b=2, c=3, d=4, z=10)
4453
aliases = {"old_a": "a", "old_b": "b", "z": None}
45-
self._test(kwargs, aliases)
54+
self._test("1.0", "2.0", kwargs, aliases)
4655

4756
def test_with_new_and_alias_present(self):
4857
kwargs = dict(old_a=1, a=1, b=2, c=3, d=4, z=10)
4958
aliases = {"old_a": "a", "old_b": "b", "z": None}
5059
with self.assertRaises(TypeError):
51-
self._test(kwargs, aliases)
60+
self._test("1.0", "2.0", kwargs, aliases)
61+
62+
63+
class DeprecatedArgsAliasTest(unittest.TestCase):
64+
def test_decorator(self):
65+
@deprecated_args_alias("1.0.0", old_a="a")
66+
def _test_func1(a):
67+
pass
68+
69+
with pytest.warns(DeprecationWarning) as record:
70+
_test_func1(old_a=1)
71+
assert len(record) == 1
72+
assert (
73+
record[0].message.args[0]
74+
== "The 'old_a' argument is deprecated since python-can v1.0.0. Use 'a' instead."
75+
)
76+
77+
@deprecated_args_alias("1.6.0", "3.4.0", old_a="a", old_b=None)
78+
def _test_func2(a):
79+
pass
80+
81+
with pytest.warns(DeprecationWarning) as record:
82+
_test_func2(old_a=1, old_b=2)
83+
assert len(record) == 2
84+
assert record[0].message.args[0] == (
85+
"The 'old_a' argument is deprecated since python-can v1.6.0, and scheduled for "
86+
"removal in python-can v3.4.0. Use 'a' instead."
87+
)
88+
assert record[1].message.args[0] == (
89+
"The 'old_b' argument is deprecated since python-can v1.6.0, and scheduled for "
90+
"removal in python-can v3.4.0."
91+
)
92+
93+
@deprecated_args_alias("1.6.0", "3.4.0", old_a="a")
94+
@deprecated_args_alias("2.0.0", "4.0.0", old_b=None)
95+
def _test_func3(a):
96+
pass
97+
98+
with pytest.warns(DeprecationWarning) as record:
99+
_test_func3(old_a=1, old_b=2)
100+
assert len(record) == 2
101+
assert record[0].message.args[0] == (
102+
"The 'old_a' argument is deprecated since python-can v1.6.0, and scheduled "
103+
"for removal in python-can v3.4.0. Use 'a' instead."
104+
)
105+
assert record[1].message.args[0] == (
106+
"The 'old_b' argument is deprecated since python-can v2.0.0, and scheduled "
107+
"for removal in python-can v4.0.0."
108+
)
109+
110+
with pytest.warns(DeprecationWarning) as record:
111+
_test_func3(old_a=1)
112+
assert len(record) == 1
113+
assert record[0].message.args[0] == (
114+
"The 'old_a' argument is deprecated since python-can v1.6.0, and scheduled "
115+
"for removal in python-can v3.4.0. Use 'a' instead."
116+
)
117+
118+
with pytest.warns(DeprecationWarning) as record:
119+
_test_func3(a=1, old_b=2)
120+
assert len(record) == 1
121+
assert record[0].message.args[0] == (
122+
"The 'old_b' argument is deprecated since python-can v2.0.0, and scheduled "
123+
"for removal in python-can v4.0.0."
124+
)
125+
126+
with warnings.catch_warnings():
127+
warnings.simplefilter("error")
128+
_test_func3(a=1)
52129

53130

54131
class TestBusConfig(unittest.TestCase):

0 commit comments

Comments
 (0)