diff -r 5715a6d9ff12 Lib/test/test_xrange.py --- a/Lib/test/test_xrange.py Wed Feb 10 13:44:29 2016 +0100 +++ b/Lib/test/test_xrange.py Wed Feb 24 18:34:22 2016 +0200 @@ -108,14 +108,14 @@ class XrangeTest(unittest.TestCase): self.assertRaises(TypeError, xrange, 0, "spam") self.assertRaises(TypeError, xrange, 0, 42, "spam") - self.assertEqual(len(xrange(0, sys.maxint, sys.maxint-1)), 2) + self.assertEqual(len(xrange(0, sys.maxsize, sys.maxsize-1)), 2) - self.assertRaises(OverflowError, xrange, -sys.maxint, sys.maxint) - self.assertRaises(OverflowError, xrange, 0, 2*sys.maxint) + self.assertRaises(OverflowError, xrange, -sys.maxsize, sys.maxsize) + self.assertRaises(OverflowError, xrange, 0, 2*sys.maxsize) - r = xrange(-sys.maxint, sys.maxint, 2) - self.assertEqual(len(r), sys.maxint) - self.assertRaises(OverflowError, xrange, -sys.maxint-1, sys.maxint, 2) + r = xrange(-sys.maxsize, sys.maxsize, 2) + self.assertEqual(len(r), sys.maxsize) + self.assertRaises(OverflowError, xrange, -sys.maxsize-1, sys.maxsize, 2) def test_pickling(self): testcases = [(13,), (0, 11), (-22, 10), (20, 3, -1), @@ -126,7 +126,7 @@ class XrangeTest(unittest.TestCase): self.assertEqual(list(pickle.loads(pickle.dumps(r, proto))), list(r)) - M = min(sys.maxint, sys.maxsize) + M = sys.maxsize large_testcases = testcases + [ (0, M, 1), (M, 0, -1), @@ -151,8 +151,8 @@ class XrangeTest(unittest.TestCase): # Check that repr of an xrange is a valid representation # of that xrange. - # Valid xranges have at most min(sys.maxint, sys.maxsize) elements. - M = min(sys.maxint, sys.maxsize) + # Valid xranges have at most sys.maxsize elements. + M = sys.maxsize testcases = [ (13,), diff -r 5715a6d9ff12 Objects/rangeobject.c --- a/Objects/rangeobject.c Wed Feb 10 13:44:29 2016 +0100 +++ b/Objects/rangeobject.c Wed Feb 24 18:34:22 2016 +0200 @@ -4,16 +4,16 @@ typedef struct { PyObject_HEAD - long start; - long step; - long len; + Py_ssize_t start; + Py_ssize_t step; + Py_ssize_t len; } rangeobject; /* Return number of items in range (lo, hi, step). step != 0 - * required. The result always fits in an unsigned long. + * required. The result always fits in a size_t. */ -static unsigned long -get_len_of_range(long lo, long hi, long step) +static size_t +get_len_of_range(Py_ssize_t lo, Py_ssize_t hi, Py_ssize_t step) { /* ------------------------------------------------------------- If step > 0 and lo >= hi, or step < 0 and lo <= hi, the range is empty. @@ -22,9 +22,9 @@ get_len_of_range(long lo, long hi, long n <= (hi - lo - 1)/step + 1, so taking the floor of the RHS gives the proper value. Since lo < hi in this case, hi-lo-1 >= 0, so the RHS is non-negative and so truncation is the same as the - floor. Letting M be the largest positive long, the worst case + floor. Letting M be the largest positive Py_ssize_t, the worst case for the RHS numerator is hi=M, lo=-M-1, and then - hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore unsigned long has enough + hi-lo-1 = M-(-M-1)-1 = 2*M. Therefore size_t has enough precision to compute the RHS exactly. The analysis for step < 0 is similar. ---------------------------------------------------------------*/ @@ -39,47 +39,48 @@ get_len_of_range(long lo, long hi, long /* Return a stop value suitable for reconstructing the xrange from * a (start, stop, step) triple. Used in range_repr and range_reduce. - * Computes start + len * step, clipped to the range [LONG_MIN, LONG_MAX]. + * Computes start + len * step, clipped to the range + * [PY_SSIZE_T_MIN, PY_SSIZE_T_MAX]. */ -static long +static Py_ssize_t get_stop_for_range(rangeobject *r) { - long last; + Py_ssize_t last; if (r->len == 0) return r->start; /* The tricky bit is avoiding overflow. We first compute the last entry in the xrange, start + (len - 1) * step, which is guaranteed to lie within - the range of a long, and then add step to it. See the range_reverse + the range of a Py_ssize_t, and then add step to it. See the range_reverse comments for an explanation of the casts below. */ - last = (long)(r->start + (unsigned long)(r->len - 1) * r->step); + last = (Py_ssize_t)(r->start + (size_t)(r->len - 1) * r->step); if (r->step > 0) - return last > LONG_MAX - r->step ? LONG_MAX : last + r->step; + return last > PY_SSIZE_T_MAX - r->step ? PY_SSIZE_T_MAX : last + r->step; else - return last < LONG_MIN - r->step ? LONG_MIN : last + r->step; + return last < PY_SSIZE_T_MIN - r->step ? PY_SSIZE_T_MIN : last + r->step; } static PyObject * range_new(PyTypeObject *type, PyObject *args, PyObject *kw) { rangeobject *obj; - long ilow = 0, ihigh = 0, istep = 1; - unsigned long n; + Py_ssize_t ilow = 0, ihigh = 0, istep = 1; + size_t n; if (!_PyArg_NoKeywords("xrange()", kw)) return NULL; if (PyTuple_Size(args) <= 1) { if (!PyArg_ParseTuple(args, - "l;xrange() requires 1-3 int arguments", + "n;xrange() requires 1-3 int arguments", &ihigh)) return NULL; } else { if (!PyArg_ParseTuple(args, - "ll|l;xrange() requires 1-3 int arguments", + "nn|n;xrange() requires 1-3 int arguments", &ilow, &ihigh, &istep)) return NULL; } @@ -88,7 +89,7 @@ range_new(PyTypeObject *type, PyObject * return NULL; } n = get_len_of_range(ilow, ihigh, istep); - if (n > (unsigned long)LONG_MAX || (long)n > PY_SSIZE_T_MAX) { + if (n > (size_t)PY_SSIZE_T_MAX) { PyErr_SetString(PyExc_OverflowError, "xrange() result has too many items"); return NULL; @@ -98,7 +99,7 @@ range_new(PyTypeObject *type, PyObject * if (obj == NULL) return NULL; obj->start = ilow; - obj->len = (long)n; + obj->len = (Py_ssize_t)n; obj->step = istep; return (PyObject *) obj; } @@ -119,15 +120,15 @@ range_item(rangeobject *r, Py_ssize_t i) "xrange object index out of range"); return NULL; } - /* do calculation entirely using unsigned longs, to avoid + /* do calculation entirely using size_t, to avoid undefined behaviour due to signed overflow. */ - return PyInt_FromLong((long)(r->start + (unsigned long)i * r->step)); + return PyInt_FromSsize_t((Py_ssize_t)(r->start + (size_t)i * r->step)); } static Py_ssize_t range_length(rangeobject *r) { - return (Py_ssize_t)(r->len); + return r->len; } static PyObject * @@ -136,16 +137,16 @@ range_repr(rangeobject *r) PyObject *rtn; if (r->start == 0 && r->step == 1) - rtn = PyString_FromFormat("xrange(%ld)", + rtn = PyString_FromFormat("xrange(%zd)", get_stop_for_range(r)); else if (r->step == 1) - rtn = PyString_FromFormat("xrange(%ld, %ld)", + rtn = PyString_FromFormat("xrange(%zd, %zd)", r->start, get_stop_for_range(r)); else - rtn = PyString_FromFormat("xrange(%ld, %ld, %ld)", + rtn = PyString_FromFormat("xrange(%zd, %zd, %zd)", r->start, get_stop_for_range(r), r->step); @@ -228,24 +229,24 @@ PyTypeObject PyRange_Type = { typedef struct { PyObject_HEAD - long index; - long start; - long step; - long len; + Py_ssize_t index; + Py_ssize_t start; + Py_ssize_t step; + Py_ssize_t len; } rangeiterobject; static PyObject * rangeiter_next(rangeiterobject *r) { if (r->index < r->len) - return PyInt_FromLong(r->start + (r->index++) * r->step); + return PyInt_FromSsize_t(r->start + (r->index++) * r->step); return NULL; } static PyObject * rangeiter_len(rangeiterobject *r) { - return PyInt_FromLong(r->len - r->index); + return PyInt_FromSsize_t(r->len - r->index); } PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); @@ -312,7 +313,7 @@ static PyObject * range_reverse(PyObject *seq) { rangeiterobject *it; - long start, step, len; + Py_ssize_t start, step, len; if (!PyRange_Check(seq)) { PyErr_BadInternalCall(); @@ -330,18 +331,18 @@ range_reverse(PyObject *seq) it->len = len; /* the casts below guard against signed overflow by turning it into unsigned overflow instead. The correctness of this - code still depends on conversion from unsigned long to long - wrapping modulo ULONG_MAX+1, which isn't guaranteed (see + code still depends on conversion from size_t to Py_ssize_t + wrapping modulo PY_SIZE_MAX+1, which isn't guaranteed (see C99 6.3.1.3p3) but seems to hold in practice for all platforms we're likely to meet. - If step == LONG_MIN then we still end up with LONG_MIN + If step == PY_SSIZE_T_MIN then we still end up with PY_SSIZE_T_MIN after negation; but this works out, since we've still got - the correct value modulo ULONG_MAX+1, and the range_item - calculation is also done modulo ULONG_MAX+1. + the correct value modulo PY_SIZE_MAX+1, and the range_item + calculation is also done modulo PY_SIZE_MAX+1. */ - it->start = (long)(start + (unsigned long)(len-1) * step); - it->step = (long)(0UL-step); + it->start = (Py_ssize_t)(start + (size_t)(len-1) * step); + it->step = (Py_ssize_t)(0UL-step); return (PyObject *)it; }