diff --git a/Doc/library/inspect.rst b/Doc/library/inspect.rst index b463c0b6d0e402..691d6ae0589cc1 100644 --- a/Doc/library/inspect.rst +++ b/Doc/library/inspect.rst @@ -1086,24 +1086,11 @@ Classes and functions ``**`` arguments, if any) to their values from *args* and *kwds*. In case of invoking *func* incorrectly, i.e. whenever ``func(*args, **kwds)`` would raise an exception because of incompatible signature, an exception of the same type - and the same or similar message is raised. For example:: - - >>> from inspect import getcallargs - >>> def f(a, b=1, *pos, **named): - ... pass - ... - >>> getcallargs(f, 1, 2, 3) == {'a': 1, 'named': {}, 'b': 2, 'pos': (3,)} - True - >>> getcallargs(f, a=2, x=4) == {'a': 2, 'named': {'x': 4}, 'b': 1, 'pos': ()} - True - >>> getcallargs(f) - Traceback (most recent call last): - ... - TypeError: f() missing 1 required positional argument: 'a' + and the same or similar message is raised. .. versionadded:: 3.2 - .. deprecated:: 3.5 + .. deprecated-removed:: 3.5 3.15 Use :meth:`Signature.bind` and :meth:`Signature.bind_partial` instead. diff --git a/Doc/whatsnew/3.13.rst b/Doc/whatsnew/3.13.rst index 4d05bce34ef847..f56a8c469274fb 100644 --- a/Doc/whatsnew/3.13.rst +++ b/Doc/whatsnew/3.13.rst @@ -581,6 +581,12 @@ Pending Removal in Python 3.15 All arguments will be removed from :func:`threading.RLock` in Python 3.15. (Contributed by Nikita Sobolev in :gh:`102029`.) +* :func:`inspect.getcallargs` has been deprecated since Python 3.5. + Issue a runtime warning and slate it for removal in Python 3.15. + Use :meth:`inspect.Signature.bind` + or :meth:`inspect.Signature.bind_partial` instead. + (Contributed by Nikita Sobolev in :gh:`108901`.) + Pending Removal in Python 3.16 ------------------------------ diff --git a/Lib/inspect.py b/Lib/inspect.py index aaa22bef896602..f254c6e5428e5e 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -1579,6 +1579,13 @@ def getcallargs(func, /, *positional, **named): A dict is returned, with keys the function argument names (including the names of the * and ** arguments, if any), and values the respective bound values from 'positional' and 'named'.""" + import warnings + warnings._deprecated( + "getcallargs", + '{name!r} is deprecated since Python 3.5 and slated for removal in Python {remove}; ' + 'use `inspect.Singature.bind` instead', + remove=(3, 15), + ) spec = getfullargspec(func) args, varargs, varkw, defaults, kwonlyargs, kwonlydefaults, ann = spec f_name = func.__name__ diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index becbb0498bbb3f..b0e76c2621d386 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -1810,12 +1810,20 @@ def test_builtins_as_module(self): class TestGetcallargsFunctions(unittest.TestCase): + def assertDeprecated(self): + import re + return self.assertWarnsRegex( + DeprecationWarning, + re.escape("'getcallargs' is deprecated since Python 3.5 " + "and slated for removal in Python 3.15"), + ) def assertEqualCallArgs(self, func, call_params_string, locs=None): locs = dict(locs or {}, func=func) r1 = eval('func(%s)' % call_params_string, None, locs) - r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None, - locs) + with self.assertDeprecated(): + r2 = eval('inspect.getcallargs(func, %s)' % call_params_string, None, + locs) self.assertEqual(r1, r2) def assertEqualException(self, func, call_param_string, locs=None): @@ -1827,8 +1835,9 @@ def assertEqualException(self, func, call_param_string, locs=None): else: self.fail('Exception not raised') try: - eval('inspect.getcallargs(func, %s)' % call_param_string, None, - locs) + with self.assertDeprecated(): + eval('inspect.getcallargs(func, %s)' % call_param_string, None, + locs) except Exception as e: ex2 = e else: @@ -1987,14 +1996,16 @@ def test_errors(self): def f5(*, a): pass with self.assertRaisesRegex(TypeError, 'missing 1 required keyword-only'): - inspect.getcallargs(f5) + with self.assertDeprecated(): + inspect.getcallargs(f5) # issue20817: def f6(a, b, c): pass with self.assertRaisesRegex(TypeError, "'a', 'b' and 'c'"): - inspect.getcallargs(f6) + with self.assertDeprecated(): + inspect.getcallargs(f6) # bpo-33197 with self.assertRaisesRegex(ValueError, diff --git a/Misc/NEWS.d/next/Library/2023-11-18-17-01-45.gh-issue-108901.T3p5ie.rst b/Misc/NEWS.d/next/Library/2023-11-18-17-01-45.gh-issue-108901.T3p5ie.rst new file mode 100644 index 00000000000000..8b763eb8397eca --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-11-18-17-01-45.gh-issue-108901.T3p5ie.rst @@ -0,0 +1,3 @@ +Add a runtime ``DeprecationWarning`` to :func:`inspect.getcallargs` and +slate it for removal in Python 3.15. It was soft-deprecated in Python 3.5. +Use :meth:`inspect.Signature.bind` instead.