Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions Lib/test/test_funcattrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -453,6 +453,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
Comment thread
skirpichev marked this conversation as resolved.

# 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')
Comment thread
skirpichev marked this conversation as resolved.
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

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Setup ``__module__`` attribute for built-in class/static methods. Patch by
Sergey B Kirpichev.
6 changes: 5 additions & 1 deletion Objects/descrobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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__));
Comment thread
skirpichev marked this conversation as resolved.
Outdated
PyErr_Clear();
PyObject *result = PyCMethod_New(descr->d_method, type, mod, cls);
Py_XDECREF(mod);
return result;
}

static PyObject *
Expand Down
5 changes: 4 additions & 1 deletion Objects/typeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -6653,7 +6653,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__));
Comment thread
skirpichev marked this conversation as resolved.
Outdated
PyErr_Clear();
Comment thread
skirpichev marked this conversation as resolved.
Outdated
PyObject *cfunc = PyCFunction_NewEx(meth, (PyObject*)type, mod);
Py_XDECREF(mod);
if (cfunc == NULL) {
return -1;
}
Expand Down