https://github.com/python/cpython/commit/9789440de387219bb7677fe0d66860aa8c9deb02
commit: 9789440de387219bb7677fe0d66860aa8c9deb02
branch: main
author: Sergey B Kirpichev <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2024-05-02T17:44:33+03:00
summary:

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.

files:
A Misc/NEWS.d/next/Library/2024-02-11-07-31-43.gh-issue-82062.eeS6w7.rst
M Lib/inspect.py
M Lib/test/test_inspect/test_inspect.py
M Modules/_testcapi/docstring.c

diff --git a/Lib/inspect.py b/Lib/inspect.py
index d46514f4b10467..a0c80bd5c8b601 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 fbef34eddacb3a..d12240353ff832 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -3069,6 +3069,13 @@ def test_signature_on_builtins_no_signature(self):
                 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 00000000000000..a57a5918b135bb
--- /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 d99fbdd904b594..3f7acbae1b181b 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;
 }

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to