summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2005-09-24 21:23:05 (GMT)
committerRaymond Hettinger <python@rcn.com>2005-09-24 21:23:05 (GMT)
commit6b27cda64386195cd07dfb686e9486f1c4bc3159 (patch)
tree277a5c96e9683c63b573b508f8c4bd2d1374aed8
parent9ceebd544516908e67c0f0d92c7a5f484e12beeb (diff)
downloadcpython-6b27cda64386195cd07dfb686e9486f1c4bc3159.zip
cpython-6b27cda64386195cd07dfb686e9486f1c4bc3159.tar.gz
cpython-6b27cda64386195cd07dfb686e9486f1c4bc3159.tar.bz2
Convert iterator __len__() methods to a private API.
-rw-r--r--Include/abstract.h15
-rw-r--r--Lib/test/test_enumerate.py1
-rw-r--r--Lib/test/test_iterlen.py12
-rw-r--r--Lib/test/test_itertools.py1
-rw-r--r--Misc/NEWS4
-rw-r--r--Modules/collectionsmodule.c18
-rw-r--r--Modules/itertoolsmodule.c20
-rw-r--r--Objects/abstract.c27
-rw-r--r--Objects/dictobject.c27
-rw-r--r--Objects/enumobject.c20
-rw-r--r--Objects/iterobject.c31
-rw-r--r--Objects/listobject.c25
-rw-r--r--Objects/rangeobject.c18
-rw-r--r--Objects/setobject.c19
-rw-r--r--Objects/tupleobject.c19
-rw-r--r--Python/bltinmodule.c6
16 files changed, 169 insertions, 94 deletions
diff --git a/Include/abstract.h b/Include/abstract.h
index 17ce105..7e0bc4d 100644
--- a/Include/abstract.h
+++ b/Include/abstract.h
@@ -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);
diff --git a/Lib/test/test_enumerate.py b/Lib/test/test_enumerate.py
index b6a18ee..e0a272e 100644
--- a/Lib/test/test_enumerate.py
+++ b/Lib/test/test_enumerate.py
@@ -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)
diff --git a/Lib/test/test_iterlen.py b/Lib/test/test_iterlen.py
index b51263d..1770de2 100644
--- a/Lib/test/test_iterlen.py
+++ b/Lib/test/test_iterlen.py
@@ -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):
diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index 5db128c..635d156 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -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))
diff --git a/Misc/NEWS b/Misc/NEWS
index 00bd247..409126a 100644
--- 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.
diff --git a/Modules/collectionsmodule.c b/Modules/collectionsmodule.c
index ffe1a96..1a8258e 100644
--- a/Modules/collectionsmodule.c
+++ b/Modules/collectionsmodule.c
@@ -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,
};
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index 34b37be..5ec5b8d 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -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 */
diff --git a/Objects/abstract.c b/Objects/abstract.c
index 94af3da..1f8feb5 100644
--- a/Objects/abstract.c
+++ b/Objects/abstract.c
@@ -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)) {
diff --git a/Objects/dictobject.c b/Objects/dictobject.c
index e90aca4..42e55e8 100644
--- a/Objects/dictobject.c
+++ b/Objects/dictobject.c
@@ -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,
};
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index aac88db..f74acdc 100644
--- a/Objects/enumobject.c
+++ b/Objects/enumobject.c
@@ -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 */
diff --git a/Objects/iterobject.c b/Objects/iterobject.c
index b414cc2..fdee3ca 100644
--- a/Objects/iterobject.c
+++ b/Objects/iterobject.c
@@ -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 */
};
diff --git a/Objects/listobject.c b/Objects/listobject.c
index 3b7358a..1a96361 100644
--- a/Objects/listobject.c
+++ b/Objects/listobject.c
@@ -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 **************************/
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 8b5650a..3cc5504 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -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,
};
diff --git a/Objects/setobject.c b/Objects/setobject.c
index c4cd562..29a9184 100644
--- a/Objects/setobject.c
+++ b/Objects/setobject.c
@@ -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
diff --git a/Objects/tupleobject.c b/Objects/tupleobject.c
index ea7d753..76e5de3 100644
--- a/Objects/tupleobject.c
+++ b/Objects/tupleobject.c
@@ -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,
};
diff --git a/Python/bltinmodule.c b/Python/bltinmodule.c
index dca8555..3e5f4eb 100644
--- a/Python/bltinmodule.c
+++ b/Python/bltinmodule.c
@@ -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)) {