]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39200: Correct the error message for range() empty constructor (GH-17813)
authorPablo Galindo <Pablogsal@gmail.com>
Sun, 5 Jan 2020 17:30:53 +0000 (17:30 +0000)
committerGitHub <noreply@github.com>
Sun, 5 Jan 2020 17:30:53 +0000 (17:30 +0000)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
Lib/test/test_range.py
Misc/NEWS.d/next/Core and Builtins/2020-01-03-14-50-14.bpo-39200.Ip2_iI.rst [new file with mode: 0644]
Objects/rangeobject.c

index 73cbcc4717d7df986f2b4e650591099bfd98e22f..30fa129b50ecba53dbf0bef744f22554ebf960bb 100644 (file)
@@ -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 (file)
index 0000000..e5cb396
--- /dev/null
@@ -0,0 +1,2 @@
+Correct the error message when trying to construct :class:`range` objects
+with no arguments. Patch by Pablo Galindo.
index 239ace6f4235ede252a51664f2d2eb89197ba3ad..9311f8b1f174cceee16d5391c4aafc2ada49dd2b 100644 (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))
+    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);