]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Convert iterator __len__() methods to a private API.
authorRaymond Hettinger <python@rcn.com>
Sat, 24 Sep 2005 21:23:05 +0000 (21:23 +0000)
committerRaymond Hettinger <python@rcn.com>
Sat, 24 Sep 2005 21:23:05 +0000 (21:23 +0000)
16 files changed:
Include/abstract.h
Lib/test/test_enumerate.py
Lib/test/test_iterlen.py
Lib/test/test_itertools.py
Misc/NEWS
Modules/collectionsmodule.c
Modules/itertoolsmodule.c
Objects/abstract.c
Objects/dictobject.c
Objects/enumobject.c
Objects/iterobject.c
Objects/listobject.c
Objects/rangeobject.c
Objects/setobject.c
Objects/tupleobject.c
Python/bltinmodule.c

index 17ce10551f7f00ee66fce4d8554aaa17f8fdf6bd..7e0bc4d6ad6eefb2cc03b0736531ad1a2316fab3 100644 (file)
@@ -422,6 +422,21 @@ xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx*/
      PyAPI_FUNC(int) PyObject_Length(PyObject *o);
 #define PyObject_Length PyObject_Size
 
+     PyAPI_FUNC(int) _PyObject_LengthCue(PyObject *o);
+
+       /*
+         Return the size of object o.  If the object, o, provides
+        both sequence and mapping protocols, the sequence size is
+        returned. On error, -1 is returned.  If the object provides
+        a _length_cue() method, its value is returned.  This is the 
+        equivalent to the Python expression: 
+               try:
+                       return len(o)
+               except (AttributeError, TypeError):
+                       if hasattr(o, '_length_cue'):
+                               return o._length_cue()
+                       raise
+       */
 
      PyAPI_FUNC(PyObject *) PyObject_GetItem(PyObject *o, PyObject *key);
 
index b6a18eeeb49b567ce15ccf2373dc62ce648f409b..e0a272e025f9aea2e9928197f6bd34affa18b3b9 100644 (file)
@@ -144,6 +144,7 @@ class TestReversed(unittest.TestCase):
 
     def test_len(self):
         # This is an implementation detail, not an interface requirement
+        from test.test_iterlen import len
         for s in ('hello', tuple('hello'), list('hello'), xrange(5)):
             self.assertEqual(len(reversed(s)), len(s))
             r = reversed(s)
index b51263d118accb957b5a86f2c22e2e723b49e5fc..1770de2c0ad383650c1d71eac200a1faec959781 100644 (file)
@@ -43,12 +43,22 @@ enumerate(iter('abc')).
 
 import unittest
 from test import test_support
-from itertools import repeat, count
+from itertools import repeat
 from collections import deque
 from UserList import UserList
+from __builtin__ import len as _len
 
 n = 10
 
+def len(obj):
+    try:
+        return _len(obj)
+    except TypeError:
+        try:
+            return obj._length_cue()
+        except AttributeError:
+            raise TypeError
+
 class TestInvariantWithoutMutations(unittest.TestCase):
 
     def test_invariant(self):
index 5db128cda145539a0a3cd6a04a534122cacdbc3d..635d1563760d6697cd12e90f1197cfa14ad28162 100644 (file)
@@ -670,6 +670,7 @@ class TestVariousIteratorArgs(unittest.TestCase):
 class LengthTransparency(unittest.TestCase):
 
     def test_repeat(self):
+        from test.test_iterlen import len
         self.assertEqual(len(repeat(None, 50)), 50)
         self.assertRaises(TypeError, len, repeat(None))
 
index 00bd2471de625ab5d1af51a3f701563bfa10199c..409126aa09c1f5cb33c026e217671e0ec13b28f2 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,10 @@ What's New in Python 2.5 alpha 1?
 Core and builtins
 -----------------
 
+- All iterators now have a Boolean value of true.  Formerly, some iterators
+  supported a __len__() method which evaluated to False when the iterator
+  was empty.
+
 - On 64-bit platforms, when __len__() returns a value that cannot be
   represented as a C int, raise OverflowError.
 
index ffe1a96c6a122cdffe8e661c1258a95bbb2f4610..1a8258ef7c3f00baefe5251c370daec8b2b0062c 100644 (file)
@@ -935,15 +935,17 @@ dequeiter_next(dequeiterobject *it)
        return item;
 }
 
-static int
+static PyObject *
 dequeiter_len(dequeiterobject *it)
 {
-       return it->counter;
+       return PyInt_FromLong(it->counter);
 }
 
-static PySequenceMethods dequeiter_as_sequence = {
-       (inquiry)dequeiter_len,         /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef dequeiter_methods[] = {
+       {"_length_cue", (PyCFunction)dequeiter_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 PyTypeObject dequeiter_type = {
@@ -960,7 +962,7 @@ PyTypeObject dequeiter_type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &dequeiter_as_sequence,                 /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -976,6 +978,7 @@ PyTypeObject dequeiter_type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)dequeiter_next,           /* tp_iternext */
+       dequeiter_methods,                      /* tp_methods */
        0,
 };
 
@@ -1042,7 +1045,7 @@ PyTypeObject dequereviter_type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &dequeiter_as_sequence,                 /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -1058,6 +1061,7 @@ PyTypeObject dequereviter_type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)dequereviter_next,        /* tp_iternext */
+       dequeiter_methods,                      /* tp_methods */
        0,
 };
 
index 34b37be43ff6369256b298418a21ed038ec78150..5ec5b8dde9f53e51072596c1904732fa30cc44ee 100644 (file)
@@ -2336,17 +2336,21 @@ repeat_repr(repeatobject *ro)
        return result;
 }      
 
-static int
+static PyObject *
 repeat_len(repeatobject *ro)
 {
-        if (ro->cnt == -1)
+        if (ro->cnt == -1) {
                 PyErr_SetString(PyExc_TypeError, "len() of unsized object");
-        return (int)(ro->cnt);
+               return NULL;
+       }
+        return PyInt_FromLong(ro->cnt);
 }
 
