summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew M. Kuchling <amk@amk.ca>2000-06-18 18:43:14 (GMT)
committerAndrew M. Kuchling <amk@amk.ca>2000-06-18 18:43:14 (GMT)
commit74042d6e5d44cc9d332c28414a1e04eadd204248 (patch)
tree888efb4a5da65b5fed5d282d019af6fb29fefe0b
parentb75c485f0bc6394f616d4a0bc746e613fd7b1021 (diff)
downloadcpython-74042d6e5d44cc9d332c28414a1e04eadd204248.zip
cpython-74042d6e5d44cc9d332c28414a1e04eadd204248.tar.gz
cpython-74042d6e5d44cc9d332c28414a1e04eadd204248.tar.bz2
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.
-rw-r--r--Include/abstract.h21
-rw-r--r--Objects/abstract.c20
-rw-r--r--Objects/listobject.c37
3 files changed, 56 insertions, 22 deletions
diff --git a/Include/abstract.h b/Include/abstract.h
index 12d799d..70c0e7c 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 410b80b..79af2f8 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 3bb5aec..163ba2a 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;
}