Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0b796fa

Browse files
committed
Fixed support for containment test when a negative step is used; this
*really* closes bug #121965. Added three attributes to the xrange object: start, stop, and step. These are the same as for the slice objects.
1 parent a91e165 commit 0b796fa

1 file changed

Lines changed: 34 additions & 8 deletions

File tree

Objects/rangeobject.c

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
/* Range object implementation */
33

44
#include "Python.h"
5+
#include "structmember.h"
6+
#include <string.h>
57

68
typedef struct {
79
PyObject_HEAD
@@ -175,14 +177,30 @@ range_tolist(rangeobject *self, PyObject *args)
175177
static PyObject *
176178
range_getattr(rangeobject *r, char *name)
177179
{
180+
PyObject *result;
181+
178182
static PyMethodDef range_methods[] = {
179183
{"tolist", (PyCFunction)range_tolist, METH_VARARGS,
180184
"tolist() -> list\n"
181185
"Return a list object with the same values."},
182186
{NULL, NULL}
183187
};
188+
static struct memberlist range_members[] = {
189+
{"step", T_LONG, offsetof(rangeobject, step), RO},
190+
{"start", T_LONG, offsetof(rangeobject, start), RO},
191+
{"stop", T_LONG, 0, RO},
192+
{NULL, 0, 0, 0}
193+
};
184194

185-
return Py_FindMethod(range_methods, (PyObject *) r, name);
195+
result = Py_FindMethod(range_methods, (PyObject *) r, name);
196+
if (result == NULL) {
197+
PyErr_Clear();
198+
if (strcmp("stop", name) == 0)
199+
result = PyInt_FromLong(r->start + (r->len * r->step));
200+
else
201+
result = PyMember_Get((char *)r, range_members, name);
202+
}
203+
return result;
186204
}
187205

188206
static int
@@ -193,21 +211,29 @@ range_contains(rangeobject *r, PyObject *obj)
193211
if (num < 0 && PyErr_Occurred())
194212
return -1;
195213

196-
if ((num < r->start) || ((num - r->start) % r->step))
197-
return 0;
198-
if (num >= (r->start + (r->len * r->step)))
199-
return 0;
214+
if (r->step > 0) {
215+
if ((num < r->start) || ((num - r->start) % r->step))
216+
return 0;
217+
if (num >= (r->start + (r->len * r->step)))
218+
return 0;
219+
}
220+
else {
221+
if ((num > r->start) || ((num - r->start) % r->step))
222+
return 0;
223+
if (num <= (r->start + (r->len * r->step)))
224+
return 0;
225+
}
200226
return 1;
201227
}
202228

203229
static PySequenceMethods range_as_sequence = {
204-
(inquiry)range_length, /*sq_length*/
230+
(inquiry)range_length, /*sq_length*/
205231
(binaryfunc)range_concat, /*sq_concat*/
206232
(intargfunc)range_repeat, /*sq_repeat*/
207233
(intargfunc)range_item, /*sq_item*/
208234
(intintargfunc)range_slice, /*sq_slice*/
209-
0, /*sq_ass_item*/
210-
0, /*sq_ass_slice*/
235+
0, /*sq_ass_item*/
236+
0, /*sq_ass_slice*/
211237
(objobjproc)range_contains, /*sq_contains*/
212238
};
213239

0 commit comments

Comments
 (0)