[3.13] Tee of tee was not producing n independent iterators (gh-123884) (gh-125081)

This commit is contained in:
Raymond Hettinger 2024-10-08 14:11:43 -05:00 committed by GitHub
parent f5fea4dec6
commit 7bc99dd49e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 90 additions and 80 deletions

View file

@ -1642,10 +1642,11 @@ class TestBasicOps(unittest.TestCase):
self.assertEqual(len(result), n)
self.assertEqual([list(x) for x in result], [list('abc')]*n)
# tee pass-through to copyable iterator
# tee objects are independent (see bug gh-123884)
a, b = tee('abc')
c, d = tee(a)
self.assertTrue(a is c)
e, f = tee(c)
self.assertTrue(len({a, b, c, d, e, f}) == 6)
# test tee_new
t1, t2 = tee('abc')
@ -2072,21 +2073,36 @@ class TestPurePythonRoughEquivalents(unittest.TestCase):
def tee(iterable, n=2):
if n < 0:
raise ValueError('n must be >= 0')
iterator = iter(iterable)
shared_link = [None, None]
return tuple(_tee(iterator, shared_link) for _ in range(n))
raise ValueError
if n == 0:
return ()
iterator = _tee(iterable)
result = [iterator]
for _ in range(n - 1):
result.append(_tee(iterator))
return tuple(result)
def _tee(iterator, link):
try:
while True:
if link[1] is None:
link[0] = next(iterator)
link[1] = [None, None]
value, link = link
yield value
except StopIteration:
return
class _tee:
def __init__(self, iterable):
it = iter(iterable)
if isinstance(it, _tee):
self.iterator = it.iterator
self.link = it.link
else:
self.iterator = it
self.link = [None, None]
def __iter__(self):
return self
def __next__(self):
link = self.link
if link[1] is None:
link[0] = next(self.iterator)
link[1] = [None, None]
value, self.link = link
return value
# End tee() recipe #############################################
@ -2132,12 +2148,10 @@ class TestPurePythonRoughEquivalents(unittest.TestCase):
self.assertRaises(TypeError, tee, [1,2], 'x')
self.assertRaises(TypeError, tee, [1,2], 3, 'x')
# Tests not applicable to the tee() recipe
if False:
# tee object should be instantiable
a, b = tee('abc')
c = type(a)('def')
self.assertEqual(list(c), list('def'))
# tee object should be instantiable
a, b = tee('abc')
c = type(a)('def')
self.assertEqual(list(c), list('def'))
# test long-lagged and multi-way split
a, b, c = tee(range(2000), 3)
@ -2158,21 +2172,19 @@ class TestPurePythonRoughEquivalents(unittest.TestCase):
self.assertEqual(len(result), n)
self.assertEqual([list(x) for x in result], [list('abc')]*n)
# tee objects are independent (see bug gh-123884)
a, b = tee('abc')
c, d = tee(a)
e, f = tee(c)
self.assertTrue(len({a, b, c, d, e, f}) == 6)
# Tests not applicable to the tee() recipe
if False:
# tee pass-through to copyable iterator
a, b = tee('abc')
c, d = tee(a)
self.assertTrue(a is c)
# test tee_new
t1, t2 = tee('abc')
tnew = type(t1)
self.assertRaises(TypeError, tnew)
self.assertRaises(TypeError, tnew, 10)
t3 = tnew(t1)
self.assertTrue(list(t1) == list(t2) == list(t3) == list('abc'))
# test tee_new
t1, t2 = tee('abc')
tnew = type(t1)
self.assertRaises(TypeError, tnew)
self.assertRaises(TypeError, tnew, 10)
t3 = tnew(t1)
self.assertTrue(list(t1) == list(t2) == list(t3) == list('abc'))
# test that tee objects are weak referencable
a, b = tee(range(10))