]> granicus.if.org Git - python/commitdiff
Patch from /F:
authorAndrew M. Kuchling <amk@amk.ca>
Sun, 18 Jun 2000 18:43:14 +0000 (18:43 +0000)
committerAndrew M. Kuchling <amk@amk.ca>
Sun, 18 Jun 2000 18:43:14 +0000 (18:43 +0000)
this patch introduces PySequence_Fast and PySequence_Fast_GET_ITEM,
and modifies the list.extend method to accept any kind of sequence.

Include/abstract.h
Objects/abstract.c
Objects/listobject.c

index 12d799d1f1dcb2dc0d438d9dba3cae9e6fafc4d0..70c0e7cf31688c038a8c632c15281e1fbbd139ae 100644 (file)
@@ -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));
 
        /*
index 410b80b59755fbd591cb68d9155feda7e3a8de33..79af2f8d2f6a9bda25baf7a10b896627694aaa28 100644 (file)
@@ -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;
index 3bb5aec33d69aae74078115e578743c53d8ab839..163ba2a8194c48c59f981af00540468c89af5beb 100644 (file)
@@ -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;
 }