Skip to content

Commit

Permalink
bpo-28876: bool of large range raises OverflowError (python#699)
Browse files Browse the repository at this point in the history
  • Loading branch information
4kir4 authored and serhiy-storchaka committed Mar 20, 2017
1 parent 6450878 commit e46fb86
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 5 deletions.
17 changes: 13 additions & 4 deletions Lib/test/test_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,20 +98,24 @@ def test_large_operands(self):
x = range(10**20+10, 10**20, 3)
self.assertEqual(len(x), 0)
self.assertEqual(len(list(x)), 0)
self.assertFalse(x)

x = range(10**20, 10**20+10, -3)
self.assertEqual(len(x), 0)
self.assertEqual(len(list(x)), 0)
self.assertFalse(x)

x = range(10**20+10, 10**20, -3)
self.assertEqual(len(x), 4)
self.assertEqual(len(list(x)), 4)
self.assertTrue(x)

# Now test range() with longs
self.assertEqual(list(range(-2**100)), [])
self.assertEqual(list(range(0, -2**100)), [])
self.assertEqual(list(range(0, 2**100, -1)), [])
self.assertEqual(list(range(0, 2**100, -1)), [])
for x in [range(-2**100),
range(0, -2**100),
range(0, 2**100, -1)]:
self.assertEqual(list(x), [])
self.assertFalse(x)

a = int(10 * sys.maxsize)
b = int(100 * sys.maxsize)
Expand Down Expand Up @@ -152,13 +156,15 @@ def _range_len(x):
step = x[1] - x[0]
length = 1 + ((x[-1] - x[0]) // step)
return length

a = -sys.maxsize
b = sys.maxsize
expected_len = b - a
x = range(a, b)
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
Expand All @@ -176,6 +182,7 @@ def _range_len(x):
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
Expand All @@ -194,6 +201,7 @@ def _range_len(x):
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
Expand All @@ -212,6 +220,7 @@ def _range_len(x):
self.assertIn(a, x)
self.assertNotIn(b, x)
self.assertRaises(OverflowError, len, x)
self.assertTrue(x)
self.assertEqual(_range_len(x), expected_len)
self.assertEqual(x[0], a)
idx = sys.maxsize+1
Expand Down
3 changes: 3 additions & 0 deletions Misc/NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ Core and Builtins
- bpo-28893: Set correct __cause__ for errors about invalid awaitables
returned from __aiter__ and __anext__.

- bpo-28876: ``bool(range)`` works even if ``len(range)``
raises :exc:`OverflowError`.

- bpo-29683: Fixes to memory allocation in _PyCode_SetExtra. Patch by
Brian Coleman.

Expand Down
12 changes: 11 additions & 1 deletion Objects/rangeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,16 @@ static PyMappingMethods range_as_mapping = {
(objobjargproc)0, /* mp_ass_subscript */
};

static int
range_bool(rangeobject* self)
{
return PyObject_IsTrue(self->length);
}

static PyNumberMethods range_as_number = {
.nb_bool = (inquiry)range_bool,
};

static PyObject * range_iter(PyObject *seq);
static PyObject * range_reverse(PyObject *seq);

Expand Down Expand Up @@ -707,7 +717,7 @@ PyTypeObject PyRange_Type = {
0, /* tp_setattr */
0, /* tp_reserved */
(reprfunc)range_repr, /* tp_repr */
0, /* tp_as_number */
&range_as_number, /* tp_as_number */
&range_as_sequence, /* tp_as_sequence */
&range_as_mapping, /* tp_as_mapping */
(hashfunc)range_hash, /* tp_hash */
Expand Down

0 comments on commit e46fb86

Please sign in to comment.