Skip to content

Commit f8c70ad

Browse files
committed
Get rid of PyArg_UnpackTuple
1 parent 7a5723d commit f8c70ad

2 files changed

Lines changed: 46 additions & 31 deletions

File tree

Lib/test/test_range.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,13 @@ def test_range(self):
9191
r = range(-sys.maxsize, sys.maxsize, 2)
9292
self.assertEqual(len(r), sys.maxsize)
9393

94+
def test_range_constructor_error_messages(self):
95+
with self.assertRaisesRegex(TypeError, "range expected at least 1 argument, got 0"):
96+
range()
97+
98+
with self.assertRaisesRegex(TypeError, "range expected at most 3 arguments, got 6"):
99+
range(1, 2, 3, 4, 5, 6)
100+
94101
def test_large_operands(self):
95102
x = range(10**20, 10**20+10, 3)
96103
self.assertEqual(len(x), 4)

Objects/rangeobject.c

Lines changed: 39 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -77,41 +77,49 @@ range_new(PyTypeObject *type, PyObject *args, PyObject *kw)
7777
if (!_PyArg_NoKeywords("range", kw))
7878
return NULL;
7979

80-
if (PyTuple_Size(args) <= 1) {
81-
if (!PyArg_UnpackTuple(args, "range", 1, 1, &stop)) {
82-
if (PyExceptionClass_Check(PyExc_TypeError)) {
83-
PyErr_SetString(PyExc_TypeError, "range expected at least 1 argument, got 0");
80+
Py_ssize_t num_args = PyTuple_GET_SIZE(args);
81+
switch (num_args) {
82+
case 3:
83+
step = PyTuple_GET_ITEM(args, 2);
84+
/* FALLTHRU */
85+
case 2:
86+
start = PyTuple_GET_ITEM(args, 0);
87+
start = PyNumber_Index(start);
88+
if (!start) {
89+
return NULL;
8490
}
85-
return NULL;
86-
}
87-
stop = PyNumber_Index(stop);
88-
if (!stop)
89-
return NULL;
90-
Py_INCREF(_PyLong_Zero);
91-
start = _PyLong_Zero;
92-
Py_INCREF(_PyLong_One);
93-
step = _PyLong_One;
94-
}
95-
else {
96-
if (!PyArg_UnpackTuple(args, "range", 2, 3,
97-
&start, &stop, &step))
98-
return NULL;
9991

100-
/* Convert borrowed refs to owned refs */
101-
start = PyNumber_Index(start);
102-
if (!start)
103-
return NULL;
104-
stop = PyNumber_Index(stop);
105-
if (!stop) {
106-
Py_DECREF(start);
92+
stop = PyTuple_GET_ITEM(args, 1);
93+
stop = PyNumber_Index(stop);
94+
if (!stop) {
95+
Py_DECREF(start);
96+
return NULL;
97+
}
98+
99+
step = validate_step(step);
100+
if (!step) {
101+
Py_DECREF(start);
102+
Py_DECREF(stop);
103+
return NULL;
104+
}
105+
break;
106+
case 1:
107+
stop = PyTuple_GET_ITEM(args, 0);
108+
stop = PyNumber_Index(stop);
109+
if (!stop) {
110+
return NULL;
111+
}
112+
Py_INCREF(_PyLong_Zero);
113+
start = _PyLong_Zero;
114+
Py_INCREF(_PyLong_One);
115+
step = _PyLong_One;
116+
break;
117+
case 0:
118+
PyErr_SetString(PyExc_TypeError, "range expected at least 1 argument, got 0");
107119
return NULL;
108-
}
109-
step = validate_step(step); /* Caution, this can clear exceptions */
110-
if (!step) {
111-
Py_DECREF(start);
112-
Py_DECREF(stop);
120+
default:
121+
PyErr_Format(PyExc_TypeError, "range expected at most 3 arguments, got %i", num_args);
113122
return NULL;
114-
}
115123
}
116124

117125
obj = make_range_object(type, start, stop, step);

0 commit comments

Comments
 (0)