From f0c5aec85f30ed16d1a8b4d3113bd056881bbf6f Mon Sep 17 00:00:00 2001
From: Raymond Hettinger <python@rcn.com>
Date: Sun, 26 Oct 2003 14:25:56 +0000
Subject: Minor improvements to itertools.tee():

* tee object is no longer subclassable
* independent iterators renamed to "itertools.tee_iterator"
* fixed doc string typo and added entry in the module doc string
---
 Lib/test/test_itertools.py | 12 ++++++++++++
 Modules/itertoolsmodule.c  | 18 +++++++++---------
 2 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/Lib/test/test_itertools.py b/Lib/test/test_itertools.py
index ce03b1a..e12aa41 100644
--- a/Lib/test/test_itertools.py
+++ b/Lib/test/test_itertools.py
@@ -243,6 +243,18 @@ class TestBasicOps(unittest.TestCase):
         self.assertRaises(TypeError, tee, 3)
         self.assertRaises(TypeError, tee, [1,2], 'x')
 
+        try:
+            class A(tee): pass
+        except TypeError:
+            pass
+        else:
+            self.fail("tee constructor should not be subclassable")
+
+        # tee_iterator should not be instantiable
+        a, b = tee(xrange(10))
+        self.assertRaises(TypeError, type(a))
+        self.assert_(a is iter(a))  # tee_iterator should support __iter__
+
     def test_StopIteration(self):
         self.assertRaises(StopIteration, izip().next)
 
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c
index b37dec1..7cafc14 100644
--- a/Modules/itertoolsmodule.c
+++ b/Modules/itertoolsmodule.c
@@ -113,12 +113,12 @@ ii_traverse(iiobject *ii, visitproc visit, void *arg)
 	return 0;
 }
 
-PyDoc_STRVAR(ii_doc, "Independent iterators linked to a tee() object.");
+PyDoc_STRVAR(ii_doc, "Independent iterator created by tee(iterable).");
 
 static PyTypeObject ii_type = {
 	PyObject_HEAD_INIT(&PyType_Type)
 	0,					/* ob_size */
-	"itertools.independent_iterator",	/* tp_name */
+	"itertools.tee_iterator",		/* tp_name */
 	sizeof(iiobject),			/* tp_basicsize */
 	0,					/* tp_itemsize */
 	/* methods */
@@ -173,7 +173,7 @@ tee_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	outbasket = PyList_New(0);
 	if (outbasket == NULL) goto fail;
 
-	to = (teeobject *)type->tp_alloc(type, 0);
+	to = PyObject_GC_New(teeobject, &tee_type);
 	if (to == NULL)  goto fail;
 
 	to->it = it;
@@ -181,6 +181,7 @@ tee_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 	to->outbasket = outbasket;
 	to->save_mode = 1;
 	to->num_seen = 0;
+	PyObject_GC_Track(to);
 
 	/* create independent iterators */
 	result = PyTuple_New(2);
@@ -212,7 +213,7 @@ tee_dealloc(teeobject *to)
 	Py_XDECREF(to->inbasket);
 	Py_XDECREF(to->outbasket);
 	Py_XDECREF(to->it);
-	to->ob_type->tp_free(to);
+	PyObject_GC_Del(to);
 }
 
 static int
@@ -241,7 +242,7 @@ tee_traverse(teeobject *to, visitproc visit, void *arg)
 PyDoc_STRVAR(tee_doc,
 "tee(iterable) --> (it1, it2)\n\
 \n\
-Split the iterable into to independent iterables.");
+Split the iterable into two independent iterables.");
 
 static PyTypeObject tee_type = {
 	PyObject_HEAD_INIT(NULL)
@@ -262,11 +263,10 @@ static PyTypeObject tee_type = {
 	0,				/* tp_hash */
 	0,				/* tp_call */
 	0,				/* tp_str */
-	PyObject_GenericGetAttr,	/* tp_getattro */
+	0,				/* tp_getattro */
 	0,				/* tp_setattro */
 	0,				/* tp_as_buffer */
-	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
-		Py_TPFLAGS_BASETYPE,	/* tp_flags */
+	Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,	/* tp_flags */
 	tee_doc,			/* tp_doc */
 	(traverseproc)tee_traverse,	/* tp_traverse */
 	0,				/* tp_clear */
@@ -285,7 +285,6 @@ static PyTypeObject tee_type = {
 	0,				/* tp_init */
 	0,				/* tp_alloc */
 	tee_new,			/* tp_new */
-	PyObject_GC_Del,		/* tp_free */
 };
 
 /* cycle object **********************************************************/
@@ -2092,6 +2091,7 @@ islice(seq, [start,] stop [, step]) --> elements from\n\
        seq[start:stop:step]\n\
 imap(fun, p, q, ...) --> fun(p0, q0), fun(p1, q1), ...\n\
 starmap(fun, seq) --> fun(*seq[0]), fun(*seq[1]), ...\n\
+tee(it) --> (it1, it2) splits one iterator into two \n\
 chain(p, q, ...) --> p0, p1, ... plast, q0, q1, ... \n\
 takewhile(pred, seq) --> seq[0], seq[1], until pred fails\n\
 dropwhile(pred, seq) --> seq[n], seq[n+1], starting when pred fails\n\
-- 
cgit v0.12