-static PySequenceMethods repeat_as_sequence = {
-       (inquiry)repeat_len,            /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef repeat_methods[] = {
+       {"_length_cue", (PyCFunction)repeat_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 PyDoc_STRVAR(repeat_doc,
@@ -2368,7 +2372,7 @@ static PyTypeObject repeat_type = {
        0,                              /* tp_compare */
        (reprfunc)repeat_repr,          /* tp_repr */
        0,                              /* tp_as_number */
-       &repeat_as_sequence,            /* tp_as_sequence */
+       0,                              /* tp_as_sequence */
        0,                              /* tp_as_mapping */
        0,                              /* tp_hash */
        0,                              /* tp_call */
@@ -2385,7 +2389,7 @@ static PyTypeObject repeat_type = {
        0,                              /* tp_weaklistoffset */
        PyObject_SelfIter,              /* tp_iter */
        (iternextfunc)repeat_next,      /* tp_iternext */
-       0,                              /* tp_methods */
+       repeat_methods,                 /* tp_methods */
        0,                              /* tp_members */
        0,                              /* tp_getset */
        0,                              /* tp_base */
index 94af3da039b19ab2f33a1ebae00d5cd4084039b4..1f8feb52e721d17214c4c4836c6bbd7a03a94938 100644 (file)
@@ -81,6 +81,31 @@ PyObject_Length(PyObject *o)
 }
 #define PyObject_Length PyObject_Size
 
+int
+_PyObject_LengthCue(PyObject *o)
+{
+       int rv = PyObject_Size(o);
+       if (rv != -1)
+               return rv;
+       if (PyErr_ExceptionMatches(PyExc_TypeError) ||
+           PyErr_ExceptionMatches(PyExc_AttributeError)) {
+               PyObject *err_type, *err_value, *err_tb, *ro;
+
+               PyErr_Fetch(&err_type, &err_value, &err_tb);
+               ro = PyObject_CallMethod(o, "_length_cue", NULL);
+               if (ro != NULL) {
+                       rv = (int)PyInt_AsLong(ro);
+                       Py_DECREF(ro);
+                       Py_XDECREF(err_type);
+                       Py_XDECREF(err_value);
+                       Py_XDECREF(err_tb);
+                       return rv;
+               }
+               PyErr_Restore(err_type, err_value, err_tb);
+       }
+       return -1;
+}
+
 PyObject *
 PyObject_GetItem(PyObject *o, PyObject *key)
 {
@@ -1399,7 +1424,7 @@ PySequence_Tuple(PyObject *v)
                return NULL;
 
        /* Guess result size and allocate space. */
-       n = PyObject_Size(v);
+       n = _PyObject_LengthCue(v);
        if (n < 0) {
                if (!PyErr_ExceptionMatches(PyExc_TypeError)  &&
                    !PyErr_ExceptionMatches(PyExc_AttributeError)) {
index e90aca4b0fd4602200449c9cc205612141b12471..42e55e868c2c02f855f3350fcd48c0e06f582398 100644 (file)
@@ -2054,17 +2054,20 @@ dictiter_dealloc(dictiterobject *di)
        PyObject_Del(di);
 }
 
-static int
+static PyObject *
 dictiter_len(dictiterobject *di)
 {
+       int len = 0;
        if (di->di_dict != NULL && di->di_used == di->di_dict->ma_used)
-               return di->len;
-       return 0;
+               len = di->len;
+       return PyInt_FromLong(len);
 }
 
-static PySequenceMethods dictiter_as_sequence = {
-       (inquiry)dictiter_len,          /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef dictiter_methods[] = {
+       {"_length_cue", (PyCFunction)dictiter_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 static PyObject *dictiter_iternextkey(dictiterobject *di)
@@ -2120,7 +2123,7 @@ PyTypeObject PyDictIterKey_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &dictiter_as_sequence,                  /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -2136,6 +2139,8 @@ PyTypeObject PyDictIterKey_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)dictiter_iternextkey,     /* tp_iternext */
+       dictiter_methods,                       /* tp_methods */
+       0,
 };
 
 static PyObject *dictiter_iternextvalue(dictiterobject *di)
@@ -2191,7 +2196,7 @@ PyTypeObject PyDictIterValue_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &dictiter_as_sequence,                  /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -2207,6 +2212,8 @@ PyTypeObject PyDictIterValue_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)dictiter_iternextvalue,   /* tp_iternext */
+       dictiter_methods,                       /* tp_methods */
+       0,
 };
 
 static PyObject *dictiter_iternextitem(dictiterobject *di)
@@ -2276,7 +2283,7 @@ PyTypeObject PyDictIterItem_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &dictiter_as_sequence,                  /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -2292,4 +2299,6 @@ PyTypeObject PyDictIterItem_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)dictiter_iternextitem,    /* tp_iternext */
+       dictiter_methods,                       /* tp_methods */
+       0,
 };
index aac88dbb0129698656979943913e7d2c029299f6..f74acdcddc986235a3f8002bc9b9fa708142175a 100644 (file)
@@ -239,23 +239,25 @@ PyDoc_STRVAR(reversed_doc,
 "\n"
 "Return a reverse iterator");
 
-static int
+static PyObject *
 reversed_len(reversedobject *ro)
 {
        int position, seqsize;
 
        if (ro->seq == NULL)
-               return 0;
+               return PyInt_FromLong(0);
        seqsize = PySequence_Size(ro->seq);
        if (seqsize == -1)
-               return -1;
+               return NULL;
        position = ro->index + 1;
-       return (seqsize < position)  ?  0  :  position;
+       return PyInt_FromLong((seqsize < position)  ?  0  :  position);
 }
 
-static PySequenceMethods reversed_as_sequence = {
-       (inquiry)reversed_len,          /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef reversediter_methods[] = {
+       {"_length_cue", (PyCFunction)reversed_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 PyTypeObject PyReversed_Type = {
@@ -272,7 +274,7 @@ PyTypeObject PyReversed_Type = {
        0,                              /* tp_compare */
        0,                              /* tp_repr */
        0,                              /* tp_as_number */
-       &reversed_as_sequence,          /* tp_as_sequence */
+       0,                              /* tp_as_sequence */
        0,                              /* tp_as_mapping */
        0,                              /* tp_hash */
        0,                              /* tp_call */
@@ -289,7 +291,7 @@ PyTypeObject PyReversed_Type = {
        0,                              /* tp_weaklistoffset */
        PyObject_SelfIter,              /* tp_iter */
        (iternextfunc)reversed_next,    /* tp_iternext */
-       0,                              /* tp_methods */
+       reversediter_methods,           /* tp_methods */
        0,                              /* tp_members */
        0,                              /* tp_getset */
        0,                              /* tp_base */
index b414cc2e9f47ffebfb3f6f499fde769feb423b4e..fdee3ca9178efa0fc199520cc34eb31134d58c84 100644 (file)
@@ -71,7 +71,7 @@ iter_iternext(PyObject *iterator)
        return NULL;
 }
 
-static int
+static PyObject *
 iter_len(seqiterobject *it)
 {
        int seqsize, len;
@@ -79,17 +79,19 @@ iter_len(seqiterobject *it)
        if (it->it_seq) {
                seqsize = PySequence_Size(it->it_seq);
                if (seqsize == -1)
-                       return -1;
+                       return NULL;
                len = seqsize - it->it_index;
                if (len >= 0)
-                       return len;
+                       return PyInt_FromLong(len);
        }
-       return 0;
+       return PyInt_FromLong(0);
 }
 
-static PySequenceMethods iter_as_sequence = {
-       (inquiry)iter_len,              /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef seqiter_methods[] = {
+       {"_length_cue", (PyCFunction)iter_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 PyTypeObject PySeqIter_Type = {
@@ -106,7 +108,7 @@ PyTypeObject PySeqIter_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &iter_as_sequence,                      /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -122,13 +124,8 @@ PyTypeObject PySeqIter_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)iter_iternext,            /* tp_iternext */
-       0,                                      /* tp_methods */
+       seqiter_methods,                        /* tp_methods */
        0,                                      /* tp_members */
-       0,                                      /* tp_getset */
-       0,                                      /* tp_base */
-       0,                                      /* tp_dict */
-       0,                                      /* tp_descr_get */
-       0,                                      /* tp_descr_set */
 };
 
 /* -------------------------------------- */
@@ -236,10 +233,4 @@ PyTypeObject PyCallIter_Type = {
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)calliter_iternext,        /* tp_iternext */
        0,                                      /* tp_methods */
-       0,                                      /* tp_members */
-       0,                                      /* tp_getset */
-       0,                                      /* tp_base */
-       0,                                      /* tp_dict */
-       0,                                      /* tp_descr_get */
-       0,                                      /* tp_descr_set */
 };
index 3b7358a312ec8f2a665501ea224e593ad1e57477..1a96361526fedb1f24901b1c1c5f1efdbb39d50e 100644 (file)
@@ -775,7 +775,7 @@ listextend(PyListObject *self, PyObject *b)
        iternext = *it->ob_type->tp_iternext;
 
        /* Guess a result list size. */
-       n = PyObject_Size(b);
+       n = _PyObject_LengthCue(b);
        if (n < 0) {
                if (!PyErr_ExceptionMatches(PyExc_TypeError)  &&
                    !PyErr_ExceptionMatches(PyExc_AttributeError)) {
@@ -2764,21 +2764,23 @@ listiter_next(listiterobject *it)
        return NULL;
 }
 
-static int
+static PyObject *
 listiter_len(listiterobject *it)
 {
        int len;
        if (it->it_seq) {
                len = PyList_GET_SIZE(it->it_seq) - it->it_index;
                if (len >= 0)
-                       return len;
+                       return PyInt_FromLong((long)len);
        }
-       return 0;
+       return PyInt_FromLong(0);
 }
 
-static PySequenceMethods listiter_as_sequence = {
-       (inquiry)listiter_len,          /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef listiter_methods[] = {
+       {"_length_cue", (PyCFunction)listiter_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 PyTypeObject PyListIter_Type = {
@@ -2795,7 +2797,7 @@ PyTypeObject PyListIter_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &listiter_as_sequence,                  /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -2811,13 +2813,8 @@ PyTypeObject PyListIter_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)listiter_next,            /* tp_iternext */
-       0,                                      /* tp_methods */
+       listiter_methods,                       /* tp_methods */
        0,                                      /* tp_members */
-       0,                                      /* tp_getset */
-       0,                                      /* tp_base */
-       0,                                      /* tp_dict */
-       0,                                      /* tp_descr_get */
-       0,                                      /* tp_descr_set */
 };
 
 /*********************** List Reverse Iterator **************************/
index 8b5650a4fdfa9b66211eed0f2a43cec79baeac41..3cc5504631bfafa41ba5fd74c223ac1184c115a0 100644 (file)
@@ -262,17 +262,18 @@ rangeiter_next(rangeiterobject *r)
        return NULL;
 }
 
-static int
+static PyObject *
 rangeiter_len(rangeiterobject *r)
 {
-       return r->len - r->index;
+       return PyInt_FromLong(r->len - r->index);
 }
 
-static PySequenceMethods rangeiter_as_sequence = {
-       (inquiry)rangeiter_len,         /* sq_length */
-       0,                              /* sq_concat */
-};
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
 
+static PyMethodDef rangeiter_methods[] = {
+       {"_length_cue", (PyCFunction)rangeiter_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
+};
 
 static PyTypeObject Pyrangeiter_Type = {
        PyObject_HEAD_INIT(&PyType_Type)
@@ -288,7 +289,7 @@ static PyTypeObject Pyrangeiter_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &rangeiter_as_sequence,                 /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -304,5 +305,6 @@ static PyTypeObject Pyrangeiter_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)rangeiter_next,           /* tp_iternext */
-       0,                                      /* tp_methods */
+       rangeiter_methods,                      /* tp_methods */
+       0,
 };
index c4cd562d58246a8b7c5fa4aea96d39181d59d0e3..29a9184c360024db05329f1363313eba7a00a2db 100644 (file)
@@ -749,17 +749,20 @@ setiter_dealloc(setiterobject *si)
        PyObject_Del(si);
 }
 
-static int
+static PyObject *
 setiter_len(setiterobject *si)
 {
+       int len = 0;
        if (si->si_set != NULL && si->si_used == si->si_set->used)
-               return si->len;
-       return 0;
+               len = si->len;
+       return PyInt_FromLong(len);
 }
 
-static PySequenceMethods setiter_as_sequence = {
-       (inquiry)setiter_len,           /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef setiter_methods[] = {
+       {"_length_cue", (PyCFunction)setiter_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 static PyObject *setiter_iternext(setiterobject *si)
@@ -814,7 +817,7 @@ static PyTypeObject PySetIter_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &setiter_as_sequence,                   /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -830,6 +833,8 @@ static PyTypeObject PySetIter_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)setiter_iternext,         /* tp_iternext */
+       setiter_methods,                        /* tp_methods */
+       0,
 };
 
 static int
index ea7d75302238d5e81eea50e781885bce8c462e6c..76e5de32d18699a119baab82286f682e0c82229a 100644 (file)
@@ -851,17 +851,20 @@ tupleiter_next(tupleiterobject *it)
        return NULL;
 }
 
-static int
+static PyObject *
 tupleiter_len(tupleiterobject *it)
 {
+       int len = 0;
        if (it->it_seq)
-               return PyTuple_GET_SIZE(it->it_seq) - it->it_index;
-       return 0;
+               len = PyTuple_GET_SIZE(it->it_seq) - it->it_index;
+       return PyInt_FromLong(len);
 }
 
-static PySequenceMethods tupleiter_as_sequence = {
-       (inquiry)tupleiter_len,         /* sq_length */
-       0,                              /* sq_concat */
+PyDoc_STRVAR(length_cue_doc, "Private method returning an estimate of len(list(it)).");
+
+static PyMethodDef tupleiter_methods[] = {
+       {"_length_cue", (PyCFunction)tupleiter_len, METH_NOARGS, length_cue_doc},
+       {NULL,          NULL}           /* sentinel */
 };
 
 PyTypeObject PyTupleIter_Type = {
@@ -878,7 +881,7 @@ PyTypeObject PyTupleIter_Type = {
        0,                                      /* tp_compare */
        0,                                      /* tp_repr */
        0,                                      /* tp_as_number */
-       &tupleiter_as_sequence,                 /* tp_as_sequence */
+       0,                                      /* tp_as_sequence */
        0,                                      /* tp_as_mapping */
        0,                                      /* tp_hash */
        0,                                      /* tp_call */
@@ -894,4 +897,6 @@ PyTypeObject PyTupleIter_Type = {
        0,                                      /* tp_weaklistoffset */
        PyObject_SelfIter,                      /* tp_iter */
        (iternextfunc)tupleiter_next,           /* tp_iternext */
+       tupleiter_methods,                      /* tp_methods */
+       0,
 };
index dca8555a2fb56b8d11b7ae069207fee6f8095146..3e5f4ebfefa609120e437662d431d006d88f33f1 100644 (file)
@@ -221,7 +221,7 @@ builtin_filter(PyObject *self, PyObject *args)
                goto Fail_arg;
 
        /* Guess a result list size. */
-       len = PyObject_Size(seq);
+       len = _PyObject_LengthCue(seq);
        if (len < 0) {
                if (!PyErr_ExceptionMatches(PyExc_TypeError)  &&
                    !PyErr_ExceptionMatches(PyExc_AttributeError)) {
@@ -873,7 +873,7 @@ builtin_map(PyObject *self, PyObject *args)
                }
 
                /* Update len. */
-               curlen = PyObject_Size(curseq);
+               curlen = _PyObject_LengthCue(curseq);
                if (curlen < 0) {
                        if (!PyErr_ExceptionMatches(PyExc_TypeError)  &&
                            !PyErr_ExceptionMatches(PyExc_AttributeError)) {
@@ -2108,7 +2108,7 @@ builtin_zip(PyObject *self, PyObject *args)
        len = -1;       /* unknown */
        for (i = 0; i < itemsize; ++i) {
                PyObject *item = PyTuple_GET_ITEM(args, i);
-               int thislen = PyObject_Size(item);
+               int thislen = _PyObject_LengthCue(item);
                if (thislen < 0) {
                        if (!PyErr_ExceptionMatches(PyExc_TypeError)  &&
                            !PyErr_ExceptionMatches(PyExc_AttributeError)) {