mirror of
https://github.com/python/cpython.git
synced 2025-11-03 03:22:27 +00:00
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.
This commit is contained in:
parent
b75c485f0b
commit
74042d6e5d
3 changed files with 56 additions and 22 deletions
|
|
@ -731,7 +731,6 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
|||
/*
|
||||
Return the ith element of o, or NULL on failure. This is the
|
||||
equivalent of the Python expression: o[i].
|
||||
|
||||
*/
|
||||
|
||||
DL_IMPORT(PyObject *) PySequence_GetSlice Py_PROTO((PyObject *o, int i1, int i2));
|
||||
|
|
@ -783,6 +782,7 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
|||
This is equivalent to the Python expression: tuple(o)
|
||||
*/
|
||||
|
||||
|
||||
DL_IMPORT(PyObject *) PySequence_List Py_PROTO((PyObject *o));
|
||||
|
||||
/*
|
||||
|
|
@ -790,6 +790,25 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
|
|||
This is equivalent to the Python expression: list(o)
|
||||
*/
|
||||
|
||||
DL_IMPORT(PyObject *) PySequence_Fast Py_PROTO((PyObject *o, const char* m));
|
||||
|
||||
/*
|
||||
Returns the sequence, o, as a tuple, unless it's already a
|
||||
tuple or list. Use PySequence_Fast_GET_ITEM to access the
|
||||
members of this list.
|
||||
|
||||
Returns NULL on failure. If the object is not a sequence,
|
||||
raises a TypeError exception with m as the message text.
|
||||
*/
|
||||
|
||||
#define PySequence_Fast_GET_ITEM(o, i)\
|
||||
(PyList_Check(o) ? PyList_GET_ITEM(o, i) : PyTuple_GET_ITEM(o, i))
|
||||
|
||||
/*
|
||||
Return the ith element of o, assuming that o was returned by
|
||||
PySequence_Fast, and that i is within bounds.
|
||||
*/
|
||||
|
||||
DL_IMPORT(int) PySequence_Count Py_PROTO((PyObject *o, PyObject *value));
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -1207,6 +1207,26 @@ PySequence_List(v)
|
|||
return type_error("list() argument must be a sequence");
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PySequence_Fast(v, m)
|
||||
PyObject *v;
|
||||
const char* m;
|
||||
{
|
||||
if (v == NULL)
|
||||
return null_error();
|
||||
|
||||
if (PyList_Check(v) || PyTuple_Check(v)) {
|
||||
Py_INCREF(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
v = PySequence_Tuple(v);
|
||||
if (v == NULL && PyErr_ExceptionMatches(PyExc_TypeError))
|
||||
return type_error(m);
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
int
|
||||
PySequence_Count(s, o)
|
||||
PyObject *s;
|
||||
|
|
|
|||
|
|
@ -627,16 +627,14 @@ listextend(self, args)
|
|||
if (!PyArg_ParseTuple(args, "O:extend", &b))
|
||||
return NULL;
|
||||
|
||||
if (!PyList_Check(b)) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"list.extend() argument must be a list");
|
||||
b = PySequence_Fast(b, "list.extend() argument must be a sequence");
|
||||
if (!b)
|
||||
return NULL;
|
||||
}
|
||||
if (PyList_GET_SIZE(b) == 0) {
|
||||
|
||||
if (PyObject_Length(b) == 0)
|
||||
/* short circuit when b is empty */
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
goto ok;
|
||||
|
||||
if (self == (PyListObject*)b) {
|
||||
/* as in list_ass_slice() we must special case the
|
||||
* situation: a.extend(a)
|
||||
|
|
@ -644,6 +642,7 @@ listextend(self, args)
|
|||
* XXX: I think this way ought to be faster than using
|
||||
* list_slice() the way list_ass_slice() does.
|
||||
*/
|
||||
Py_DECREF(b);
|
||||
b = PyList_New(selflen);
|
||||
if (!b)
|
||||
return NULL;
|
||||
|
|
@ -653,33 +652,29 @@ listextend(self, args)
|
|||
PyList_SET_ITEM(b, i, o);
|
||||
}
|
||||
}
|
||||
else
|
||||
/* we want b to have the same refcount semantics for the
|
||||
* Py_XDECREF() in the finally clause regardless of which
|
||||
* branch in the above conditional we took.
|
||||
*/
|
||||
Py_INCREF(b);
|
||||
|
||||
blen = PyList_GET_SIZE(b);
|
||||
blen = PyObject_Length(b);
|
||||
|
||||
/* resize a using idiom */
|
||||
items = self->ob_item;
|
||||
NRESIZE(items, PyObject*, selflen + blen);
|
||||
if (items == NULL ) {
|
||||
if (items == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto finally;
|
||||
goto failed;
|
||||
}
|
||||
self->ob_item = items;
|
||||
|
||||
/* populate the end self with b's items */
|
||||
/* populate the end of self with b's items */
|
||||
for (i = 0; i < blen; i++) {
|
||||
PyObject *o = PyList_GET_ITEM(b, i);
|
||||
PyObject *o = PySequence_Fast_GET_ITEM(b, i);
|
||||
Py_INCREF(o);
|
||||
PyList_SET_ITEM(self, self->ob_size++, o);
|
||||
}
|
||||
ok:
|
||||
res = Py_None;
|
||||
Py_INCREF(res);
|
||||
finally:
|
||||
Py_XDECREF(b);
|
||||
failed:
|
||||
Py_DECREF(b);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue