Skip to content

Commit da915c0

Browse files
committed
Use PyNumber_Index in the non-float branch of math_factorial and add deprecation warning for floats
1 parent 745c0f3 commit da915c0

File tree

2 files changed

+35
-15
lines changed

2 files changed

+35
-15
lines changed

Lib/test/test_math.py

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from test import support
66
import unittest
77
import itertools
8+
import decimal
89
import math
910
import os
1011
import platform
@@ -497,26 +498,33 @@ def testFabs(self):
497498

498499
def testFactorial(self):
499500
self.assertEqual(math.factorial(0), 1)
500-
self.assertEqual(math.factorial(0.0), 1)
501-
total = 1
502-
for i in range(1, 1000):
503-
total *= i
504-
self.assertEqual(math.factorial(i), total)
505-
self.assertEqual(math.factorial(float(i)), total)
506-
self.assertEqual(math.factorial(i), py_factorial(i))
501+
with self.assertWarns(DeprecationWarning):
502+
self.assertEqual(math.factorial(0.0), 1)
503+
total = 1
504+
for i in range(1, 1000):
505+
total *= i
506+
self.assertEqual(math.factorial(i), total)
507+
self.assertEqual(math.factorial(float(i)), total)
508+
self.assertEqual(math.factorial(i), py_factorial(i))
507509
self.assertRaises(ValueError, math.factorial, -1)
508-
self.assertRaises(ValueError, math.factorial, -1.0)
509-
self.assertRaises(ValueError, math.factorial, -10**100)
510-
self.assertRaises(ValueError, math.factorial, -1e100)
511-
self.assertRaises(ValueError, math.factorial, math.pi)
510+
with self.assertWarns(DeprecationWarning):
511+
self.assertRaises(ValueError, math.factorial, -1.0)
512+
self.assertRaises(ValueError, math.factorial, -10**100)
513+
self.assertRaises(ValueError, math.factorial, -1e100)
514+
self.assertRaises(ValueError, math.factorial, math.pi)
515+
516+
def testFactorialNonIntegers(self):
517+
self.assertRaises(TypeError, math.factorial, decimal.Decimal(5.2))
518+
self.assertRaises(TypeError, math.factorial, "5")
512519

513520
# Other implementations may place different upper bounds.
514521
@support.cpython_only
515522
def testFactorialHugeInputs(self):
516523
# Currently raises ValueError for inputs that are too large
517524
# to fit into a C long.
518525
self.assertRaises(OverflowError, math.factorial, 10**100)
519-
self.assertRaises(OverflowError, math.factorial, 1e100)
526+
with self.assertWarns(DeprecationWarning):
527+
self.assertRaises(OverflowError, math.factorial, 1e100)
520528

521529
def testFloor(self):
522530
self.assertRaises(TypeError, math.floor)

Modules/mathmodule.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,7 +1656,7 @@ math_factorial(PyObject *module, PyObject *arg)
16561656
{
16571657
long x;
16581658
int overflow;
1659-
PyObject *result, *odd_part, *two_valuation;
1659+
PyObject *result, *odd_part, *two_valuation, *pyint_form;
16601660

16611661
if (PyFloat_Check(arg)) {
16621662
PyObject *lx;
@@ -1671,9 +1671,21 @@ math_factorial(PyObject *module, PyObject *arg)
16711671
return NULL;
16721672
x = PyLong_AsLongAndOverflow(lx, &overflow);
16731673
Py_DECREF(lx);
1674+
if (PyErr_WarnEx(PyExc_DeprecationWarning,
1675+
"Passing float instances to math.factorial will be "
1676+
"removed in future versions.", 1) < 0) {
1677+
return NULL;
1678+
}
1679+
1680+
}
1681+
else{
1682+
pyint_form = PyNumber_Index(arg);
1683+
if( pyint_form == NULL){
1684+
return NULL;
1685+
}
1686+
x = PyLong_AsLongAndOverflow(pyint_form, &overflow);
1687+
Py_DECREF(pyint_form);
16741688
}
1675-
else
1676-
x = PyLong_AsLongAndOverflow(arg, &overflow);
16771689

16781690
if (x == -1 && PyErr_Occurred()) {
16791691
return NULL;

0 commit comments

Comments
 (0)