Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
19 changes: 19 additions & 0 deletions Lib/math/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
math module -- Mathematical functions
"""

from _math import *

# gh-140824: Fix module name for pickle
def patch_module(objs, module):
Comment on lines +8 to +9
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be better just to have the module name as math.integer for these functions in C?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In C, function.__module__ is set to the extension name: so set to _math or _math_integer. The whole purpose of this PR is to fix function.__module__.

for obj in objs:
if not hasattr(obj, "__module__"):
continue
obj.__module__ = module
patch_module([obj for name, obj in globals().items()
if not name.startswith('_')], 'math')

from _math_integer import comb, factorial, gcd, isqrt, lcm, perm
patch_module([comb, factorial, gcd, isqrt, lcm, perm], 'math.integer')

del patch_module
5 changes: 5 additions & 0 deletions Lib/math/integer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""
math.integer module -- integer-specific mathematics functions
"""

from _math_integer import *
18 changes: 18 additions & 0 deletions Lib/test/test_math.py
Original file line number Diff line number Diff line change
Expand Up @@ -2413,6 +2413,24 @@ def assertEqualSign(self, x, y):
self.assertEqual(x, y)
self.assertEqual(math.copysign(1.0, x), math.copysign(1.0, y))

def test_module(self):
# gh-140824: _math and _math_integer extensions are exported as math
# and math.integer names.
math_integer_names = set('comb factorial gcd isqrt lcm perm'.split())
for name in dir(math):
if name.startswith('_'):
continue
obj = getattr(math, name)
if not hasattr(obj, '__module__'):
continue

if name in math_integer_names:
module = 'math.integer'
else:
module = 'math'
with self.subTest(name=name):
self.assertEqual(obj.__module__, module)


class IsCloseTests(unittest.TestCase):
isclose = math.isclose # subclasses should override this
Expand Down
2 changes: 1 addition & 1 deletion Modules/Setup
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ PYTHONPATH=$(COREPYTHONPATH)
#array arraymodule.c
#binascii binascii.c
#cmath cmathmodule.c
#math mathmodule.c
#_math mathmodule.c
#_math_integer mathintegermodule.c
#mmap mmapmodule.c
#select selectmodule.c
Expand Down
2 changes: 1 addition & 1 deletion Modules/Setup.stdlib.in
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
@MODULE__ZONEINFO_TRUE@_zoneinfo _zoneinfo.c

# needs libm
@MODULE_MATH_TRUE@math mathmodule.c
@MODULE__MATH_TRUE@_math mathmodule.c
@MODULE_CMATH_TRUE@cmath cmathmodule.c
@MODULE__STATISTICS_TRUE@_statistics _statisticsmodule.c

Expand Down
31 changes: 2 additions & 29 deletions Modules/mathmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2976,7 +2976,6 @@ math_ulp_impl(PyObject *module, double x)
static int
math_exec(PyObject *module)
{

if (PyModule_Add(module, "pi", PyFloat_FromDouble(Py_MATH_PI)) < 0) {
return -1;
}
Expand All @@ -2993,32 +2992,6 @@ math_exec(PyObject *module)
if (PyModule_Add(module, "nan", PyFloat_FromDouble(fabs(Py_NAN))) < 0) {
return -1;
}

PyObject *intmath = PyImport_ImportModule("_math_integer");
if (!intmath) {
return -1;
}
#define IMPORT_FROM_INTMATH(NAME) do { \
if (PyModule_Add(module, #NAME, \
PyObject_GetAttrString(intmath, #NAME)) < 0) { \
Py_DECREF(intmath); \
return -1; \
} \
} while(0)

IMPORT_FROM_INTMATH(comb);
IMPORT_FROM_INTMATH(factorial);
IMPORT_FROM_INTMATH(gcd);
IMPORT_FROM_INTMATH(isqrt);
IMPORT_FROM_INTMATH(lcm);
IMPORT_FROM_INTMATH(perm);
if (_PyImport_SetModuleString("math.integer", intmath) < 0) {
Py_DECREF(intmath);
return -1;
}
if (PyModule_Add(module, "integer", intmath) < 0) {
return -1;
}
return 0;
}

Expand Down Expand Up @@ -3095,15 +3068,15 @@ PyDoc_STRVAR(module_doc,

static struct PyModuleDef mathmodule = {
PyModuleDef_HEAD_INIT,
.m_name = "math",
.m_name = "_math",
.m_doc = module_doc,
.m_size = 0,
.m_methods = math_methods,
.m_slots = math_slots,
};

PyMODINIT_FUNC
PyInit_math(void)
PyInit__math(void)
{
return PyModuleDef_Init(&mathmodule);
}
28 changes: 14 additions & 14 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -7913,7 +7913,7 @@ PY_STDLIB_MOD([_posixshmem],
dnl needs libm
PY_STDLIB_MOD_SIMPLE([_statistics], [], [$LIBM])
PY_STDLIB_MOD_SIMPLE([cmath], [], [$LIBM])
PY_STDLIB_MOD_SIMPLE([math], [], [$LIBM])
PY_STDLIB_MOD_SIMPLE([_math], [], [$LIBM])

dnl needs libm and on some platforms librt
PY_STDLIB_MOD_SIMPLE([_datetime], [], [$TIMEMODULE_LIB $LIBM])
Expand Down
Loading