From 9789440de387219bb7677fe0d66860aa8c9deb02 Mon Sep 17 00:00:00 2001 From: Sergey B Kirpichev Date: Thu, 2 May 2024 17:44:33 +0300 Subject: gh-82062: Fix support of parameter defaults on methods in extension modules (GH-115270) Now inspect.signature() supports references to the module globals in parameter defaults on methods in extension modules. Previously it was only supported in functions. The workaround was to specify the fully qualified name, including the module name. --- Lib/inspect.py | 5 +++++ Lib/test/test_inspect/test_inspect.py | 7 +++++++ .../next/Library/2024-02-11-07-31-43.gh-issue-82062.eeS6w7.rst | 3 +++ Modules/_testcapi/docstring.c | 10 ++++++++++ 4 files changed, 25 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2024-02-11-07-31-43.gh-issue-82062.eeS6w7.rst diff --git a/Lib/inspect.py b/Lib/inspect.py index d46514f..a0c80bd 100644 --- a/Lib/inspect.py +++ b/Lib/inspect.py @@ -2285,7 +2285,12 @@ def _signature_fromstr(cls, obj, s, skip_bound_arg=True): module = None module_dict = {} + module_name = getattr(obj, '__module__', None) + if not module_name: + objclass = getattr(obj, '__objclass__', None) + module_name = getattr(objclass, '__module__', None) + if module_name: module = sys.modules.get(module_name, None) if module: diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index fbef34e..d122403 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -3069,6 +3069,13 @@ class TestSignatureObject(unittest.TestCase): self.assertEqual(inspect.signature(builtin), inspect.signature(template)) + @unittest.skipIf(MISSING_C_DOCSTRINGS, + "Signature information for builtins requires docstrings") + def test_signature_parsing_with_defaults(self): + _testcapi = import_helper.import_module("_testcapi") + meth = _testcapi.DocStringUnrepresentableSignatureTest.with_default + self.assertEqual(str(inspect.signature(meth)), '(self, /, x=1)') + def test_signature_on_non_function(self): with self.assertRaisesRegex(TypeError, 'is not a callable object'): inspect.signature(42) diff --git a/Misc/NEWS.d/next/Library/2024-02-11-07-31-43.gh-issue-82062.eeS6w7.rst b/Misc/NEWS.d/next/Library/2024-02-11-07-31-43.gh-issue-82062.eeS6w7.rst new file mode 100644 index 0000000..a57a591 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-02-11-07-31-43.gh-issue-82062.eeS6w7.rst @@ -0,0 +1,3 @@ +Fix :func:`inspect.signature()` to correctly handle parameter defaults +on methods in extension modules that use names defined in the module +namespace. diff --git a/Modules/_testcapi/docstring.c b/Modules/_testcapi/docstring.c index d99fbdd..3f7acba 100644 --- a/Modules/_testcapi/docstring.c +++ b/Modules/_testcapi/docstring.c @@ -169,6 +169,13 @@ static PyMethodDef DocStringUnrepresentableSignatureTest_methods[] = { "--\n\n" "This docstring has a signature with unrepresentable default." )}, + {"with_default", + (PyCFunction)test_with_docstring, METH_VARARGS, + PyDoc_STR( + "with_default($self, /, x=ONE)\n" + "--\n\n" + "This instance method has a default parameter value from the module scope." + )}, {NULL}, }; @@ -193,5 +200,8 @@ _PyTestCapi_Init_Docstring(PyObject *mod) if (PyModule_AddType(mod, &DocStringUnrepresentableSignatureTest) < 0) { return -1; } + if (PyModule_AddObject(mod, "ONE", PyLong_FromLong(1)) < 0) { + return -1; + } return 0; } -- cgit v0.12