bpo-39200: Correct the error message for range() empty constructor (GH-17813)

Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
Pablo Galindo 2020-01-05 17:30:53 +00:00 committed by GitHub
parent b121a4a45f
commit 4b66fa6ce9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 58 additions and 28 deletions

View file

@ -91,6 +91,19 @@ def test_range(self):
r = range(-sys.maxsize, sys.maxsize, 2)
self.assertEqual(len(r), sys.maxsize)
def test_range_constructor_error_messages(self):
with self.assertRaisesRegex(
TypeError,
"range expected at least 1 argument, got 0"
):
range()
with self.assertRaisesRegex(
TypeError,
"range expected at most 3 arguments, got 6"
):
range(1, 2, 3, 4, 5, 6)
def test_large_operands(self):
x = range(10**20, 10**20+10, 3)
self.assertEqual(len(x), 4)

View file

@ -0,0 +1,2 @@
Correct the error message when trying to construct :class:`range` objects
with no arguments. Patch by Pablo Galindo.

View file

@ -77,37 +77,52 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
if (!_PyArg_NoKeywords("range", kw))
return NULL;
if (PyTuple_Size(args) <= 1) {
if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop))
return NULL;
stop = PyNumber_Index(stop);
if (!stop)
return NULL;
Py_INCREF(_PyLong_Zero);
start = _PyLong_Zero;
Py_INCREF(_PyLong_One);
step = _PyLong_One;
}
else {
if (!PyArg_UnpackTuple(args, "range", 2, 3,
&start, &stop, &step))
return NULL;
Py_ssize_t num_args = PyTuple_GET_SIZE(args);
switch (num_args) {
case 3:
step = PyTuple_GET_ITEM(args, 2);
/* fallthrough */
case 2:
start = PyTuple_GET_ITEM(args, 0);
start = PyNumber_Index(start);
if (!start) {
return NULL;
}
/* Convert borrowed refs to owned refs */
start = PyNumber_Index(start);
if (!start)
stop = PyTuple_GET_ITEM(args, 1);
stop = PyNumber_Index(stop);
if (!stop) {
Py_DECREF(start);
return NULL;
}
step = validate_step(step);
if (!step) {
Py_DECREF(start);
Py_DECREF(stop);
return NULL;
}
break;
case 1:
stop = PyTuple_GET_ITEM(args, 0);
stop = PyNumber_Index(stop);
if (!stop) {
return NULL;
}
Py_INCREF(_PyLong_Zero);
start = _PyLong_Zero;
Py_INCREF(_PyLong_One);
step = _PyLong_One;
break;
case 0:
PyErr_SetString(PyExc_TypeError,
"range expected at least 1 argument, got 0");
return NULL;
stop = PyNumber_Index(stop);
if (!stop) {
Py_DECREF(start);
default:
PyErr_Format(PyExc_TypeError,
"range expected at most 3 arguments, got %zd",
num_args);
return NULL;
}
step = validate_step(step); /* Caution, this can clear exceptions */
if (!step) {
Py_DECREF(start);
Py_DECREF(stop);
return NULL;
}
}
obj = make_range_object(type, start, stop, step);