Issue #28019: itertools.count() no longer rounds non-integer step in range
between 1.0 and 2.0 to 1.
This commit is contained in:
commit
8f9cafad3d
|
@ -510,12 +510,18 @@ class TestBasicOps(unittest.TestCase):
|
||||||
self.assertEqual(take(2, zip('abc',count(-3))), [('a', -3), ('b', -2)])
|
self.assertEqual(take(2, zip('abc',count(-3))), [('a', -3), ('b', -2)])
|
||||||
self.assertRaises(TypeError, count, 2, 3, 4)
|
self.assertRaises(TypeError, count, 2, 3, 4)
|
||||||
self.assertRaises(TypeError, count, 'a')
|
self.assertRaises(TypeError, count, 'a')
|
||||||
self.assertEqual(list(islice(count(maxsize-5), 10)),
|
self.assertEqual(take(10, count(maxsize-5)),
|
||||||
list(range(maxsize-5, maxsize+5)))
|
list(range(maxsize-5, maxsize+5)))
|
||||||
self.assertEqual(list(islice(count(-maxsize-5), 10)),
|
self.assertEqual(take(10, count(-maxsize-5)),
|
||||||
list(range(-maxsize-5, -maxsize+5)))
|
list(range(-maxsize-5, -maxsize+5)))
|
||||||
self.assertEqual(list(islice(count(10, maxsize+5), 3)),
|
self.assertEqual(take(3, count(3.25)), [3.25, 4.25, 5.25])
|
||||||
list(range(10, 10+3*(maxsize+5), maxsize+5)))
|
self.assertEqual(take(3, count(3.25-4j)), [3.25-4j, 4.25-4j, 5.25-4j])
|
||||||
|
self.assertEqual(take(3, count(Decimal('1.1'))),
|
||||||
|
[Decimal('1.1'), Decimal('2.1'), Decimal('3.1')])
|
||||||
|
self.assertEqual(take(3, count(Fraction(2, 3))),
|
||||||
|
[Fraction(2, 3), Fraction(5, 3), Fraction(8, 3)])
|
||||||
|
BIGINT = 1<<1000
|
||||||
|
self.assertEqual(take(3, count(BIGINT)), [BIGINT, BIGINT+1, BIGINT+2])
|
||||||
c = count(3)
|
c = count(3)
|
||||||
self.assertEqual(repr(c), 'count(3)')
|
self.assertEqual(repr(c), 'count(3)')
|
||||||
next(c)
|
next(c)
|
||||||
|
@ -523,8 +529,10 @@ class TestBasicOps(unittest.TestCase):
|
||||||
c = count(-9)
|
c = count(-9)
|
||||||
self.assertEqual(repr(c), 'count(-9)')
|
self.assertEqual(repr(c), 'count(-9)')
|
||||||
next(c)
|
next(c)
|
||||||
self.assertEqual(repr(count(10.25)), 'count(10.25)')
|
|
||||||
self.assertEqual(next(c), -8)
|
self.assertEqual(next(c), -8)
|
||||||
|
self.assertEqual(repr(count(10.25)), 'count(10.25)')
|
||||||
|
self.assertEqual(repr(count(10.0)), 'count(10.0)')
|
||||||
|
self.assertEqual(type(next(count(10.0))), float)
|
||||||
for i in (-sys.maxsize-5, -sys.maxsize+5 ,-10, -1, 0, 10, sys.maxsize-5, sys.maxsize+5):
|
for i in (-sys.maxsize-5, -sys.maxsize+5 ,-10, -1, 0, 10, sys.maxsize-5, sys.maxsize+5):
|
||||||
# Test repr
|
# Test repr
|
||||||
r1 = repr(count(i))
|
r1 = repr(count(i))
|
||||||
|
@ -548,16 +556,22 @@ class TestBasicOps(unittest.TestCase):
|
||||||
[('a', 2), ('b', 5), ('c', 8)])
|
[('a', 2), ('b', 5), ('c', 8)])
|
||||||
self.assertEqual(lzip('abc',count(step=-1)),
|
self.assertEqual(lzip('abc',count(step=-1)),
|
||||||
[('a', 0), ('b', -1), ('c', -2)])
|
[('a', 0), ('b', -1), ('c', -2)])
|
||||||
|
self.assertRaises(TypeError, count, 'a', 'b')
|
||||||
self.assertEqual(lzip('abc',count(2,0)), [('a', 2), ('b', 2), ('c', 2)])
|
self.assertEqual(lzip('abc',count(2,0)), [('a', 2), ('b', 2), ('c', 2)])
|
||||||
self.assertEqual(lzip('abc',count(2,1)), [('a', 2), ('b', 3), ('c', 4)])
|
self.assertEqual(lzip('abc',count(2,1)), [('a', 2), ('b', 3), ('c', 4)])
|
||||||
self.assertEqual(lzip('abc',count(2,3)), [('a', 2), ('b', 5), ('c', 8)])
|
self.assertEqual(lzip('abc',count(2,3)), [('a', 2), ('b', 5), ('c', 8)])
|
||||||
self.assertEqual(take(20, count(maxsize-15, 3)), take(20, range(maxsize-15, maxsize+100, 3)))
|
self.assertEqual(take(20, count(maxsize-15, 3)), take(20, range(maxsize-15, maxsize+100, 3)))
|
||||||
self.assertEqual(take(20, count(-maxsize-15, 3)), take(20, range(-maxsize-15,-maxsize+100, 3)))
|
self.assertEqual(take(20, count(-maxsize-15, 3)), take(20, range(-maxsize-15,-maxsize+100, 3)))
|
||||||
|
self.assertEqual(take(3, count(10, maxsize+5)),
|
||||||
|
list(range(10, 10+3*(maxsize+5), maxsize+5)))
|
||||||
|
self.assertEqual(take(3, count(2, 1.25)), [2, 3.25, 4.5])
|
||||||
self.assertEqual(take(3, count(2, 3.25-4j)), [2, 5.25-4j, 8.5-8j])
|
self.assertEqual(take(3, count(2, 3.25-4j)), [2, 5.25-4j, 8.5-8j])
|
||||||
self.assertEqual(take(3, count(Decimal('1.1'), Decimal('.1'))),
|
self.assertEqual(take(3, count(Decimal('1.1'), Decimal('.1'))),
|
||||||
[Decimal('1.1'), Decimal('1.2'), Decimal('1.3')])
|
[Decimal('1.1'), Decimal('1.2'), Decimal('1.3')])
|
||||||
self.assertEqual(take(3, count(Fraction(2,3), Fraction(1,7))),
|
self.assertEqual(take(3, count(Fraction(2,3), Fraction(1,7))),
|
||||||
[Fraction(2,3), Fraction(17,21), Fraction(20,21)])
|
[Fraction(2,3), Fraction(17,21), Fraction(20,21)])
|
||||||
|
BIGINT = 1<<1000
|
||||||
|
self.assertEqual(take(3, count(step=BIGINT)), [0, BIGINT, 2*BIGINT])
|
||||||
self.assertEqual(repr(take(3, count(10, 2.5))), repr([10, 12.5, 15.0]))
|
self.assertEqual(repr(take(3, count(10, 2.5))), repr([10, 12.5, 15.0]))
|
||||||
c = count(3, 5)
|
c = count(3, 5)
|
||||||
self.assertEqual(repr(c), 'count(3, 5)')
|
self.assertEqual(repr(c), 'count(3, 5)')
|
||||||
|
@ -575,6 +589,10 @@ class TestBasicOps(unittest.TestCase):
|
||||||
self.assertEqual(repr(count(10.5, 1.25)), 'count(10.5, 1.25)')
|
self.assertEqual(repr(count(10.5, 1.25)), 'count(10.5, 1.25)')
|
||||||
self.assertEqual(repr(count(10.5, 1)), 'count(10.5)') # suppress step=1 when it's an int
|
self.assertEqual(repr(count(10.5, 1)), 'count(10.5)') # suppress step=1 when it's an int
|
||||||
self.assertEqual(repr(count(10.5, 1.00)), 'count(10.5, 1.0)') # do show float values lilke 1.0
|
self.assertEqual(repr(count(10.5, 1.00)), 'count(10.5, 1.0)') # do show float values lilke 1.0
|
||||||
|
self.assertEqual(repr(count(10, 1.00)), 'count(10, 1.0)')
|
||||||
|
c = count(10, 1.0)
|
||||||
|
self.assertEqual(type(next(c)), int)
|
||||||
|
self.assertEqual(type(next(c)), float)
|
||||||
for i in (-sys.maxsize-5, -sys.maxsize+5 ,-10, -1, 0, 10, sys.maxsize-5, sys.maxsize+5):
|
for i in (-sys.maxsize-5, -sys.maxsize+5 ,-10, -1, 0, 10, sys.maxsize-5, sys.maxsize+5):
|
||||||
for j in (-sys.maxsize-5, -sys.maxsize+5 ,-10, -1, 0, 1, 10, sys.maxsize-5, sys.maxsize+5):
|
for j in (-sys.maxsize-5, -sys.maxsize+5 ,-10, -1, 0, 1, 10, sys.maxsize-5, sys.maxsize+5):
|
||||||
# Test repr
|
# Test repr
|
||||||
|
|
|
@ -135,6 +135,9 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #28019: itertools.count() no longer rounds non-integer step in range
|
||||||
|
between 1.0 and 2.0 to 1.
|
||||||
|
|
||||||
- Issue #18401: Pdb now supports the 'readrc' keyword argument to control
|
- Issue #18401: Pdb now supports the 'readrc' keyword argument to control
|
||||||
whether .pdbrc files should be read. Patch by Martin Matusiak and
|
whether .pdbrc files should be read. Patch by Martin Matusiak and
|
||||||
Sam Kimbrel.
|
Sam Kimbrel.
|
||||||
|
|
|
@ -3907,7 +3907,7 @@ static PyObject *
|
||||||
count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
{
|
{
|
||||||
countobject *lz;
|
countobject *lz;
|
||||||
int slow_mode = 0;
|
int fast_mode;
|
||||||
Py_ssize_t cnt = 0;
|
Py_ssize_t cnt = 0;
|
||||||
PyObject *long_cnt = NULL;
|
PyObject *long_cnt = NULL;
|
||||||
PyObject *long_step = NULL;
|
PyObject *long_step = NULL;
|
||||||
|
@ -3924,16 +3924,26 @@ count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fast_mode = (long_cnt == NULL || PyLong_Check(long_cnt)) &&
|
||||||
|
(long_step == NULL || PyLong_Check(long_step));
|
||||||
|
|
||||||
|
/* If not specified, start defaults to 0 */
|
||||||
if (long_cnt != NULL) {
|
if (long_cnt != NULL) {
|
||||||
cnt = PyLong_AsSsize_t(long_cnt);
|
if (fast_mode) {
|
||||||
if ((cnt == -1 && PyErr_Occurred()) || !PyLong_Check(long_cnt)) {
|
assert(PyLong_Check(long_cnt));
|
||||||
PyErr_Clear();
|
cnt = PyLong_AsSsize_t(long_cnt);
|
||||||
slow_mode = 1;
|
if (cnt == -1 && PyErr_Occurred()) {
|
||||||
|
PyErr_Clear();
|
||||||
|
fast_mode = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Py_INCREF(long_cnt);
|
Py_INCREF(long_cnt);
|
||||||
} else {
|
} else {
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
long_cnt = PyLong_FromLong(0);
|
long_cnt = PyLong_FromLong(0);
|
||||||
|
if (long_cnt == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If not specified, step defaults to 1 */
|
/* If not specified, step defaults to 1 */
|
||||||
|
@ -3949,21 +3959,24 @@ count_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
|
||||||
assert(long_cnt != NULL && long_step != NULL);
|
assert(long_cnt != NULL && long_step != NULL);
|
||||||
|
|
||||||
/* Fast mode only works when the step is 1 */
|
/* Fast mode only works when the step is 1 */
|
||||||
step = PyLong_AsLong(long_step);
|
if (fast_mode) {
|
||||||
if (step != 1) {
|
assert(PyLong_Check(long_step));
|
||||||
slow_mode = 1;
|
step = PyLong_AsLong(long_step);
|
||||||
if (step == -1 && PyErr_Occurred())
|
if (step != 1) {
|
||||||
PyErr_Clear();
|
fast_mode = 0;
|
||||||
|
if (step == -1 && PyErr_Occurred())
|
||||||
|
PyErr_Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (slow_mode)
|
if (fast_mode)
|
||||||
cnt = PY_SSIZE_T_MAX;
|
|
||||||
else
|
|
||||||
Py_CLEAR(long_cnt);
|
Py_CLEAR(long_cnt);
|
||||||
|
else
|
||||||
|
cnt = PY_SSIZE_T_MAX;
|
||||||
|
|
||||||
assert((cnt != PY_SSIZE_T_MAX && long_cnt == NULL && !slow_mode) ||
|
assert((cnt != PY_SSIZE_T_MAX && long_cnt == NULL && fast_mode) ||
|
||||||
(cnt == PY_SSIZE_T_MAX && long_cnt != NULL && slow_mode));
|
(cnt == PY_SSIZE_T_MAX && long_cnt != NULL && !fast_mode));
|
||||||
assert(slow_mode ||
|
assert(!fast_mode ||
|
||||||
(PyLong_Check(long_step) && PyLong_AS_LONG(long_step) == 1));
|
(PyLong_Check(long_step) && PyLong_AS_LONG(long_step) == 1));
|
||||||
|
|
||||||
/* create countobject structure */
|
/* create countobject structure */
|
||||||
|
|
Loading…
Reference in New Issue