From 4b35e7c20bf5e33e442609658e4061f957d033e8 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Sep 2022 12:35:01 -0700 Subject: [PATCH 1/9] Make deprecate_nonkeyword_arguments alter function signature --- .../test_deprecate_nonkeyword_arguments.py | 17 +++++++++++++ pandas/util/_decorators.py | 24 ++++++++++++++----- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/pandas/tests/util/test_deprecate_nonkeyword_arguments.py b/pandas/tests/util/test_deprecate_nonkeyword_arguments.py index 346561e0ba7ff..83166ee9d1aa4 100644 --- a/pandas/tests/util/test_deprecate_nonkeyword_arguments.py +++ b/pandas/tests/util/test_deprecate_nonkeyword_arguments.py @@ -2,6 +2,7 @@ Tests for the `deprecate_nonkeyword_arguments` decorator """ +import inspect import warnings from pandas.util._decorators import deprecate_nonkeyword_arguments @@ -16,6 +17,10 @@ def f(a, b=0, c=0, d=0): return a + b + c + d +def test_f_signature(): + assert str(inspect.signature(f)) == "(a, b=0, *, c=0, d=0)" + + def test_one_argument(): with tm.assert_produces_warning(None): assert f(19) == 19 @@ -65,6 +70,10 @@ def g(a, b=0, c=0, d=0): return a + b + c + d +def test_g_signature(): + assert str(inspect.signature(g)) == "(a, *, b=0, c=0, d=0)" + + def test_one_and_three_arguments_default_allowed_args(): with tm.assert_produces_warning(None): assert g(1, b=3, c=3, d=5) == 12 @@ -93,6 +102,10 @@ def h(a=0, b=0, c=0, d=0): return a + b + c + d +def test_h_signature(): + assert str(inspect.signature(h)) == "(*, a=0, b=0, c=0, d=0)" + + def test_all_keyword_arguments(): with tm.assert_produces_warning(None): assert h(a=1, b=2) == 3 @@ -122,6 +135,10 @@ def baz(self, bar=None, foobar=None): ... +def test_foo_signature(): + assert str(inspect.signature(Foo.baz)) == "(self, bar=None, *, foobar=None)" + + def test_class(): msg = ( r"In a future version of pandas all arguments of Foo\.baz " diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index f8359edaa8d44..f735af67241b2 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -290,14 +290,26 @@ def deprecate_nonkeyword_arguments( """ def decorate(func): + old_sig = inspect.signature(func) + if allowed_args is not None: allow_args = allowed_args else: - spec = inspect.getfullargspec(func) + allow_args = [ + p.name + for p in old_sig.parameters.values() + if p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD) + and p.default is p.empty + ] - # We must have some defaults if we are deprecating default-less - assert spec.defaults is not None # for mypy - allow_args = spec.args[: -len(spec.defaults)] + new_params = [ + p.replace(kind=p.KEYWORD_ONLY) + if (p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD) and p.name not in allow_args) + else p + for p in old_sig.parameters.values() + ] + new_params.sort(key=lambda p: p.kind) + new_sig = old_sig.replace(parameters=new_params) num_allow_args = len(allow_args) msg = ( @@ -307,15 +319,15 @@ def decorate(func): @wraps(func) def wrapper(*args, **kwargs): - arguments = _format_argument_list(allow_args) if len(args) > num_allow_args: warnings.warn( - msg.format(arguments=arguments), + msg.format(arguments=_format_argument_list(allow_args)), FutureWarning, stacklevel=find_stack_level(), ) return func(*args, **kwargs) + wrapper.__signature__ = new_sig return wrapper return decorate From 44014ede6502074b4d3c54d64b7e4d199738bc9f Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Sep 2022 12:46:28 -0700 Subject: [PATCH 2/9] reformat --- pandas/util/_decorators.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index d28044df3a244..883cc549bd30d 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -304,7 +304,10 @@ def decorate(func): new_params = [ p.replace(kind=p.KEYWORD_ONLY) - if (p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD) and p.name not in allow_args) + if ( + p.kind in (p.POSITIONAL_ONLY, p.POSITIONAL_OR_KEYWORD) + and p.name not in allow_args + ) else p for p in old_sig.parameters.values() ] From f642a043e5ca5c0ae32dc760b354dbc15a7c0030 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Sep 2022 13:24:00 -0700 Subject: [PATCH 3/9] type ignore --- pandas/util/_decorators.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 883cc549bd30d..0de96fd8d5d93 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -330,7 +330,7 @@ def wrapper(*args, **kwargs): ) return func(*args, **kwargs) - wrapper.__signature__ = new_sig + wrapper.__signature__ = new_sig # type: ignore[attr-defined] return wrapper return decorate From f60bd70e7b9c885815566e4bc05fa5be65267994 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Sep 2022 14:12:31 -0700 Subject: [PATCH 4/9] add comment --- pandas/util/_decorators.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/util/_decorators.py b/pandas/util/_decorators.py index 0de96fd8d5d93..e95025371a204 100644 --- a/pandas/util/_decorators.py +++ b/pandas/util/_decorators.py @@ -330,6 +330,8 @@ def wrapper(*args, **kwargs): ) return func(*args, **kwargs) + # error: "Callable[[VarArg(Any), KwArg(Any)], Any]" has no + # attribute "__signature__" wrapper.__signature__ = new_sig # type: ignore[attr-defined] return wrapper From 8b3e68cfb31754073e2fb6762cd6ec1fac189591 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Sep 2022 14:15:30 -0700 Subject: [PATCH 5/9] changelog entry --- doc/source/whatsnew/v1.6.0.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/whatsnew/v1.6.0.rst b/doc/source/whatsnew/v1.6.0.rst index 050dfacc13df0..e4bd6c078d4a5 100644 --- a/doc/source/whatsnew/v1.6.0.rst +++ b/doc/source/whatsnew/v1.6.0.rst @@ -35,6 +35,7 @@ Other enhancements - Added ``index`` parameter to :meth:`DataFrame.to_dict` (:issue:`46398`) - Added metadata propagation for binary operators on :class:`DataFrame` (:issue:`28283`) - :class:`.CategoricalConversionWarning`, :class:`.InvalidComparison`, :class:`.InvalidVersion`, :class:`.LossySetitemError`, and :class:`.NoBufferPresent` are now exposed in ``pandas.errors`` (:issue:`27656`) +- Avoid showing deprecated signatures when introspecting functions using ``deprecate_nonkeyword_arguments`` (:issue:`48692`) - .. --------------------------------------------------------------------------- From d3d912bc688b03c2cb5172f82f9e74f4100f6fed Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Wed, 21 Sep 2022 14:23:24 -0700 Subject: [PATCH 6/9] clearer phrasing --- doc/source/whatsnew/v1.6.0.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.6.0.rst b/doc/source/whatsnew/v1.6.0.rst index e4bd6c078d4a5..98498c6a27c40 100644 --- a/doc/source/whatsnew/v1.6.0.rst +++ b/doc/source/whatsnew/v1.6.0.rst @@ -35,7 +35,7 @@ Other enhancements - Added ``index`` parameter to :meth:`DataFrame.to_dict` (:issue:`46398`) - Added metadata propagation for binary operators on :class:`DataFrame` (:issue:`28283`) - :class:`.CategoricalConversionWarning`, :class:`.InvalidComparison`, :class:`.InvalidVersion`, :class:`.LossySetitemError`, and :class:`.NoBufferPresent` are now exposed in ``pandas.errors`` (:issue:`27656`) -- Avoid showing deprecated signatures when introspecting functions using ``deprecate_nonkeyword_arguments`` (:issue:`48692`) +- Avoid showing deprecated signatures when introspecting functions that use ``deprecate_nonkeyword_arguments`` (:issue:`48692`) - .. --------------------------------------------------------------------------- From b39ae267bf42d345cd686e49322509b21fa42479 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Thu, 22 Sep 2022 11:38:13 -0700 Subject: [PATCH 7/9] move changelog entry --- doc/source/whatsnew/v1.5.1.rst | 1 + doc/source/whatsnew/v1.6.0.rst | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.5.1.rst b/doc/source/whatsnew/v1.5.1.rst index 9d40d9118db32..bf2ce3053807d 100644 --- a/doc/source/whatsnew/v1.5.1.rst +++ b/doc/source/whatsnew/v1.5.1.rst @@ -32,6 +32,7 @@ Bug fixes Other ~~~~~ +- Avoid showing deprecated signatures when introspecting functions that use ``deprecate_nonkeyword_arguments`` (:issue:`48692`) - - diff --git a/doc/source/whatsnew/v1.6.0.rst b/doc/source/whatsnew/v1.6.0.rst index 98498c6a27c40..050dfacc13df0 100644 --- a/doc/source/whatsnew/v1.6.0.rst +++ b/doc/source/whatsnew/v1.6.0.rst @@ -35,7 +35,6 @@ Other enhancements - Added ``index`` parameter to :meth:`DataFrame.to_dict` (:issue:`46398`) - Added metadata propagation for binary operators on :class:`DataFrame` (:issue:`28283`) - :class:`.CategoricalConversionWarning`, :class:`.InvalidComparison`, :class:`.InvalidVersion`, :class:`.LossySetitemError`, and :class:`.NoBufferPresent` are now exposed in ``pandas.errors`` (:issue:`27656`) -- Avoid showing deprecated signatures when introspecting functions that use ``deprecate_nonkeyword_arguments`` (:issue:`48692`) - .. --------------------------------------------------------------------------- From 5c4836af055ce673a634e8dd68d32ddba2ed6164 Mon Sep 17 00:00:00 2001 From: hauntsaninja Date: Mon, 26 Sep 2022 10:08:28 -0700 Subject: [PATCH 8/9] add test for positional-only --- pandas/tests/util/test_deprecate_nonkeyword_arguments.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/pandas/tests/util/test_deprecate_nonkeyword_arguments.py b/pandas/tests/util/test_deprecate_nonkeyword_arguments.py index 83166ee9d1aa4..f6501fa8315e4 100644 --- a/pandas/tests/util/test_deprecate_nonkeyword_arguments.py +++ b/pandas/tests/util/test_deprecate_nonkeyword_arguments.py @@ -129,6 +129,15 @@ def test_one_positional_argument_with_warning_message_analysis(): ) +@deprecate_nonkeyword_arguments(version="1.1") +def i(a=0, /, b=0, *, c=0, d=0): + return a + b + c + d + + +def test_i_signature(): + assert str(inspect.signature(i)) == "(*, a=0, b=0, c=0, d=0)" + + class Foo: @deprecate_nonkeyword_arguments(version=None, allowed_args=["self", "bar"]) def baz(self, bar=None, foobar=None): From 75769a7600d4f881869f694cd27cd87e1329dbd5 Mon Sep 17 00:00:00 2001 From: Shantanu <12621235+hauntsaninja@users.noreply.github.com> Date: Mon, 26 Sep 2022 10:19:25 -0700 Subject: [PATCH 9/9] Update doc/source/whatsnew/v1.5.1.rst Co-authored-by: Marco Edward Gorelli <33491632+MarcoGorelli@users.noreply.github.com> --- doc/source/whatsnew/v1.5.1.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v1.5.1.rst b/doc/source/whatsnew/v1.5.1.rst index bf2ce3053807d..3425659ec77d6 100644 --- a/doc/source/whatsnew/v1.5.1.rst +++ b/doc/source/whatsnew/v1.5.1.rst @@ -32,7 +32,7 @@ Bug fixes Other ~~~~~ -- Avoid showing deprecated signatures when introspecting functions that use ``deprecate_nonkeyword_arguments`` (:issue:`48692`) +- Avoid showing deprecated signatures when introspecting functions with warnings about arguments becoming keyword-only (:issue:`48692`) - -