Issue #28376: Creating instances of range_iterator by calling range_iterator

type now is disallowed.  Calling iter() on range instance is the only way.
Patch by Oren Milman.
This commit is contained in:
Serhiy Storchaka 2016-10-08 22:01:18 +03:00
parent aa078674e0
commit df53392f0d
3 changed files with 7 additions and 75 deletions

View File

@ -4,7 +4,6 @@ import unittest
import sys
import pickle
import itertools
import test.support
# pure Python implementations (3 args only), for comparison
def pyrange(start, stop, step):
@ -494,37 +493,13 @@ class RangeTest(unittest.TestCase):
test_id = "reversed(range({}, {}, {}))".format(start, end, step)
self.assert_iterators_equal(iter1, iter2, test_id, limit=100)
@test.support.cpython_only
def test_range_iterator_invocation(self):
import _testcapi
def test_range_iterators_invocation(self):
# verify range iterators instances cannot be created by
# calling their type
rangeiter_type = type(iter(range(0)))
self.assertWarns(DeprecationWarning, rangeiter_type, 1, 3, 1)
with test.support.check_warnings(('', DeprecationWarning)):
# rangeiter_new doesn't take keyword arguments
with self.assertRaises(TypeError):
rangeiter_type(a=1)
# rangeiter_new takes exactly 3 arguments
self.assertRaises(TypeError, rangeiter_type)
self.assertRaises(TypeError, rangeiter_type, 1)
self.assertRaises(TypeError, rangeiter_type, 1, 1)
self.assertRaises(TypeError, rangeiter_type, 1, 1, 1, 1)
# start, stop and stop must fit in C long
for good_val in [_testcapi.LONG_MAX, _testcapi.LONG_MIN]:
rangeiter_type(good_val, good_val, good_val)
for bad_val in [_testcapi.LONG_MAX + 1, _testcapi.LONG_MIN - 1]:
self.assertRaises(OverflowError,
rangeiter_type, bad_val, 1, 1)
self.assertRaises(OverflowError,
rangeiter_type, 1, bad_val, 1)
self.assertRaises(OverflowError,
rangeiter_type, 1, 1, bad_val)
# step mustn't be zero
self.assertRaises(ValueError, rangeiter_type, 1, 1, 0)
self.assertRaises(TypeError, rangeiter_type, 1, 3, 1)
long_rangeiter_type = type(iter(range(1 << 1000)))
self.assertRaises(TypeError, long_rangeiter_type, 1, 3, 1)
def test_slice(self):
def check(start, stop, step=None):

View File

@ -11,9 +11,7 @@ Core and Builtins
-----------------
- Issue #28376: Creating instances of range_iterator by calling range_iterator
type now is deprecated. Patch by Oren Milman.
- Issue #28376: The constructor of range_iterator now checks that step is not 0.
type now is disallowed. Calling iter() on range instance is the only way.
Patch by Oren Milman.
- Issue #26906: Resolving special methods of uninitialized type now causes

View File

@ -829,8 +829,6 @@ static PyMethodDef rangeiter_methods[] = {
{NULL, NULL} /* sentinel */
};
static PyObject *rangeiter_new(PyTypeObject *, PyObject *args, PyObject *kw);
PyTypeObject PyRangeIter_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0)
"range_iterator", /* tp_name */
@ -862,15 +860,6 @@ PyTypeObject PyRangeIter_Type = {
(iternextfunc)rangeiter_next, /* tp_iternext */
rangeiter_methods, /* tp_methods */
0, /* tp_members */
0, /* tp_getset */
0, /* tp_base */
0, /* tp_dict */
0, /* tp_descr_get */
0, /* tp_descr_set */
0, /* tp_dictoffset */
0, /* tp_init */
0, /* tp_alloc */
rangeiter_new, /* tp_new */
};
/* Return number of items in range (lo, hi, step). step != 0
@ -925,36 +914,6 @@ fast_range_iter(long start, long stop, long step)
return (PyObject *)it;
}
static PyObject *
rangeiter_new(PyTypeObject *type, PyObject *args, PyObject *kw)
{
long start, stop, step;
if (PyErr_WarnEx(PyExc_DeprecationWarning,
"range_iterator(): creating instances of range_iterator "
"by calling range_iterator type is deprecated",
1)) {
return NULL;
}
if (!_PyArg_NoKeywords("range_iterator()", kw)) {
return NULL;
}
if (!PyArg_ParseTuple(args,
"lll;range_iterator() requires 3 int arguments",
&start, &stop, &step)) {
return NULL;
}
if (step == 0) {
PyErr_SetString(PyExc_ValueError,
"range_iterator() arg 3 must not be zero");
return NULL;
}
return fast_range_iter(start, stop, step);
}
typedef struct {
PyObject_HEAD
PyObject *index;