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

Skip to content

Commit 74042d6

Browse files
committed
Patch from /F:
this patch introduces PySequence_Fast and PySequence_Fast_GET_ITEM, and modifies the list.extend method to accept any kind of sequence.
1 parent b75c485 commit 74042d6

3 files changed

Lines changed: 56 additions & 22 deletions

File tree

Include/abstract.h

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
731731
/*
732732
Return the ith element of o, or NULL on failure. This is the
733733
equivalent of the Python expression: o[i].
734-
735734
*/
736735

737736
DL_IMPORT(PyObject *) PySequence_GetSlice Py_PROTO((PyObject *o, int i1, int i2));
@@ -783,13 +782,33 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
783782
This is equivalent to the Python expression: tuple(o)
784783
*/
785784

785+
786786
DL_IMPORT(PyObject *) PySequence_List Py_PROTO((PyObject *o));
787787

788788
/*
789789
Returns the sequence, o, as a list on success, and NULL on failure.
790790
This is equivalent to the Python expression: list(o)
791791
*/
792792

793+
DL_IMPORT(PyObject *) PySequence_Fast Py_PROTO((PyObject *o, const char* m));
794+
795+
/*
796+
Returns the sequence, o, as a tuple, unless it's already a
797+
tuple or list. Use PySequence_Fast_GET_ITEM to access the
798+
members of this list.
799+
800+
Returns NULL on failure. If the object is not a sequence,
801+
raises a TypeError exception with m as the message text.
802+
*/
803+
804+
#define PySequence_Fast_GET_ITEM(o, i)\
805+
(PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i))
806+
807+
/*
808+
Return the ith element of o, assuming that o was returned by
809+
PySequence_Fast, and that i is within bounds.
810+
*/
811+
793812
DL_IMPORT(int) PySequence_Count Py_PROTO((PyObject *o, PyObject *value));
794813

795814
/*

Objects/abstract.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,6 +1207,26 @@ PySequence_List(v)
12071207
return type_error("list() argument must be a sequence");
12081208
}
12091209

1210+
PyObject *
1211+
PySequence_Fast(v, m)
1212+
PyObject *v;
1213+
const char* m;
1214+
{
1215+
if (v == NULL)
1216+
return null_error();
1217+
1218+
if (PyList_Check(v) || PyTuple_Check(v)) {
1219+
Py_INCREF(v);
1220+
return v;
1221+
}
1222+
1223+
v = PySequence_Tuple(v);
1224+
if (v == NULL && PyErr_ExceptionMatches(PyExc_TypeError))
1225+
return type_error(m);
1226+
1227+
return v;
1228+
}
1229+
12101230
int
12111231
PySequence_Count(s, o)
12121232
PyObject *s;

Objects/listobject.c

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -627,23 +627,22 @@ listextend(self, args)
627627
if (!PyArg_ParseTuple(args, "O:extend", &b))
628628
return NULL;
629629

630-
if (!PyList_Check(b)) {
631-
PyErr_SetString(PyExc_TypeError,
632-
"list.extend() argument must be a list");
630+
b = PySequence_Fast(b, "list.extend() argument must be a sequence");
631+
if (!b)
633632
return NULL;
634-
}
635-
if (PyList_GET_SIZE(b) == 0) {
633+
634+
if (PyObject_Length(b) == 0)
636635
/* short circuit when b is empty */
637-
Py_INCREF(Py_None);
638-
return Py_None;
639-
}
636+
goto ok;
637+
640638
if (self == (PyListObject*)b) {
641639
/* as in list_ass_slice() we must special case the
642640
* situation: a.extend(a)
643641
*
644642
* XXX: I think this way ought to be faster than using
645643
* list_slice() the way list_ass_slice() does.
646644
*/
645+
Py_DECREF(b);
647646
b = PyList_New(selflen);
648647
if (!b)
649648
return NULL;
@@ -653,33 +652,29 @@ listextend(self, args)
653652
PyList_SET_ITEM(b, i, o);
654653
}
655654
}
656-
else
657-
/* we want b to have the same refcount semantics for the
658-
* Py_XDECREF() in the finally clause regardless of which
659-
* branch in the above conditional we took.
660-
*/
661-
Py_INCREF(b);
662655

663-
blen = PyList_GET_SIZE(b);
656+
blen = PyObject_Length(b);
657+
664658
/* resize a using idiom */
665659
items = self->ob_item;
666660
NRESIZE(items, PyObject*, selflen + blen);
667-
if (items == NULL ) {
661+
if (items == NULL) {
668662
PyErr_NoMemory();
669-
goto finally;
663+
goto failed;
670664
}
671665
self->ob_item = items;
672666

673-
/* populate the end self with b's items */
667+
/* populate the end of self with b's items */
674668
for (i = 0; i < blen; i++) {
675-
PyObject *o = PyList_GET_ITEM(b, i);
669+
PyObject *o = PySequence_Fast_GET_ITEM(b, i);
676670
Py_INCREF(o);
677671
PyList_SET_ITEM(self, self->ob_size++, o);
678672
}
673+
ok:
679674
res = Py_None;
680675
Py_INCREF(res);
681-
finally:
682-
Py_XDECREF(b);
676+
failed:
677+
Py_DECREF(b);
683678
return res;
684679
}
685680

0 commit comments

Comments
 (0)