summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPablo Galindo <Pablogsal@gmail.com>2020-01-05 17:30:53 +0000
committerGitHub <noreply@github.com>2020-01-05 17:30:53 +0000
commit4b66fa6ce9c37e70b55af220d0e07368319de803 (patch)
treee6863cade7856b951c4ee966df8b43fd8b6d5419
parentb121a4a45ff4bab8812a9b26ceffe5ad642f5d5a (diff)
downloadcpython-git-4b66fa6ce9c37e70b55af220d0e07368319de803.tar.gz
bpo-39200: Correct the error message for range() empty constructor (GH-17813)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
-rw-r--r--Lib/test/test_range.py13
-rw-r--r--Misc/NEWS.d/next/Core and Builtins/2020-01-03-14-50-14.bpo-39200.Ip2_iI.rst2
-rw-r--r--Objects/rangeobject.c73
3 files changed, 59 insertions, 29 deletions
diff --git a/Lib/test/test_range.py b/Lib/test/test_range.py
index 73cbcc4717..30fa129b50 100644
--- a/Lib/test/test_range.py
+++ b/Lib/test/test_range.py
@@ -91,6 +91,19 @@ class RangeTest(unittest.TestCase):
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 0000000000..e5cb396643
--- /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 239ace6f42..9311f8b1f1 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);