[Python-checkins] bpo-39200: Correct the error message for range() empty constructor (GH-17813)
Pablo Galindo
webhook-mailer at python.org
Sun Jan 5 12:30:58 EST 2020
https://github.com/python/cpython/commit/4b66fa6ce9c37e70b55af220d0e07368319de803
commit: 4b66fa6ce9c37e70b55af220d0e07368319de803
branch: master
author: Pablo Galindo <Pablogsal at gmail.com>
committer: GitHub <noreply at github.com>
date: 2020-01-05T17:30:53Z
summary:
bpo-39200: Correct the error message for range() empty constructor (GH-17813)
Co-authored-by: Serhiy Storchaka <storchaka at gmail.com>
files:
A Misc/NEWS.d/next/Core and Builtins/2020-01-03-14-50-14.bpo-39200.Ip2_iI.rst
M Lib/test/test_range.py
M Objects/rangeobject.c
diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py
index 73cbcc4717d7d..30fa129b50ecb 100644
--- a/Lib/test/test_range.py
+++ b/Lib/test/test_range.py
@@ -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)
diff --git a/Misc/NEWS.d/next/Core and Builtins/2020-01-03-14-50-14.bpo-39200.Ip2_iI.rst b/Misc/NEWS.d/next/Core and Builtins/2020-01-03-14-50-14.bpo-39200.Ip2_iI.rst
new file mode 100644
index 0000000000000..e5cb396643fe0
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2020-01-03-14-50-14.bpo-39200.Ip2_iI.rst
@@ -0,0 +1,2 @@
+Correct the error message when trying to construct :class:`range` objects
+with no arguments. Patch by Pablo Galindo.
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 239ace6f4235e..9311f8b1f174c 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -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))
+ 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;
+ }
+
+ 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)
+ default:
+ PyErr_Format(PyExc_TypeError,
+ "range expected at most 3 arguments, got %zd",
+ num_args);
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;
-
- /* Convert borrowed refs to owned refs */
- start = PyNumber_Index(start);
- if (!start)
- return NULL;
- stop = PyNumber_Index(stop);
- if (!stop) {
- Py_DECREF(start);
- 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);
More information about the Python-checkins
mailing list