diff --git a/Lib/test/test_funcattrs.py b/Lib/test/test_funcattrs.py index d919d62613ea7c..fd43e8a7f3c994 100644 --- a/Lib/test/test_funcattrs.py +++ b/Lib/test/test_funcattrs.py @@ -458,6 +458,29 @@ 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 decimal + 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.assertRaises(AttributeError, getattr, decimal.Decimal.exp, '__module__') + self.assertEqual(int.to_bytes.__objclass__.__module__, 'builtins') + self.assertEqual(decimal.Decimal.exp.__objclass__.__module__, 'decimal') + + # builtin classmethod: + self.assertEqual(int.from_bytes.__module__, 'builtins') + self.assertEqual(int.from_bytes.__self__.__module__, 'builtins') + self.assertEqual(decimal.Decimal.from_float.__module__, 'decimal') + self.assertEqual(decimal.Decimal.from_float.__self__.__module__, 'decimal') + + # 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 00000000000000..12c622f6c086c4 --- /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 class/static methods. Patch by +Sergey B Kirpichev. diff --git a/Objects/descrobject.c b/Objects/descrobject.c index 4eccd1704eb95a..d280bf7adfc8e6 100644 --- a/Objects/descrobject.c +++ b/Objects/descrobject.c @@ -130,7 +130,11 @@ classmethod_get(PyObject *self, PyObject *obj, PyObject *type) if (descr->d_method->ml_flags & METH_METHOD) { cls = descr->d_common.d_type; } - return PyCMethod_New(descr->d_method, type, NULL, cls); + PyObject *mod = PyObject_GetAttr((PyObject*)type, &_Py_ID(__module__)); + PyErr_Clear(); + PyObject *result = PyCMethod_New(descr->d_method, type, mod, cls); + Py_XDECREF(mod); + return result; } static PyObject * diff --git a/Objects/typeobject.c b/Objects/typeobject.c index b4a11195613d74..e87763a54d4ae8 100644 --- a/Objects/typeobject.c +++ b/Objects/typeobject.c @@ -7611,7 +7611,10 @@ 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 = PyObject_GetAttr((PyObject*)type, &_Py_ID(__module__)); + PyErr_Clear(); + PyObject *cfunc = PyCFunction_NewEx(meth, (PyObject*)type, mod); + Py_XDECREF(mod); if (cfunc == NULL) { return -1; }