gh-115231: Fill __module__ for built-in staticmethods (#115232)
Co-authored-by: Nikita Sobolev <mail@sobolevn.me>
Co-authored-by: Victor Stinner <vstinner@python.org>
diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py
index 375f456..fe14e7c 100644
--- a/Lib/test/test_funcattrs.py
+++ b/Lib/test/test_funcattrs.py
@@ -459,6 +459,24 @@ class BuiltinFunctionPropertiesTest(unittest.TestCase):
# XXX Not sure where this should really go since I can't find a
# test module specifically for builtin_function_or_method.
+ def test_builtin__module__(self):
+ import math
+
+ # builtin function:
+ self.assertEqual(len.__module__, 'builtins')
+ self.assertEqual(math.sin.__module__, 'math')
+
+ # instance method:
+ self.assertRaises(AttributeError, getattr, int.to_bytes, '__module__')
+ self.assertEqual(int.to_bytes.__objclass__.__module__, 'builtins')
+
+ # builtin classmethod:
+ self.assertEqual(int.from_bytes.__module__, None)
+ self.assertEqual(int.from_bytes.__self__.__module__, 'builtins')
+
+ # builtin staticmethod:
+ self.assertEqual(bytes.maketrans.__module__, 'builtins')
+
def test_builtin__qualname__(self):
import time
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2024-02-10-05-42-26.gh-issue-115231.6T7dzi.rst b/Misc/NEWS.d/next/Core_and_Builtins/2024-02-10-05-42-26.gh-issue-115231.6T7dzi.rst
new file mode 100644
index 0000000..0e41bc9
--- /dev/null
+++ b/Misc/NEWS.d/next/Core_and_Builtins/2024-02-10-05-42-26.gh-issue-115231.6T7dzi.rst
@@ -0,0 +1,2 @@
+Setup ``__module__`` attribute for built-in static methods. Patch by Sergey
+B Kirpichev.
diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index 54263fd..2905b9b 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -8361,7 +8361,15 @@ type_add_method(PyTypeObject *type, PyMethodDef *meth)
descr = PyDescr_NewClassMethod(type, meth);
}
else if (meth->ml_flags & METH_STATIC) {
- PyObject *cfunc = PyCFunction_NewEx(meth, (PyObject*)type, NULL);
+ PyObject *mod = type_module(type);
+ if (mod == NULL) {
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
+ return -1;
+ }
+ PyErr_Clear();
+ }
+ PyObject *cfunc = PyCFunction_NewEx(meth, (PyObject*)type, mod);
+ Py_XDECREF(mod);
if (cfunc == NULL) {
return -1;
}