Skip to content

Commit ec24a16

Browse files
committed
Add renamed_kwarg_warning decorator
1 parent 29b1f86 commit ec24a16

File tree

2 files changed

+101
-0
lines changed

2 files changed

+101
-0
lines changed

pvlib/_deprecation.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,66 @@ def wrapper(*args, **kwargs):
316316
return finalize(wrapper, new_doc)
317317

318318
return deprecate
319+
320+
321+
def renamed_kwarg_warning(since, old_param_name, new_param_name, removal=""):
322+
"""
323+
Decorator to mark a possible keyword argument as deprecated and replaced
324+
with other name.
325+
326+
Raises a warning when the deprecated argument is used, and replaces the
327+
call with the new argument name. Does not modify the function signature.
328+
329+
.. warning::
330+
Ensure ``removal`` date with a ``fail_on_pvlib_version`` decorator in
331+
the test suite.
332+
333+
.. note::
334+
Not compatible with positional-only arguments.
335+
336+
.. note::
337+
Documentation for the function may updated to reflect the new parameter
338+
name; it is suggested to add a |.. versionchanged::| directive.
339+
340+
Parameters
341+
----------
342+
since : str
343+
The release at which this API became deprecated.
344+
old_param_name : str
345+
The name of the deprecated parameter.
346+
new_param_name : str
347+
The name of the new parameter.
348+
removal : str, optional
349+
The expected removal version, in order to compose the Warning message.
350+
351+
Examples
352+
--------
353+
@renamed_kwarg('1.4.0', 'old_name', 'new_name')
354+
def some_function(new_name=None):
355+
pass
356+
"""
357+
358+
def deprecate(func, old=old_param_name, new=new_param_name, since=since):
359+
def wrapper(*args, **kwargs):
360+
if old in kwargs:
361+
if new in kwargs:
362+
raise ValueError(
363+
f"{func.__name__} received both '{old}' and '{new}', "
364+
"which are mutually exclusive since they refer to the "
365+
f"same parameter. Please remove deprecated '{old}'."
366+
)
367+
warnings.warn(
368+
f"Parameter '{old}' has been renamed since {since}. "
369+
f"and will be removed "
370+
+ ("in {removal}." if removal else "soon.")
371+
+ f"Please use '{new}' instead.",
372+
_projectWarning,
373+
stacklevel=2,
374+
)
375+
kwargs[new] = kwargs.pop(old)
376+
return func(*args, **kwargs)
377+
378+
wrapper = functools.wraps(func)(wrapper)
379+
return wrapper
380+
381+
return deprecate

pvlib/tests/test__deprecation.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""
2+
Test the _deprecation module.
3+
"""
4+
5+
import pytest
6+
7+
from pvlib import _deprecation
8+
9+
10+
@pytest.fixture
11+
def renamed_kwarg_func():
12+
"""Returns a function decorated by renamed_kwarg_warning."""
13+
@_deprecation.renamed_kwarg_warning(
14+
"0.1.0", "old_kwarg", "new_kwarg", "0.2.0"
15+
)
16+
def func(new_kwarg):
17+
return new_kwarg
18+
19+
return func
20+
21+
22+
def test_renamed_kwarg_warning(renamed_kwarg_func):
23+
# assert no warning is raised when using the new kwarg
24+
assert renamed_kwarg_func(new_kwarg=1) == 1
25+
26+
# assert a warning is raised when using the old kwarg
27+
with pytest.warns(Warning, match="Parameter 'old_kwarg' has been renamed"):
28+
assert renamed_kwarg_func(old_kwarg=1) == 1
29+
30+
# assert an error is raised when using both the old and new kwarg
31+
with pytest.raises(ValueError, match="they refer to the same parameter."):
32+
renamed_kwarg_func(old_kwarg=1, new_kwarg=2)
33+
34+
# assert when not providing any of them
35+
with pytest.raises(
36+
TypeError, match="missing 1 required positional argument"
37+
):
38+
renamed_kwarg_func()

0 commit comments

Comments
 (0)