mirror of
https://github.com/python/cpython.git
synced 2025-07-24 11:44:31 +00:00
[3.13] Tee of tee was not producing n independent iterators (gh-123884) (gh-125081)
This commit is contained in:
parent
f5fea4dec6
commit
7bc99dd49e
4 changed files with 90 additions and 80 deletions
|
@ -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))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue