From: Andrew M. Kuchling Date: Sun, 18 Jun 2000 18:43:14 +0000 (+0000) Subject: Patch from /F: X-Git-Tag: v2.0b1~1479 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=74042d6e5d44cc9d332c28414a1e04eadd204248;p=python 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. --- diff --git a/Include/abstract.h b/Include/abstract.h index 12d799d1f1..70c0e7cf31 100644 --- a/Include/abstract.h +++ b/Include/abstract.h @@ -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)); /* diff --git a/Objects/abstract.c b/Objects/abstract.c index 410b80b597..79af2f8d2f 100644 --- a/Objects/abstract.c +++ b/Objects/abstract.c @@ -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; diff --git a/Objects/listobject.c b/Objects/listobject.c index 3bb5aec33d..163ba2a819 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -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; }