blob: bd17ad4a21bb9347ff58ca365d781d8ca33272e1 [file] [log] [blame]
Serhiy Storchakad7a44152015-11-12 11:23:04 +02001import copy
Antoine Pitrou796564c2013-07-30 19:59:21 +02002import gc
Serhiy Storchakad7a44152015-11-12 11:23:04 +02003import pickle
Antoine Pitrou796564c2013-07-30 19:59:21 +02004import sys
5import unittest
Yury Selivanov68333392015-05-22 11:16:47 -04006import warnings
Antoine Pitrou796564c2013-07-30 19:59:21 +02007import weakref
Yury Selivanove13f8f32015-07-03 00:23:30 -04008import inspect
Antoine Pitrou796564c2013-07-30 19:59:21 +02009
10from test import support
11
Nathaniel J. Smithab4413a2017-05-17 13:33:23 -070012_testcapi = support.import_module('_testcapi')
13
14
15# This tests to make sure that if a SIGINT arrives just before we send into a
16# yield from chain, the KeyboardInterrupt is raised in the innermost
17# generator (see bpo-30039).
18class SignalAndYieldFromTest(unittest.TestCase):
19
20 def generator1(self):
21 return (yield from self.generator2())
22
23 def generator2(self):
24 try:
25 yield
26 except KeyboardInterrupt:
27 return "PASSED"
28 else:
29 return "FAILED"
30
31 def test_raise_and_yield_from(self):
32 gen = self.generator1()
33 gen.send(None)
34 try:
35 _testcapi.raise_SIGINT_then_send_None(gen)
36 except BaseException as _exc:
37 exc = _exc
38 self.assertIs(type(exc), StopIteration)
39 self.assertEqual(exc.value, "PASSED")
40
Antoine Pitrou796564c2013-07-30 19:59:21 +020041
42class FinalizationTest(unittest.TestCase):
43
44 def test_frame_resurrect(self):
45 # A generator frame can be resurrected by a generator's finalization.
46 def gen():
47 nonlocal frame
48 try:
49 yield
50 finally:
51 frame = sys._getframe()
52
53 g = gen()
54 wr = weakref.ref(g)
55 next(g)
56 del g
57 support.gc_collect()
58 self.assertIs(wr(), None)
59 self.assertTrue(frame)
60 del frame
61 support.gc_collect()
62
63 def test_refcycle(self):
64 # A generator caught in a refcycle gets finalized anyway.
65 old_garbage = gc.garbage[:]
66 finalized = False
67 def gen():
68 nonlocal finalized
69 try:
70 g = yield
71 yield 1
72 finally:
73 finalized = True
74
75 g = gen()
76 next(g)
77 g.send(g)
78 self.assertGreater(sys.getrefcount(g), 2)
79 self.assertFalse(finalized)
80 del g
81 support.gc_collect()
82 self.assertTrue(finalized)
83 self.assertEqual(gc.garbage, old_garbage)
84
Serhiy Storchakac775ad62015-03-11 18:20:35 +020085 def test_lambda_generator(self):
86 # Issue #23192: Test that a lambda returning a generator behaves
87 # like the equivalent function
88 f = lambda: (yield 1)
89 def g(): return (yield 1)
90
91 # test 'yield from'
92 f2 = lambda: (yield from g())
93 def g2(): return (yield from g())
94
95 f3 = lambda: (yield from f())
96 def g3(): return (yield from f())
97
98 for gen_fun in (f, g, f2, g2, f3, g3):
99 gen = gen_fun()
100 self.assertEqual(next(gen), 1)
101 with self.assertRaises(StopIteration) as cm:
102 gen.send(2)
103 self.assertEqual(cm.exception.value, 2)
104
Antoine Pitrou796564c2013-07-30 19:59:21 +0200105
Victor Stinner40ee3012014-06-16 15:59:28 +0200106class GeneratorTest(unittest.TestCase):
107
108 def test_name(self):
109 def func():
110 yield 1
111
112 # check generator names
113 gen = func()
114 self.assertEqual(gen.__name__, "func")
115 self.assertEqual(gen.__qualname__,
116 "GeneratorTest.test_name.<locals>.func")
117
118 # modify generator names
119 gen.__name__ = "name"
120 gen.__qualname__ = "qualname"
121 self.assertEqual(gen.__name__, "name")
122 self.assertEqual(gen.__qualname__, "qualname")
123
124 # generator names must be a string and cannot be deleted
125 self.assertRaises(TypeError, setattr, gen, '__name__', 123)
126 self.assertRaises(TypeError, setattr, gen, '__qualname__', 123)
127 self.assertRaises(TypeError, delattr, gen, '__name__')
128 self.assertRaises(TypeError, delattr, gen, '__qualname__')
129
130 # modify names of the function creating the generator
131 func.__qualname__ = "func_qualname"
132 func.__name__ = "func_name"
133 gen = func()
134 self.assertEqual(gen.__name__, "func_name")
135 self.assertEqual(gen.__qualname__, "func_qualname")
136
137 # unnamed generator
138 gen = (x for x in range(10))
139 self.assertEqual(gen.__name__,
140 "<genexpr>")
141 self.assertEqual(gen.__qualname__,
142 "GeneratorTest.test_name.<locals>.<genexpr>")
143
Serhiy Storchakad7a44152015-11-12 11:23:04 +0200144 def test_copy(self):
145 def f():
146 yield 1
147 g = f()
148 with self.assertRaises(TypeError):
149 copy.copy(g)
150
151 def test_pickle(self):
152 def f():
153 yield 1
154 g = f()
155 for proto in range(pickle.HIGHEST_PROTOCOL + 1):
156 with self.assertRaises((TypeError, pickle.PicklingError)):
157 pickle.dumps(g, proto)
158
Victor Stinner40ee3012014-06-16 15:59:28 +0200159
Victor Stinner26f7b8a2015-01-31 10:29:47 +0100160class ExceptionTest(unittest.TestCase):
161 # Tests for the issue #23353: check that the currently handled exception
162 # is correctly saved/restored in PyEval_EvalFrameEx().
163
164 def test_except_throw(self):
165 def store_raise_exc_generator():
166 try:
167 self.assertEqual(sys.exc_info()[0], None)
168 yield
169 except Exception as exc:
170 # exception raised by gen.throw(exc)
171 self.assertEqual(sys.exc_info()[0], ValueError)
172 self.assertIsNone(exc.__context__)
173 yield
174
175 # ensure that the exception is not lost
176 self.assertEqual(sys.exc_info()[0], ValueError)
177 yield
178
179 # we should be able to raise back the ValueError
180 raise
181
182 make = store_raise_exc_generator()
183 next(make)
184
185 try:
186 raise ValueError()
187 except Exception as exc:
188 try:
189 make.throw(exc)
190 except Exception:
191 pass
192
193 next(make)
194 with self.assertRaises(ValueError) as cm:
195 next(make)
196 self.assertIsNone(cm.exception.__context__)
197
198 self.assertEqual(sys.exc_info(), (None, None, None))
199
200 def test_except_next(self):
201 def gen():
202 self.assertEqual(sys.exc_info()[0], ValueError)
203 yield "done"
204
205 g = gen()
206 try:
207 raise ValueError
208 except Exception:
209 self.assertEqual(next(g), "done")
210 self.assertEqual(sys.exc_info(), (None, None, None))
211
212 def test_except_gen_except(self):
213 def gen():
214 try:
215 self.assertEqual(sys.exc_info()[0], None)
216 yield
217 # we are called from "except ValueError:", TypeError must
218 # inherit ValueError in its context
219 raise TypeError()
220 except TypeError as exc:
221 self.assertEqual(sys.exc_info()[0], TypeError)
222 self.assertEqual(type(exc.__context__), ValueError)
223 # here we are still called from the "except ValueError:"
224 self.assertEqual(sys.exc_info()[0], ValueError)
225 yield
226 self.assertIsNone(sys.exc_info()[0])
227 yield "done"
228
229 g = gen()
230 next(g)
231 try:
232 raise ValueError
233 except Exception:
234 next(g)
235
236 self.assertEqual(next(g), "done")
237 self.assertEqual(sys.exc_info(), (None, None, None))
238
239 def test_except_throw_exception_context(self):
240 def gen():
241 try:
242 try:
243 self.assertEqual(sys.exc_info()[0], None)
244 yield
245 except ValueError:
246 # we are called from "except ValueError:"
247 self.assertEqual(sys.exc_info()[0], ValueError)
248 raise TypeError()
249 except Exception as exc:
250 self.assertEqual(sys.exc_info()[0], TypeError)
251 self.assertEqual(type(exc.__context__), ValueError)
252 # we are still called from "except ValueError:"
253 self.assertEqual(sys.exc_info()[0], ValueError)
254 yield
255 self.assertIsNone(sys.exc_info()[0])
256 yield "done"
257
258 g = gen()
259 next(g)
260 try:
261 raise ValueError
262 except Exception as exc:
263 g.throw(exc)
264
265 self.assertEqual(next(g), "done")
266 self.assertEqual(sys.exc_info(), (None, None, None))
267
Yury Selivanov68333392015-05-22 11:16:47 -0400268 def test_stopiteration_warning(self):
269 # See also PEP 479.
270
271 def gen():
272 raise StopIteration
273 yield
274
275 with self.assertRaises(StopIteration), \
Martin Panter7e3a91a2016-02-10 04:40:48 +0000276 self.assertWarnsRegex(DeprecationWarning, "StopIteration"):
Yury Selivanov68333392015-05-22 11:16:47 -0400277
278 next(gen())
279
Martin Panter7e3a91a2016-02-10 04:40:48 +0000280 with self.assertRaisesRegex(DeprecationWarning,
Yury Selivanov68333392015-05-22 11:16:47 -0400281 "generator .* raised StopIteration"), \
282 warnings.catch_warnings():
283
284 warnings.simplefilter('error')
285 next(gen())
286
287
288 def test_tutorial_stopiteration(self):
289 # Raise StopIteration" stops the generator too:
290
291 def f():
292 yield 1
293 raise StopIteration
294 yield 2 # never reached
295
296 g = f()
297 self.assertEqual(next(g), 1)
298
Martin Panter7e3a91a2016-02-10 04:40:48 +0000299 with self.assertWarnsRegex(DeprecationWarning, "StopIteration"):
Yury Selivanov68333392015-05-22 11:16:47 -0400300 with self.assertRaises(StopIteration):
301 next(g)
302
303 with self.assertRaises(StopIteration):
304 # This time StopIteration isn't raised from the generator's body,
305 # hence no warning.
306 next(g)
307
Serhiy Storchaka24411f82016-11-06 18:44:42 +0200308 def test_return_tuple(self):
309 def g():
310 return (yield 1)
311
312 gen = g()
313 self.assertEqual(next(gen), 1)
314 with self.assertRaises(StopIteration) as cm:
315 gen.send((2,))
316 self.assertEqual(cm.exception.value, (2,))
317
318 def test_return_stopiteration(self):
319 def g():
320 return (yield 1)
321
322 gen = g()
323 self.assertEqual(next(gen), 1)
324 with self.assertRaises(StopIteration) as cm:
325 gen.send(StopIteration(2))
326 self.assertIsInstance(cm.exception.value, StopIteration)
327 self.assertEqual(cm.exception.value.value, 2)
328
Victor Stinner26f7b8a2015-01-31 10:29:47 +0100329
Yury Selivanove13f8f32015-07-03 00:23:30 -0400330class YieldFromTests(unittest.TestCase):
331 def test_generator_gi_yieldfrom(self):
332 def a():
333 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING)
334 self.assertIsNone(gen_b.gi_yieldfrom)
335 yield
336 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_RUNNING)
337 self.assertIsNone(gen_b.gi_yieldfrom)
338
339 def b():
340 self.assertIsNone(gen_b.gi_yieldfrom)
341 yield from a()
342 self.assertIsNone(gen_b.gi_yieldfrom)
343 yield
344 self.assertIsNone(gen_b.gi_yieldfrom)
345
346 gen_b = b()
347 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CREATED)
348 self.assertIsNone(gen_b.gi_yieldfrom)
349
350 gen_b.send(None)
351 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED)
352 self.assertEqual(gen_b.gi_yieldfrom.gi_code.co_name, 'a')
353
354 gen_b.send(None)
355 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_SUSPENDED)
356 self.assertIsNone(gen_b.gi_yieldfrom)
357
358 [] = gen_b # Exhaust generator
359 self.assertEqual(inspect.getgeneratorstate(gen_b), inspect.GEN_CLOSED)
360 self.assertIsNone(gen_b.gi_yieldfrom)
361
362
Tim Peters6ba5f792001-06-23 20:45:43 +0000363tutorial_tests = """
Tim Peters1def3512001-06-23 20:27:04 +0000364Let's try a simple generator:
365
366 >>> def f():
367 ... yield 1
368 ... yield 2
369
Tim Petersb9e9ff12001-06-24 03:44:52 +0000370 >>> for i in f():
Guido van Rossum7131f842007-02-09 20:13:25 +0000371 ... print(i)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000372 1
373 2
Tim Peters1def3512001-06-23 20:27:04 +0000374 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000375 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000376 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000377 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000378 2
Tim Petersea2e97a2001-06-24 07:10:02 +0000379
Tim Peters2106ef02001-06-25 01:30:12 +0000380"Falling off the end" stops the generator:
Tim Petersea2e97a2001-06-24 07:10:02 +0000381
Georg Brandla18af4e2007-04-21 15:47:16 +0000382 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000383 Traceback (most recent call last):
384 File "<stdin>", line 1, in ?
385 File "<stdin>", line 2, in g
386 StopIteration
387
Tim Petersea2e97a2001-06-24 07:10:02 +0000388"return" also stops the generator:
Tim Peters1def3512001-06-23 20:27:04 +0000389
390 >>> def f():
391 ... yield 1
392 ... return
393 ... yield 2 # never reached
394 ...
395 >>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +0000396 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000397 1
Georg Brandla18af4e2007-04-21 15:47:16 +0000398 >>> next(g)
Tim Peters1def3512001-06-23 20:27:04 +0000399 Traceback (most recent call last):
400 File "<stdin>", line 1, in ?
401 File "<stdin>", line 3, in f
402 StopIteration
Georg Brandla18af4e2007-04-21 15:47:16 +0000403 >>> next(g) # once stopped, can't be resumed
Tim Peters1def3512001-06-23 20:27:04 +0000404 Traceback (most recent call last):
405 File "<stdin>", line 1, in ?
406 StopIteration
407
Yury Selivanov68333392015-05-22 11:16:47 -0400408However, "return" and StopIteration are not exactly equivalent:
Tim Peters1def3512001-06-23 20:27:04 +0000409
410 >>> def g1():
411 ... try:
412 ... return
413 ... except:
414 ... yield 1
415 ...
416 >>> list(g1())
417 []
418
419 >>> def g2():
420 ... try:
421 ... raise StopIteration
422 ... except:
423 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000424 >>> print(list(g2()))
Tim Peters1def3512001-06-23 20:27:04 +0000425 [42]
426
427This may be surprising at first:
428
429 >>> def g3():
430 ... try:
431 ... return
432 ... finally:
433 ... yield 1
434 ...
435 >>> list(g3())
436 [1]
437
438Let's create an alternate range() function implemented as a generator:
439
440 >>> def yrange(n):
441 ... for i in range(n):
442 ... yield i
443 ...
444 >>> list(yrange(5))
445 [0, 1, 2, 3, 4]
446
447Generators always return to the most recent caller:
448
449 >>> def creator():
450 ... r = yrange(5)
Georg Brandla18af4e2007-04-21 15:47:16 +0000451 ... print("creator", next(r))
Tim Peters1def3512001-06-23 20:27:04 +0000452 ... return r
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000453 ...
Tim Peters1def3512001-06-23 20:27:04 +0000454 >>> def caller():
455 ... r = creator()
456 ... for i in r:
Guido van Rossum7131f842007-02-09 20:13:25 +0000457 ... print("caller", i)
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000458 ...
Tim Peters1def3512001-06-23 20:27:04 +0000459 >>> caller()
460 creator 0
461 caller 1
462 caller 2
463 caller 3
464 caller 4
465
466Generators can call other generators:
467
468 >>> def zrange(n):
469 ... for i in yrange(n):
470 ... yield i
471 ...
472 >>> list(zrange(5))
473 [0, 1, 2, 3, 4]
474
475"""
476
Tim Peters6ba5f792001-06-23 20:45:43 +0000477# The examples from PEP 255.
478
479pep_tests = """
480
Tim Peterse5614632001-08-15 04:41:19 +0000481Specification: Yield
482
483 Restriction: A generator cannot be resumed while it is actively
484 running:
485
486 >>> def g():
Georg Brandla18af4e2007-04-21 15:47:16 +0000487 ... i = next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000488 ... yield i
489 >>> me = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000490 >>> next(me)
Tim Peterse5614632001-08-15 04:41:19 +0000491 Traceback (most recent call last):
492 ...
493 File "<string>", line 2, in g
494 ValueError: generator already executing
495
Tim Peters6ba5f792001-06-23 20:45:43 +0000496Specification: Return
497
498 Note that return isn't always equivalent to raising StopIteration: the
499 difference lies in how enclosing try/except constructs are treated.
500 For example,
501
502 >>> def f1():
503 ... try:
504 ... return
505 ... except:
506 ... yield 1
Guido van Rossum7131f842007-02-09 20:13:25 +0000507 >>> print(list(f1()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000508 []
509
510 because, as in any function, return simply exits, but
511
512 >>> def f2():
513 ... try:
514 ... raise StopIteration
515 ... except:
516 ... yield 42
Guido van Rossum7131f842007-02-09 20:13:25 +0000517 >>> print(list(f2()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000518 [42]
519
520 because StopIteration is captured by a bare "except", as is any
521 exception.
522
523Specification: Generators and Exception Propagation
524
525 >>> def f():
Tim Peters3caca232001-12-06 06:23:26 +0000526 ... return 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000527 >>> def g():
528 ... yield f() # the zero division exception propagates
529 ... yield 42 # and we'll never get here
530 >>> k = g()
Georg Brandla18af4e2007-04-21 15:47:16 +0000531 >>> next(k)
Tim Peters6ba5f792001-06-23 20:45:43 +0000532 Traceback (most recent call last):
533 File "<stdin>", line 1, in ?
534 File "<stdin>", line 2, in g
535 File "<stdin>", line 2, in f
536 ZeroDivisionError: integer division or modulo by zero
Georg Brandla18af4e2007-04-21 15:47:16 +0000537 >>> next(k) # and the generator cannot be resumed
Tim Peters6ba5f792001-06-23 20:45:43 +0000538 Traceback (most recent call last):
539 File "<stdin>", line 1, in ?
540 StopIteration
541 >>>
542
543Specification: Try/Except/Finally
544
545 >>> def f():
546 ... try:
547 ... yield 1
548 ... try:
549 ... yield 2
Tim Peters3caca232001-12-06 06:23:26 +0000550 ... 1//0
Tim Peters6ba5f792001-06-23 20:45:43 +0000551 ... yield 3 # never get here
552 ... except ZeroDivisionError:
553 ... yield 4
554 ... yield 5
555 ... raise
556 ... except:
557 ... yield 6
558 ... yield 7 # the "raise" above stops this
559 ... except:
560 ... yield 8
561 ... yield 9
562 ... try:
563 ... x = 12
564 ... finally:
565 ... yield 10
566 ... yield 11
Guido van Rossum7131f842007-02-09 20:13:25 +0000567 >>> print(list(f()))
Tim Peters6ba5f792001-06-23 20:45:43 +0000568 [1, 2, 4, 5, 8, 9, 10, 11]
569 >>>
570
Tim Peters6ba5f792001-06-23 20:45:43 +0000571Guido's binary tree example.
572
573 >>> # A binary tree class.
574 >>> class Tree:
575 ...
576 ... def __init__(self, label, left=None, right=None):
577 ... self.label = label
578 ... self.left = left
579 ... self.right = right
580 ...
581 ... def __repr__(self, level=0, indent=" "):
Walter Dörwald70a6b492004-02-12 17:35:32 +0000582 ... s = level*indent + repr(self.label)
Tim Peters6ba5f792001-06-23 20:45:43 +0000583 ... if self.left:
584 ... s = s + "\\n" + self.left.__repr__(level+1, indent)
585 ... if self.right:
586 ... s = s + "\\n" + self.right.__repr__(level+1, indent)
587 ... return s
588 ...
589 ... def __iter__(self):
590 ... return inorder(self)
591
592 >>> # Create a Tree from a list.
593 >>> def tree(list):
594 ... n = len(list)
595 ... if n == 0:
596 ... return []
Tim Peters3caca232001-12-06 06:23:26 +0000597 ... i = n // 2
Tim Peters6ba5f792001-06-23 20:45:43 +0000598 ... return Tree(list[i], tree(list[:i]), tree(list[i+1:]))
599
600 >>> # Show it off: create a tree.
601 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
602
Tim Petersd674e172002-03-10 07:59:13 +0000603 >>> # A recursive generator that generates Tree labels in in-order.
Tim Peters6ba5f792001-06-23 20:45:43 +0000604 >>> def inorder(t):
605 ... if t:
606 ... for x in inorder(t.left):
607 ... yield x
608 ... yield t.label
609 ... for x in inorder(t.right):
610 ... yield x
611
612 >>> # Show it off: create a tree.
Edward Loper103d26e2004-08-09 02:03:30 +0000613 >>> t = tree("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
614 >>> # Print the nodes of the tree in in-order.
615 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000616 ... print(' '+x, end='')
617 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Tim Peters6ba5f792001-06-23 20:45:43 +0000618
619 >>> # A non-recursive generator.
620 >>> def inorder(node):
621 ... stack = []
622 ... while node:
623 ... while node.left:
624 ... stack.append(node)
625 ... node = node.left
626 ... yield node.label
627 ... while not node.right:
628 ... try:
629 ... node = stack.pop()
630 ... except IndexError:
631 ... return
632 ... yield node.label
633 ... node = node.right
634
635 >>> # Exercise the non-recursive generator.
636 >>> for x in t:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000637 ... print(' '+x, end='')
638 A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
Tim Peters6ba5f792001-06-23 20:45:43 +0000639
640"""
641
Tim Petersb2bc6a92001-06-24 10:14:27 +0000642# Examples from Iterator-List and Python-Dev and c.l.py.
Tim Peters6ba5f792001-06-23 20:45:43 +0000643
644email_tests = """
645
646The difference between yielding None and returning it.
647
648>>> def g():
649... for i in range(3):
650... yield None
651... yield None
652... return
653>>> list(g())
654[None, None, None, None]
655
656Ensure that explicitly raising StopIteration acts like any other exception
657in try/except, not like a return.
658
659>>> def g():
660... yield 1
661... try:
662... raise StopIteration
663... except:
664... yield 2
665... yield 3
666>>> list(g())
667[1, 2, 3]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000668
Tim Petersb2bc6a92001-06-24 10:14:27 +0000669Next one was posted to c.l.py.
670
671>>> def gcomb(x, k):
672... "Generate all combinations of k elements from list x."
673...
674... if k > len(x):
675... return
676... if k == 0:
677... yield []
678... else:
679... first, rest = x[0], x[1:]
680... # A combination does or doesn't contain first.
681... # If it does, the remainder is a k-1 comb of rest.
682... for c in gcomb(rest, k-1):
683... c.insert(0, first)
684... yield c
685... # If it doesn't contain first, it's a k comb of rest.
686... for c in gcomb(rest, k):
687... yield c
688
Guido van Rossum805365e2007-05-07 22:24:25 +0000689>>> seq = list(range(1, 5))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000690>>> for k in range(len(seq) + 2):
Guido van Rossum7131f842007-02-09 20:13:25 +0000691... print("%d-combs of %s:" % (k, seq))
Tim Petersb2bc6a92001-06-24 10:14:27 +0000692... for c in gcomb(seq, k):
Guido van Rossum7131f842007-02-09 20:13:25 +0000693... print(" ", c)
Tim Petersb2bc6a92001-06-24 10:14:27 +00006940-combs of [1, 2, 3, 4]:
695 []
6961-combs of [1, 2, 3, 4]:
697 [1]
698 [2]
699 [3]
700 [4]
7012-combs of [1, 2, 3, 4]:
702 [1, 2]
703 [1, 3]
704 [1, 4]
705 [2, 3]
706 [2, 4]
707 [3, 4]
7083-combs of [1, 2, 3, 4]:
709 [1, 2, 3]
710 [1, 2, 4]
711 [1, 3, 4]
712 [2, 3, 4]
7134-combs of [1, 2, 3, 4]:
714 [1, 2, 3, 4]
7155-combs of [1, 2, 3, 4]:
Tim Peters3e7b1a02001-06-25 19:46:25 +0000716
Tim Peterse77f2e22001-06-26 22:24:51 +0000717From the Iterators list, about the types of these things.
Tim Peters3e7b1a02001-06-25 19:46:25 +0000718
719>>> def g():
720... yield 1
721...
722>>> type(g)
Benjamin Petersonab078e92016-07-13 21:13:29 -0700723<class 'function'>
Tim Peters3e7b1a02001-06-25 19:46:25 +0000724>>> i = g()
725>>> type(i)
Benjamin Petersonab078e92016-07-13 21:13:29 -0700726<class 'generator'>
Tim Peters5d2b77c2001-09-03 05:47:38 +0000727>>> [s for s in dir(i) if not s.startswith('_')]
Yury Selivanove13f8f32015-07-03 00:23:30 -0400728['close', 'gi_code', 'gi_frame', 'gi_running', 'gi_yieldfrom', 'send', 'throw']
Serhiy Storchaka9a11f172013-01-31 16:11:04 +0200729>>> from test.support import HAVE_DOCSTRINGS
Larry Hastings581ee362014-01-28 05:00:08 -0800730>>> print(i.__next__.__doc__ if HAVE_DOCSTRINGS else 'Implement next(self).')
731Implement next(self).
Tim Peters3e7b1a02001-06-25 19:46:25 +0000732>>> iter(i) is i
Guido van Rossum77f6a652002-04-03 22:41:51 +0000733True
Tim Peters3e7b1a02001-06-25 19:46:25 +0000734>>> import types
735>>> isinstance(i, types.GeneratorType)
Guido van Rossum77f6a652002-04-03 22:41:51 +0000736True
Tim Peterse77f2e22001-06-26 22:24:51 +0000737
738And more, added later.
739
740>>> i.gi_running
7410
742>>> type(i.gi_frame)
Benjamin Petersonab078e92016-07-13 21:13:29 -0700743<class 'frame'>
Tim Peterse77f2e22001-06-26 22:24:51 +0000744>>> i.gi_running = 42
745Traceback (most recent call last):
746 ...
Collin Winter42dae6a2007-03-28 21:44:53 +0000747AttributeError: readonly attribute
Tim Peterse77f2e22001-06-26 22:24:51 +0000748>>> def g():
749... yield me.gi_running
750>>> me = g()
751>>> me.gi_running
7520
Georg Brandla18af4e2007-04-21 15:47:16 +0000753>>> next(me)
Tim Peterse77f2e22001-06-26 22:24:51 +00007541
755>>> me.gi_running
7560
Tim Peters35302662001-07-02 01:38:33 +0000757
758A clever union-find implementation from c.l.py, due to David Eppstein.
759Sent: Friday, June 29, 2001 12:16 PM
760To: python-list@python.org
761Subject: Re: PEP 255: Simple Generators
762
763>>> class disjointSet:
764... def __init__(self, name):
765... self.name = name
766... self.parent = None
767... self.generator = self.generate()
768...
769... def generate(self):
770... while not self.parent:
771... yield self
772... for x in self.parent.generator:
773... yield x
774...
775... def find(self):
Georg Brandla18af4e2007-04-21 15:47:16 +0000776... return next(self.generator)
Tim Peters35302662001-07-02 01:38:33 +0000777...
778... def union(self, parent):
779... if self.parent:
780... raise ValueError("Sorry, I'm not a root!")
781... self.parent = parent
782...
783... def __str__(self):
784... return self.name
Tim Peters35302662001-07-02 01:38:33 +0000785
786>>> names = "ABCDEFGHIJKLM"
787>>> sets = [disjointSet(name) for name in names]
788>>> roots = sets[:]
789
790>>> import random
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000791>>> gen = random.Random(42)
Tim Peters35302662001-07-02 01:38:33 +0000792>>> while 1:
793... for s in sets:
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000794... print(" %s->%s" % (s, s.find()), end='')
Guido van Rossum7131f842007-02-09 20:13:25 +0000795... print()
Tim Peters35302662001-07-02 01:38:33 +0000796... if len(roots) > 1:
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000797... s1 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000798... roots.remove(s1)
Raymond Hettingerdd24a9f2002-12-30 00:46:09 +0000799... s2 = gen.choice(roots)
Tim Peters35302662001-07-02 01:38:33 +0000800... s1.union(s2)
Guido van Rossum7131f842007-02-09 20:13:25 +0000801... print("merged", s1, "into", s2)
Tim Peters35302662001-07-02 01:38:33 +0000802... else:
803... break
Guido van Rossumc420b2f2007-02-09 22:09:01 +0000804 A->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->K L->L M->M
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000805merged K into B
806 A->A B->B C->C D->D E->E F->F G->G H->H I->I J->J K->B L->L M->M
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000807merged A into F
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000808 A->F B->B C->C D->D E->E F->F G->G H->H I->I J->J K->B L->L M->M
809merged E into F
810 A->F B->B C->C D->D E->F F->F G->G H->H I->I J->J K->B L->L M->M
811merged D into C
812 A->F B->B C->C D->C E->F F->F G->G H->H I->I J->J K->B L->L M->M
Raymond Hettinger28de64f2008-01-13 23:40:30 +0000813merged M into C
Raymond Hettingerc585eec2010-09-07 15:00:15 +0000814 A->F B->B C->C D->C E->F F->F G->G H->H I->I J->J K->B L->L M->C
815merged J into B
816 A->F B->B C->C D->C E->F F->F G->G H->H I->I J->B K->B L->L M->C
817merged B into C
818 A->F B->C C->C D->C E->F F->F G->G H->H I->I J->C K->C L->L M->C
819merged F into G
820 A->G B->C C->C D->C E->G F->G G->G H->H I->I J->C K->C L->L M->C
821merged L into C
822 A->G B->C C->C D->C E->G F->G G->G H->H I->I J->C K->C L->C M->C
823merged G into I
824 A->I B->C C->C D->C E->I F->I G->I H->H I->I J->C K->C L->C M->C
825merged I into H
826 A->H B->C C->C D->C E->H F->H G->H H->H I->H J->C K->C L->C M->C
827merged C into H
828 A->H B->H C->H D->H E->H F->H G->H H->H I->H J->H K->H L->H M->H
Phillip J. Eby0d6615f2005-08-02 00:46:46 +0000829
Tim Peters6ba5f792001-06-23 20:45:43 +0000830"""
Barry Warsaw04f357c2002-07-23 19:04:11 +0000831# Emacs turd '
Tim Peters6ba5f792001-06-23 20:45:43 +0000832
Tim Peters0f9da0a2001-06-23 21:01:47 +0000833# Fun tests (for sufficiently warped notions of "fun").
834
835fun_tests = """
836
837Build up to a recursive Sieve of Eratosthenes generator.
838
839>>> def firstn(g, n):
Georg Brandla18af4e2007-04-21 15:47:16 +0000840... return [next(g) for i in range(n)]
Tim Peters0f9da0a2001-06-23 21:01:47 +0000841
842>>> def intsfrom(i):
843... while 1:
844... yield i
845... i += 1
846
847>>> firstn(intsfrom(5), 7)
848[5, 6, 7, 8, 9, 10, 11]
849
850>>> def exclude_multiples(n, ints):
851... for i in ints:
852... if i % n:
853... yield i
854
855>>> firstn(exclude_multiples(3, intsfrom(1)), 6)
856[1, 2, 4, 5, 7, 8]
857
858>>> def sieve(ints):
Georg Brandla18af4e2007-04-21 15:47:16 +0000859... prime = next(ints)
Tim Peters0f9da0a2001-06-23 21:01:47 +0000860... yield prime
861... not_divisible_by_prime = exclude_multiples(prime, ints)
862... for p in sieve(not_divisible_by_prime):
863... yield p
864
865>>> primes = sieve(intsfrom(2))
866>>> firstn(primes, 20)
867[2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71]
Tim Petersb9e9ff12001-06-24 03:44:52 +0000868
Tim Petersf6ed0742001-06-27 07:17:57 +0000869
Tim Petersb9e9ff12001-06-24 03:44:52 +0000870Another famous problem: generate all integers of the form
871 2**i * 3**j * 5**k
872in increasing order, where i,j,k >= 0. Trickier than it may look at first!
873Try writing it without generators, and correctly, and without generating
8743 internal results for each result output.
875
876>>> def times(n, g):
877... for i in g:
878... yield n * i
879>>> firstn(times(10, intsfrom(1)), 10)
880[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
881
882>>> def merge(g, h):
Georg Brandla18af4e2007-04-21 15:47:16 +0000883... ng = next(g)
884... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000885... while 1:
886... if ng < nh:
887... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000888... ng = next(g)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000889... elif ng > nh:
890... yield nh
Georg Brandla18af4e2007-04-21 15:47:16 +0000891... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000892... else:
893... yield ng
Georg Brandla18af4e2007-04-21 15:47:16 +0000894... ng = next(g)
895... nh = next(h)
Tim Petersb9e9ff12001-06-24 03:44:52 +0000896
Tim Petersf6ed0742001-06-27 07:17:57 +0000897The following works, but is doing a whale of a lot of redundant work --
898it's not clear how to get the internal uses of m235 to share a single
899generator. Note that me_times2 (etc) each need to see every element in the
900result sequence. So this is an example where lazy lists are more natural
901(you can look at the head of a lazy list any number of times).
Tim Petersb9e9ff12001-06-24 03:44:52 +0000902
903>>> def m235():
904... yield 1
905... me_times2 = times(2, m235())
906... me_times3 = times(3, m235())
907... me_times5 = times(5, m235())
908... for i in merge(merge(me_times2,
909... me_times3),
910... me_times5):
911... yield i
912
Tim Petersf6ed0742001-06-27 07:17:57 +0000913Don't print "too many" of these -- the implementation above is extremely
914inefficient: each call of m235() leads to 3 recursive calls, and in
915turn each of those 3 more, and so on, and so on, until we've descended
916enough levels to satisfy the print stmts. Very odd: when I printed 5
917lines of results below, this managed to screw up Win98's malloc in "the
918usual" way, i.e. the heap grew over 4Mb so Win98 started fragmenting
919address space, and it *looked* like a very slow leak.
920
Tim Petersb9e9ff12001-06-24 03:44:52 +0000921>>> result = m235()
Tim Petersf6ed0742001-06-27 07:17:57 +0000922>>> for i in range(3):
Guido van Rossum7131f842007-02-09 20:13:25 +0000923... print(firstn(result, 15))
Tim Petersb9e9ff12001-06-24 03:44:52 +0000924[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
925[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
926[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
Tim Petersee309272001-06-24 05:47:06 +0000927
928Heh. Here's one way to get a shared list, complete with an excruciating
929namespace renaming trick. The *pretty* part is that the times() and merge()
930functions can be reused as-is, because they only assume their stream
931arguments are iterable -- a LazyList is the same as a generator to times().
932
933>>> class LazyList:
934... def __init__(self, g):
935... self.sofar = []
Georg Brandla18af4e2007-04-21 15:47:16 +0000936... self.fetch = g.__next__
Tim Petersee309272001-06-24 05:47:06 +0000937...
938... def __getitem__(self, i):
939... sofar, fetch = self.sofar, self.fetch
940... while i >= len(sofar):
941... sofar.append(fetch())
942... return sofar[i]
943
944>>> def m235():
945... yield 1
Tim Petersea2e97a2001-06-24 07:10:02 +0000946... # Gack: m235 below actually refers to a LazyList.
Tim Petersee309272001-06-24 05:47:06 +0000947... me_times2 = times(2, m235)
948... me_times3 = times(3, m235)
949... me_times5 = times(5, m235)
950... for i in merge(merge(me_times2,
951... me_times3),
952... me_times5):
953... yield i
954
Tim Petersf6ed0742001-06-27 07:17:57 +0000955Print as many of these as you like -- *this* implementation is memory-
Neil Schemenauerb20e9db2001-07-12 13:26:41 +0000956efficient.
Tim Petersf6ed0742001-06-27 07:17:57 +0000957
Tim Petersee309272001-06-24 05:47:06 +0000958>>> m235 = LazyList(m235())
959>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +0000960... print([m235[j] for j in range(15*i, 15*(i+1))])
Tim Petersee309272001-06-24 05:47:06 +0000961[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
962[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
963[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
964[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
965[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
Tim Petersf6ed0742001-06-27 07:17:57 +0000966
Tim Petersf6ed0742001-06-27 07:17:57 +0000967Ye olde Fibonacci generator, LazyList style.
968
969>>> def fibgen(a, b):
970...
971... def sum(g, h):
972... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +0000973... yield next(g) + next(h)
Tim Petersf6ed0742001-06-27 07:17:57 +0000974...
975... def tail(g):
Georg Brandla18af4e2007-04-21 15:47:16 +0000976... next(g) # throw first away
Tim Petersf6ed0742001-06-27 07:17:57 +0000977... for x in g:
978... yield x
979...
980... yield a
981... yield b
982... for s in sum(iter(fib),
983... tail(iter(fib))):
984... yield s
985
986>>> fib = LazyList(fibgen(1, 2))
987>>> firstn(iter(fib), 17)
988[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
Georg Brandl52715f62005-08-24 09:02:29 +0000989
990
991Running after your tail with itertools.tee (new in version 2.4)
992
993The algorithms "m235" (Hamming) and Fibonacci presented above are both
994examples of a whole family of FP (functional programming) algorithms
995where a function produces and returns a list while the production algorithm
996suppose the list as already produced by recursively calling itself.
997For these algorithms to work, they must:
998
999- produce at least a first element without presupposing the existence of
1000 the rest of the list
1001- produce their elements in a lazy manner
1002
1003To work efficiently, the beginning of the list must not be recomputed over
1004and over again. This is ensured in most FP languages as a built-in feature.
1005In python, we have to explicitly maintain a list of already computed results
1006and abandon genuine recursivity.
1007
1008This is what had been attempted above with the LazyList class. One problem
1009with that class is that it keeps a list of all of the generated results and
1010therefore continually grows. This partially defeats the goal of the generator
1011concept, viz. produce the results only as needed instead of producing them
1012all and thereby wasting memory.
1013
1014Thanks to itertools.tee, it is now clear "how to get the internal uses of
1015m235 to share a single generator".
1016
1017>>> from itertools import tee
1018>>> def m235():
1019... def _m235():
1020... yield 1
1021... for n in merge(times(2, m2),
1022... merge(times(3, m3),
1023... times(5, m5))):
1024... yield n
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001025... m1 = _m235()
1026... m2, m3, m5, mRes = tee(m1, 4)
Georg Brandl52715f62005-08-24 09:02:29 +00001027... return mRes
1028
1029>>> it = m235()
1030>>> for i in range(5):
Guido van Rossum7131f842007-02-09 20:13:25 +00001031... print(firstn(it, 15))
Georg Brandl52715f62005-08-24 09:02:29 +00001032[1, 2, 3, 4, 5, 6, 8, 9, 10, 12, 15, 16, 18, 20, 24]
1033[25, 27, 30, 32, 36, 40, 45, 48, 50, 54, 60, 64, 72, 75, 80]
1034[81, 90, 96, 100, 108, 120, 125, 128, 135, 144, 150, 160, 162, 180, 192]
1035[200, 216, 225, 240, 243, 250, 256, 270, 288, 300, 320, 324, 360, 375, 384]
1036[400, 405, 432, 450, 480, 486, 500, 512, 540, 576, 600, 625, 640, 648, 675]
1037
1038The "tee" function does just what we want. It internally keeps a generated
1039result for as long as it has not been "consumed" from all of the duplicated
1040iterators, whereupon it is deleted. You can therefore print the hamming
1041sequence during hours without increasing memory usage, or very little.
1042
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001043The beauty of it is that recursive running-after-their-tail FP algorithms
Georg Brandl52715f62005-08-24 09:02:29 +00001044are quite straightforwardly expressed with this Python idiom.
1045
Georg Brandl52715f62005-08-24 09:02:29 +00001046Ye olde Fibonacci generator, tee style.
1047
1048>>> def fib():
Tim Peters9e34c042005-08-26 15:20:46 +00001049...
Georg Brandl52715f62005-08-24 09:02:29 +00001050... def _isum(g, h):
1051... while 1:
Georg Brandla18af4e2007-04-21 15:47:16 +00001052... yield next(g) + next(h)
Tim Peters9e34c042005-08-26 15:20:46 +00001053...
Georg Brandl52715f62005-08-24 09:02:29 +00001054... def _fib():
1055... yield 1
1056... yield 2
Georg Brandla18af4e2007-04-21 15:47:16 +00001057... next(fibTail) # throw first away
Georg Brandl52715f62005-08-24 09:02:29 +00001058... for res in _isum(fibHead, fibTail):
1059... yield res
Tim Peters9e34c042005-08-26 15:20:46 +00001060...
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001061... realfib = _fib()
1062... fibHead, fibTail, fibRes = tee(realfib, 3)
Georg Brandl52715f62005-08-24 09:02:29 +00001063... return fibRes
1064
1065>>> firstn(fib(), 17)
1066[1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584]
1067
Tim Peters0f9da0a2001-06-23 21:01:47 +00001068"""
1069
Tim Petersb6c3cea2001-06-26 03:36:28 +00001070# syntax_tests mostly provokes SyntaxErrors. Also fiddling with #if 0
1071# hackery.
Tim Petersee309272001-06-24 05:47:06 +00001072
Tim Petersea2e97a2001-06-24 07:10:02 +00001073syntax_tests = """
1074
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001075These are fine:
Tim Petersea2e97a2001-06-24 07:10:02 +00001076
1077>>> def f():
1078... yield 1
1079... return
1080
Tim Petersaef8cfa2004-08-27 15:12:49 +00001081>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +00001082... try:
1083... yield 1
1084... finally:
1085... pass
Tim Petersea2e97a2001-06-24 07:10:02 +00001086
Tim Petersaef8cfa2004-08-27 15:12:49 +00001087>>> def f():
Tim Petersea2e97a2001-06-24 07:10:02 +00001088... try:
1089... try:
Tim Peters3caca232001-12-06 06:23:26 +00001090... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +00001091... except ZeroDivisionError:
Tim Peters536cf992005-12-25 23:18:31 +00001092... yield 666
Tim Petersea2e97a2001-06-24 07:10:02 +00001093... except:
1094... pass
1095... finally:
1096... pass
Tim Petersea2e97a2001-06-24 07:10:02 +00001097
1098>>> def f():
1099... try:
1100... try:
1101... yield 12
Tim Peters3caca232001-12-06 06:23:26 +00001102... 1//0
Tim Petersea2e97a2001-06-24 07:10:02 +00001103... except ZeroDivisionError:
1104... yield 666
1105... except:
1106... try:
1107... x = 12
1108... finally:
1109... yield 12
1110... except:
1111... return
1112>>> list(f())
1113[12, 666]
Tim Petersb6c3cea2001-06-26 03:36:28 +00001114
1115>>> def f():
Tim Peters08a898f2001-06-28 01:52:22 +00001116... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001117>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001118<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001119
Tim Peters08a898f2001-06-28 01:52:22 +00001120
1121>>> def f():
1122... if 0:
1123... yield
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001124>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001125<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001126
Tim Peters08a898f2001-06-28 01:52:22 +00001127
1128>>> def f():
Tim Petersb6c3cea2001-06-26 03:36:28 +00001129... if 0:
1130... yield 1
1131>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001132<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001133
1134>>> def f():
1135... if "":
1136... yield None
1137>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001138<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001139
1140>>> def f():
1141... return
1142... try:
1143... if x==4:
1144... pass
1145... elif 0:
1146... try:
Tim Peters3caca232001-12-06 06:23:26 +00001147... 1//0
Tim Petersb6c3cea2001-06-26 03:36:28 +00001148... except SyntaxError:
1149... pass
1150... else:
1151... if 0:
1152... while 12:
1153... x += 1
1154... yield 2 # don't blink
1155... f(a, b, c, d, e)
1156... else:
1157... pass
1158... except:
1159... x = 1
1160... return
1161>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001162<class 'generator'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001163
1164>>> def f():
1165... if 0:
1166... def g():
1167... yield 1
1168...
1169>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001170<class 'NoneType'>
Tim Petersb6c3cea2001-06-26 03:36:28 +00001171
1172>>> def f():
1173... if 0:
1174... class C:
1175... def __init__(self):
1176... yield 1
1177... def f(self):
1178... yield 2
1179>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001180<class 'NoneType'>
Tim Peters08a898f2001-06-28 01:52:22 +00001181
1182>>> def f():
1183... if 0:
1184... return
1185... if 0:
1186... yield 2
1187>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001188<class 'generator'>
Tim Peters08a898f2001-06-28 01:52:22 +00001189
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00001190This one caused a crash (see SF bug 567538):
1191
1192>>> def f():
1193... for i in range(3):
1194... try:
1195... continue
1196... finally:
1197... yield i
Tim Petersc411dba2002-07-16 21:35:23 +00001198...
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00001199>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001200>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +000012010
Georg Brandla18af4e2007-04-21 15:47:16 +00001202>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +000012031
Georg Brandla18af4e2007-04-21 15:47:16 +00001204>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +000012052
Georg Brandla18af4e2007-04-21 15:47:16 +00001206>>> print(next(g))
Guido van Rossumc5fe5eb2002-06-12 03:45:21 +00001207Traceback (most recent call last):
1208StopIteration
Christian Heimesaf98da12008-01-27 15:18:18 +00001209
1210
1211Test the gi_code attribute
1212
1213>>> def f():
1214... yield 5
1215...
1216>>> g = f()
1217>>> g.gi_code is f.__code__
1218True
1219>>> next(g)
12205
1221>>> next(g)
1222Traceback (most recent call last):
1223StopIteration
1224>>> g.gi_code is f.__code__
1225True
1226
Alexandre Vassalottie9f305f2008-05-16 04:39:54 +00001227
1228Test the __name__ attribute and the repr()
1229
1230>>> def f():
1231... yield 5
1232...
1233>>> g = f()
1234>>> g.__name__
1235'f'
1236>>> repr(g) # doctest: +ELLIPSIS
Alexandre Vassalottibee32532008-05-16 18:15:12 +00001237'<generator object f at ...>'
Benjamin Peterson371ccfb2008-12-27 19:03:36 +00001238
1239Lambdas shouldn't have their usual return behavior.
1240
1241>>> x = lambda: (yield 1)
1242>>> list(x())
1243[1]
1244
1245>>> x = lambda: ((yield 1), (yield 2))
1246>>> list(x())
1247[1, 2]
Tim Petersea2e97a2001-06-24 07:10:02 +00001248"""
1249
Tim Petersbe4f0a72001-06-29 02:41:16 +00001250# conjoin is a simple backtracking generator, named in honor of Icon's
1251# "conjunction" control structure. Pass a list of no-argument functions
1252# that return iterable objects. Easiest to explain by example: assume the
1253# function list [x, y, z] is passed. Then conjoin acts like:
1254#
1255# def g():
1256# values = [None] * 3
1257# for values[0] in x():
1258# for values[1] in y():
1259# for values[2] in z():
1260# yield values
1261#
1262# So some 3-lists of values *may* be generated, each time we successfully
1263# get into the innermost loop. If an iterator fails (is exhausted) before
1264# then, it "backtracks" to get the next value from the nearest enclosing
1265# iterator (the one "to the left"), and starts all over again at the next
1266# slot (pumps a fresh iterator). Of course this is most useful when the
1267# iterators have side-effects, so that which values *can* be generated at
1268# each slot depend on the values iterated at previous slots.
1269
Benjamin Peterson78565b22009-06-28 19:19:51 +00001270def simple_conjoin(gs):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001271
1272 values = [None] * len(gs)
1273
Benjamin Peterson78565b22009-06-28 19:19:51 +00001274 def gen(i):
Tim Petersbe4f0a72001-06-29 02:41:16 +00001275 if i >= len(gs):
1276 yield values
1277 else:
1278 for values[i] in gs[i]():
1279 for x in gen(i+1):
1280 yield x
1281
1282 for x in gen(0):
1283 yield x
1284
Tim Petersc468fd22001-06-30 07:29:44 +00001285# That works fine, but recursing a level and checking i against len(gs) for
1286# each item produced is inefficient. By doing manual loop unrolling across
1287# generator boundaries, it's possible to eliminate most of that overhead.
1288# This isn't worth the bother *in general* for generators, but conjoin() is
1289# a core building block for some CPU-intensive generator applications.
1290
1291def conjoin(gs):
1292
1293 n = len(gs)
1294 values = [None] * n
1295
1296 # Do one loop nest at time recursively, until the # of loop nests
1297 # remaining is divisible by 3.
1298
Benjamin Peterson78565b22009-06-28 19:19:51 +00001299 def gen(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001300 if i >= n:
1301 yield values
1302
1303 elif (n-i) % 3:
1304 ip1 = i+1
1305 for values[i] in gs[i]():
1306 for x in gen(ip1):
1307 yield x
1308
1309 else:
1310 for x in _gen3(i):
1311 yield x
1312
1313 # Do three loop nests at a time, recursing only if at least three more
1314 # remain. Don't call directly: this is an internal optimization for
1315 # gen's use.
1316
Benjamin Peterson78565b22009-06-28 19:19:51 +00001317 def _gen3(i):
Tim Petersc468fd22001-06-30 07:29:44 +00001318 assert i < n and (n-i) % 3 == 0
1319 ip1, ip2, ip3 = i+1, i+2, i+3
1320 g, g1, g2 = gs[i : ip3]
1321
1322 if ip3 >= n:
1323 # These are the last three, so we can yield values directly.
1324 for values[i] in g():
1325 for values[ip1] in g1():
1326 for values[ip2] in g2():
1327 yield values
1328
1329 else:
1330 # At least 6 loop nests remain; peel off 3 and recurse for the
1331 # rest.
1332 for values[i] in g():
1333 for values[ip1] in g1():
1334 for values[ip2] in g2():
1335 for x in _gen3(ip3):
1336 yield x
1337
1338 for x in gen(0):
1339 yield x
1340
unknown31569562001-07-04 22:11:22 +00001341# And one more approach: For backtracking apps like the Knight's Tour
1342# solver below, the number of backtracking levels can be enormous (one
1343# level per square, for the Knight's Tour, so that e.g. a 100x100 board
1344# needs 10,000 levels). In such cases Python is likely to run out of
1345# stack space due to recursion. So here's a recursion-free version of
1346# conjoin too.
1347# NOTE WELL: This allows large problems to be solved with only trivial
1348# demands on stack space. Without explicitly resumable generators, this is
Tim Peters9a8c8e22001-07-13 09:12:12 +00001349# much harder to achieve. OTOH, this is much slower (up to a factor of 2)
1350# than the fancy unrolled recursive conjoin.
unknown31569562001-07-04 22:11:22 +00001351
1352def flat_conjoin(gs): # rename to conjoin to run tests with this instead
1353 n = len(gs)
1354 values = [None] * n
1355 iters = [None] * n
Tim Peters9a8c8e22001-07-13 09:12:12 +00001356 _StopIteration = StopIteration # make local because caught a *lot*
unknown31569562001-07-04 22:11:22 +00001357 i = 0
Tim Peters9a8c8e22001-07-13 09:12:12 +00001358 while 1:
1359 # Descend.
1360 try:
1361 while i < n:
Georg Brandla18af4e2007-04-21 15:47:16 +00001362 it = iters[i] = gs[i]().__next__
Tim Peters9a8c8e22001-07-13 09:12:12 +00001363 values[i] = it()
1364 i += 1
1365 except _StopIteration:
1366 pass
unknown31569562001-07-04 22:11:22 +00001367 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001368 assert i == n
1369 yield values
unknown31569562001-07-04 22:11:22 +00001370
Tim Peters9a8c8e22001-07-13 09:12:12 +00001371 # Backtrack until an older iterator can be resumed.
1372 i -= 1
unknown31569562001-07-04 22:11:22 +00001373 while i >= 0:
1374 try:
1375 values[i] = iters[i]()
Tim Peters9a8c8e22001-07-13 09:12:12 +00001376 # Success! Start fresh at next level.
unknown31569562001-07-04 22:11:22 +00001377 i += 1
1378 break
Tim Peters9a8c8e22001-07-13 09:12:12 +00001379 except _StopIteration:
1380 # Continue backtracking.
1381 i -= 1
1382 else:
1383 assert i < 0
1384 break
unknown31569562001-07-04 22:11:22 +00001385
Tim Petersbe4f0a72001-06-29 02:41:16 +00001386# A conjoin-based N-Queens solver.
1387
1388class Queens:
1389 def __init__(self, n):
1390 self.n = n
1391 rangen = range(n)
1392
1393 # Assign a unique int to each column and diagonal.
1394 # columns: n of those, range(n).
1395 # NW-SE diagonals: 2n-1 of these, i-j unique and invariant along
1396 # each, smallest i-j is 0-(n-1) = 1-n, so add n-1 to shift to 0-
1397 # based.
1398 # NE-SW diagonals: 2n-1 of these, i+j unique and invariant along
1399 # each, smallest i+j is 0, largest is 2n-2.
1400
1401 # For each square, compute a bit vector of the columns and
1402 # diagonals it covers, and for each row compute a function that
Martin Panter46f50722016-05-26 05:35:26 +00001403 # generates the possibilities for the columns in that row.
Tim Petersbe4f0a72001-06-29 02:41:16 +00001404 self.rowgenerators = []
1405 for i in rangen:
Guido van Rossume2a383d2007-01-15 16:59:06 +00001406 rowuses = [(1 << j) | # column ordinal
1407 (1 << (n + i-j + n-1)) | # NW-SE ordinal
1408 (1 << (n + 2*n-1 + i+j)) # NE-SW ordinal
Tim Petersbe4f0a72001-06-29 02:41:16 +00001409 for j in rangen]
1410
1411 def rowgen(rowuses=rowuses):
1412 for j in rangen:
1413 uses = rowuses[j]
Tim Petersc468fd22001-06-30 07:29:44 +00001414 if uses & self.used == 0:
1415 self.used |= uses
1416 yield j
1417 self.used &= ~uses
Tim Petersbe4f0a72001-06-29 02:41:16 +00001418
1419 self.rowgenerators.append(rowgen)
1420
1421 # Generate solutions.
1422 def solve(self):
1423 self.used = 0
1424 for row2col in conjoin(self.rowgenerators):
1425 yield row2col
1426
1427 def printsolution(self, row2col):
1428 n = self.n
1429 assert n == len(row2col)
1430 sep = "+" + "-+" * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001431 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001432 for i in range(n):
1433 squares = [" " for j in range(n)]
1434 squares[row2col[i]] = "Q"
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001435 print("|" + "|".join(squares) + "|")
1436 print(sep)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001437
unknown31569562001-07-04 22:11:22 +00001438# A conjoin-based Knight's Tour solver. This is pretty sophisticated
1439# (e.g., when used with flat_conjoin above, and passing hard=1 to the
1440# constructor, a 200x200 Knight's Tour was found quickly -- note that we're
Tim Peters9a8c8e22001-07-13 09:12:12 +00001441# creating 10s of thousands of generators then!), and is lengthy.
unknown31569562001-07-04 22:11:22 +00001442
1443class Knights:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001444 def __init__(self, m, n, hard=0):
1445 self.m, self.n = m, n
unknown31569562001-07-04 22:11:22 +00001446
Tim Peters9a8c8e22001-07-13 09:12:12 +00001447 # solve() will set up succs[i] to be a list of square #i's
1448 # successors.
1449 succs = self.succs = []
unknown31569562001-07-04 22:11:22 +00001450
Tim Peters9a8c8e22001-07-13 09:12:12 +00001451 # Remove i0 from each of its successor's successor lists, i.e.
1452 # successors can't go back to i0 again. Return 0 if we can
1453 # detect this makes a solution impossible, else return 1.
unknown31569562001-07-04 22:11:22 +00001454
Tim Peters9a8c8e22001-07-13 09:12:12 +00001455 def remove_from_successors(i0, len=len):
unknown31569562001-07-04 22:11:22 +00001456 # If we remove all exits from a free square, we're dead:
1457 # even if we move to it next, we can't leave it again.
1458 # If we create a square with one exit, we must visit it next;
1459 # else somebody else will have to visit it, and since there's
1460 # only one adjacent, there won't be a way to leave it again.
Mike53f7a7c2017-12-14 14:04:53 +03001461 # Finally, if we create more than one free square with a
unknown31569562001-07-04 22:11:22 +00001462 # single exit, we can only move to one of them next, leaving
1463 # the other one a dead end.
1464 ne0 = ne1 = 0
1465 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001466 s = succs[i]
1467 s.remove(i0)
1468 e = len(s)
1469 if e == 0:
1470 ne0 += 1
1471 elif e == 1:
1472 ne1 += 1
unknown31569562001-07-04 22:11:22 +00001473 return ne0 == 0 and ne1 < 2
1474
Tim Peters9a8c8e22001-07-13 09:12:12 +00001475 # Put i0 back in each of its successor's successor lists.
1476
1477 def add_to_successors(i0):
unknown31569562001-07-04 22:11:22 +00001478 for i in succs[i0]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001479 succs[i].append(i0)
unknown31569562001-07-04 22:11:22 +00001480
1481 # Generate the first move.
1482 def first():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001483 if m < 1 or n < 1:
unknown31569562001-07-04 22:11:22 +00001484 return
1485
unknown31569562001-07-04 22:11:22 +00001486 # Since we're looking for a cycle, it doesn't matter where we
1487 # start. Starting in a corner makes the 2nd move easy.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001488 corner = self.coords2index(0, 0)
1489 remove_from_successors(corner)
unknown31569562001-07-04 22:11:22 +00001490 self.lastij = corner
1491 yield corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001492 add_to_successors(corner)
unknown31569562001-07-04 22:11:22 +00001493
1494 # Generate the second moves.
1495 def second():
Tim Peters9a8c8e22001-07-13 09:12:12 +00001496 corner = self.coords2index(0, 0)
unknown31569562001-07-04 22:11:22 +00001497 assert self.lastij == corner # i.e., we started in the corner
Tim Peters9a8c8e22001-07-13 09:12:12 +00001498 if m < 3 or n < 3:
unknown31569562001-07-04 22:11:22 +00001499 return
Tim Peters9a8c8e22001-07-13 09:12:12 +00001500 assert len(succs[corner]) == 2
1501 assert self.coords2index(1, 2) in succs[corner]
1502 assert self.coords2index(2, 1) in succs[corner]
unknown31569562001-07-04 22:11:22 +00001503 # Only two choices. Whichever we pick, the other must be the
Tim Peters9a8c8e22001-07-13 09:12:12 +00001504 # square picked on move m*n, as it's the only way to get back
unknown31569562001-07-04 22:11:22 +00001505 # to (0, 0). Save its index in self.final so that moves before
1506 # the last know it must be kept free.
1507 for i, j in (1, 2), (2, 1):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001508 this = self.coords2index(i, j)
1509 final = self.coords2index(3-i, 3-j)
unknown31569562001-07-04 22:11:22 +00001510 self.final = final
unknown31569562001-07-04 22:11:22 +00001511
Tim Peters9a8c8e22001-07-13 09:12:12 +00001512 remove_from_successors(this)
1513 succs[final].append(corner)
unknown31569562001-07-04 22:11:22 +00001514 self.lastij = this
1515 yield this
Tim Peters9a8c8e22001-07-13 09:12:12 +00001516 succs[final].remove(corner)
1517 add_to_successors(this)
unknown31569562001-07-04 22:11:22 +00001518
Tim Peters9a8c8e22001-07-13 09:12:12 +00001519 # Generate moves 3 thru m*n-1.
1520 def advance(len=len):
unknown31569562001-07-04 22:11:22 +00001521 # If some successor has only one exit, must take it.
1522 # Else favor successors with fewer exits.
1523 candidates = []
1524 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001525 e = len(succs[i])
1526 assert e > 0, "else remove_from_successors() pruning flawed"
1527 if e == 1:
1528 candidates = [(e, i)]
1529 break
1530 candidates.append((e, i))
unknown31569562001-07-04 22:11:22 +00001531 else:
1532 candidates.sort()
1533
1534 for e, i in candidates:
1535 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001536 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001537 self.lastij = i
1538 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001539 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001540
Tim Peters9a8c8e22001-07-13 09:12:12 +00001541 # Generate moves 3 thru m*n-1. Alternative version using a
unknown31569562001-07-04 22:11:22 +00001542 # stronger (but more expensive) heuristic to order successors.
Tim Peters9a8c8e22001-07-13 09:12:12 +00001543 # Since the # of backtracking levels is m*n, a poor move early on
1544 # can take eons to undo. Smallest square board for which this
1545 # matters a lot is 52x52.
1546 def advance_hard(vmid=(m-1)/2.0, hmid=(n-1)/2.0, len=len):
unknown31569562001-07-04 22:11:22 +00001547 # If some successor has only one exit, must take it.
1548 # Else favor successors with fewer exits.
1549 # Break ties via max distance from board centerpoint (favor
1550 # corners and edges whenever possible).
1551 candidates = []
1552 for i in succs[self.lastij]:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001553 e = len(succs[i])
1554 assert e > 0, "else remove_from_successors() pruning flawed"
1555 if e == 1:
1556 candidates = [(e, 0, i)]
1557 break
1558 i1, j1 = self.index2coords(i)
1559 d = (i1 - vmid)**2 + (j1 - hmid)**2
1560 candidates.append((e, -d, i))
unknown31569562001-07-04 22:11:22 +00001561 else:
1562 candidates.sort()
1563
1564 for e, d, i in candidates:
1565 if i != self.final:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001566 if remove_from_successors(i):
unknown31569562001-07-04 22:11:22 +00001567 self.lastij = i
1568 yield i
Tim Peters9a8c8e22001-07-13 09:12:12 +00001569 add_to_successors(i)
unknown31569562001-07-04 22:11:22 +00001570
1571 # Generate the last move.
1572 def last():
1573 assert self.final in succs[self.lastij]
1574 yield self.final
1575
Tim Peters9a8c8e22001-07-13 09:12:12 +00001576 if m*n < 4:
1577 self.squaregenerators = [first]
unknown31569562001-07-04 22:11:22 +00001578 else:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001579 self.squaregenerators = [first, second] + \
1580 [hard and advance_hard or advance] * (m*n - 3) + \
unknown31569562001-07-04 22:11:22 +00001581 [last]
1582
Tim Peters9a8c8e22001-07-13 09:12:12 +00001583 def coords2index(self, i, j):
1584 assert 0 <= i < self.m
1585 assert 0 <= j < self.n
1586 return i * self.n + j
1587
1588 def index2coords(self, index):
1589 assert 0 <= index < self.m * self.n
1590 return divmod(index, self.n)
1591
1592 def _init_board(self):
1593 succs = self.succs
1594 del succs[:]
1595 m, n = self.m, self.n
1596 c2i = self.coords2index
1597
1598 offsets = [( 1, 2), ( 2, 1), ( 2, -1), ( 1, -2),
1599 (-1, -2), (-2, -1), (-2, 1), (-1, 2)]
1600 rangen = range(n)
1601 for i in range(m):
1602 for j in rangen:
1603 s = [c2i(i+io, j+jo) for io, jo in offsets
1604 if 0 <= i+io < m and
1605 0 <= j+jo < n]
1606 succs.append(s)
1607
unknown31569562001-07-04 22:11:22 +00001608 # Generate solutions.
1609 def solve(self):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001610 self._init_board()
1611 for x in conjoin(self.squaregenerators):
unknown31569562001-07-04 22:11:22 +00001612 yield x
1613
1614 def printsolution(self, x):
Tim Peters9a8c8e22001-07-13 09:12:12 +00001615 m, n = self.m, self.n
1616 assert len(x) == m*n
1617 w = len(str(m*n))
unknown31569562001-07-04 22:11:22 +00001618 format = "%" + str(w) + "d"
1619
Tim Peters9a8c8e22001-07-13 09:12:12 +00001620 squares = [[None] * n for i in range(m)]
unknown31569562001-07-04 22:11:22 +00001621 k = 1
1622 for i in x:
Tim Peters9a8c8e22001-07-13 09:12:12 +00001623 i1, j1 = self.index2coords(i)
unknown31569562001-07-04 22:11:22 +00001624 squares[i1][j1] = format % k
1625 k += 1
1626
1627 sep = "+" + ("-" * w + "+") * n
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001628 print(sep)
Tim Peters9a8c8e22001-07-13 09:12:12 +00001629 for i in range(m):
unknown31569562001-07-04 22:11:22 +00001630 row = squares[i]
Guido van Rossumbe19ed72007-02-09 05:37:30 +00001631 print("|" + "|".join(row) + "|")
1632 print(sep)
unknown31569562001-07-04 22:11:22 +00001633
Tim Petersbe4f0a72001-06-29 02:41:16 +00001634conjoin_tests = """
1635
1636Generate the 3-bit binary numbers in order. This illustrates dumbest-
1637possible use of conjoin, just to generate the full cross-product.
1638
unknown31569562001-07-04 22:11:22 +00001639>>> for c in conjoin([lambda: iter((0, 1))] * 3):
Guido van Rossum7131f842007-02-09 20:13:25 +00001640... print(c)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001641[0, 0, 0]
1642[0, 0, 1]
1643[0, 1, 0]
1644[0, 1, 1]
1645[1, 0, 0]
1646[1, 0, 1]
1647[1, 1, 0]
1648[1, 1, 1]
1649
Tim Petersc468fd22001-06-30 07:29:44 +00001650For efficiency in typical backtracking apps, conjoin() yields the same list
1651object each time. So if you want to save away a full account of its
1652generated sequence, you need to copy its results.
1653
1654>>> def gencopy(iterator):
1655... for x in iterator:
1656... yield x[:]
1657
1658>>> for n in range(10):
unknown31569562001-07-04 22:11:22 +00001659... all = list(gencopy(conjoin([lambda: iter((0, 1))] * n)))
Guido van Rossum7131f842007-02-09 20:13:25 +00001660... print(n, len(all), all[0] == [0] * n, all[-1] == [1] * n)
Guido van Rossum77f6a652002-04-03 22:41:51 +000016610 1 True True
16621 2 True True
16632 4 True True
16643 8 True True
16654 16 True True
16665 32 True True
16676 64 True True
16687 128 True True
16698 256 True True
16709 512 True True
Tim Petersc468fd22001-06-30 07:29:44 +00001671
Tim Petersbe4f0a72001-06-29 02:41:16 +00001672And run an 8-queens solver.
1673
1674>>> q = Queens(8)
1675>>> LIMIT = 2
1676>>> count = 0
1677>>> for row2col in q.solve():
1678... count += 1
1679... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001680... print("Solution", count)
Tim Petersbe4f0a72001-06-29 02:41:16 +00001681... q.printsolution(row2col)
1682Solution 1
1683+-+-+-+-+-+-+-+-+
1684|Q| | | | | | | |
1685+-+-+-+-+-+-+-+-+
1686| | | | |Q| | | |
1687+-+-+-+-+-+-+-+-+
1688| | | | | | | |Q|
1689+-+-+-+-+-+-+-+-+
1690| | | | | |Q| | |
1691+-+-+-+-+-+-+-+-+
1692| | |Q| | | | | |
1693+-+-+-+-+-+-+-+-+
1694| | | | | | |Q| |
1695+-+-+-+-+-+-+-+-+
1696| |Q| | | | | | |
1697+-+-+-+-+-+-+-+-+
1698| | | |Q| | | | |
1699+-+-+-+-+-+-+-+-+
1700Solution 2
1701+-+-+-+-+-+-+-+-+
1702|Q| | | | | | | |
1703+-+-+-+-+-+-+-+-+
1704| | | | | |Q| | |
1705+-+-+-+-+-+-+-+-+
1706| | | | | | | |Q|
1707+-+-+-+-+-+-+-+-+
1708| | |Q| | | | | |
1709+-+-+-+-+-+-+-+-+
1710| | | | | | |Q| |
1711+-+-+-+-+-+-+-+-+
1712| | | |Q| | | | |
1713+-+-+-+-+-+-+-+-+
1714| |Q| | | | | | |
1715+-+-+-+-+-+-+-+-+
1716| | | | |Q| | | |
1717+-+-+-+-+-+-+-+-+
1718
Guido van Rossum7131f842007-02-09 20:13:25 +00001719>>> print(count, "solutions in all.")
Tim Petersbe4f0a72001-06-29 02:41:16 +0000172092 solutions in all.
unknown31569562001-07-04 22:11:22 +00001721
1722And run a Knight's Tour on a 10x10 board. Note that there are about
172320,000 solutions even on a 6x6 board, so don't dare run this to exhaustion.
1724
Tim Peters9a8c8e22001-07-13 09:12:12 +00001725>>> k = Knights(10, 10)
unknown31569562001-07-04 22:11:22 +00001726>>> LIMIT = 2
1727>>> count = 0
1728>>> for x in k.solve():
1729... count += 1
1730... if count <= LIMIT:
Guido van Rossum7131f842007-02-09 20:13:25 +00001731... print("Solution", count)
unknown31569562001-07-04 22:11:22 +00001732... k.printsolution(x)
1733... else:
1734... break
1735Solution 1
1736+---+---+---+---+---+---+---+---+---+---+
1737| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1738+---+---+---+---+---+---+---+---+---+---+
1739| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1740+---+---+---+---+---+---+---+---+---+---+
1741| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1742+---+---+---+---+---+---+---+---+---+---+
1743| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1744+---+---+---+---+---+---+---+---+---+---+
1745| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1746+---+---+---+---+---+---+---+---+---+---+
1747| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1748+---+---+---+---+---+---+---+---+---+---+
1749| 87| 98| 91| 80| 77| 84| 53| 46| 65| 44|
1750+---+---+---+---+---+---+---+---+---+---+
1751| 90| 23| 88| 95| 70| 79| 68| 83| 14| 17|
1752+---+---+---+---+---+---+---+---+---+---+
1753| 97| 92| 21| 78| 81| 94| 19| 16| 45| 66|
1754+---+---+---+---+---+---+---+---+---+---+
1755| 22| 89| 96| 93| 20| 69| 82| 67| 18| 15|
1756+---+---+---+---+---+---+---+---+---+---+
1757Solution 2
1758+---+---+---+---+---+---+---+---+---+---+
1759| 1| 58| 27| 34| 3| 40| 29| 10| 5| 8|
1760+---+---+---+---+---+---+---+---+---+---+
1761| 26| 35| 2| 57| 28| 33| 4| 7| 30| 11|
1762+---+---+---+---+---+---+---+---+---+---+
1763| 59|100| 73| 36| 41| 56| 39| 32| 9| 6|
1764+---+---+---+---+---+---+---+---+---+---+
1765| 74| 25| 60| 55| 72| 37| 42| 49| 12| 31|
1766+---+---+---+---+---+---+---+---+---+---+
1767| 61| 86| 99| 76| 63| 52| 47| 38| 43| 50|
1768+---+---+---+---+---+---+---+---+---+---+
1769| 24| 75| 62| 85| 54| 71| 64| 51| 48| 13|
1770+---+---+---+---+---+---+---+---+---+---+
1771| 87| 98| 89| 80| 77| 84| 53| 46| 65| 44|
1772+---+---+---+---+---+---+---+---+---+---+
1773| 90| 23| 92| 95| 70| 79| 68| 83| 14| 17|
1774+---+---+---+---+---+---+---+---+---+---+
1775| 97| 88| 21| 78| 81| 94| 19| 16| 45| 66|
1776+---+---+---+---+---+---+---+---+---+---+
1777| 22| 91| 96| 93| 20| 69| 82| 67| 18| 15|
1778+---+---+---+---+---+---+---+---+---+---+
Tim Petersbe4f0a72001-06-29 02:41:16 +00001779"""
1780
Fred Drake56d12662002-08-09 18:37:10 +00001781weakref_tests = """\
1782Generators are weakly referencable:
1783
1784>>> import weakref
1785>>> def gen():
1786... yield 'foo!'
1787...
1788>>> wr = weakref.ref(gen)
1789>>> wr() is gen
1790True
1791>>> p = weakref.proxy(gen)
1792
1793Generator-iterators are weakly referencable as well:
1794
1795>>> gi = gen()
1796>>> wr = weakref.ref(gi)
1797>>> wr() is gi
1798True
1799>>> p = weakref.proxy(gi)
1800>>> list(p)
1801['foo!']
1802
1803"""
1804
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001805coroutine_tests = """\
1806Sending a value into a started generator:
1807
1808>>> def f():
Guido van Rossum7131f842007-02-09 20:13:25 +00001809... print((yield 1))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001810... yield 2
1811>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001812>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +000018131
1814>>> g.send(42)
181542
18162
1817
1818Sending a value into a new generator produces a TypeError:
1819
1820>>> f().send("foo")
1821Traceback (most recent call last):
1822...
1823TypeError: can't send non-None value to a just-started generator
1824
1825
1826Yield by itself yields None:
1827
1828>>> def f(): yield
1829>>> list(f())
1830[None]
1831
1832
Serhiy Storchaka73a7e9b2017-12-01 06:54:17 +02001833Yield is allowed only in the outermost iterable in generator expression:
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001834
1835>>> def f(): list(i for i in [(yield 26)])
1836>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07001837<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001838
1839
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001840A yield expression with augmented assignment.
1841
1842>>> def coroutine(seq):
1843... count = 0
1844... while count < 200:
1845... count += yield
1846... seq.append(count)
1847>>> seq = []
1848>>> c = coroutine(seq)
Georg Brandla18af4e2007-04-21 15:47:16 +00001849>>> next(c)
Guido van Rossum7131f842007-02-09 20:13:25 +00001850>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001851[]
1852>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001853>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001854[10]
1855>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001856>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001857[10, 20]
1858>>> c.send(10)
Guido van Rossum7131f842007-02-09 20:13:25 +00001859>>> print(seq)
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001860[10, 20, 30]
1861
1862
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001863Check some syntax errors for yield expressions:
1864
1865>>> f=lambda: (yield 1),(yield 2)
1866Traceback (most recent call last):
1867 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001868SyntaxError: 'yield' outside function
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001869
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001870>>> def f(): x = yield = y
1871Traceback (most recent call last):
1872 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001873SyntaxError: assignment to yield expression not possible
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001874
1875>>> def f(): (yield bar) = y
1876Traceback (most recent call last):
1877 ...
Guido van Rossum33d26892007-08-05 15:29:28 +00001878SyntaxError: can't assign to yield expression
Thomas Wouters0e3f5912006-08-11 14:57:12 +00001879
1880>>> def f(): (yield bar) += y
1881Traceback (most recent call last):
1882 ...
Benjamin Peterson87c8d872009-06-11 22:54:11 +00001883SyntaxError: can't assign to yield expression
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001884
1885
1886Now check some throw() conditions:
1887
1888>>> def f():
1889... while True:
1890... try:
Guido van Rossum7131f842007-02-09 20:13:25 +00001891... print((yield))
Guido van Rossumb940e112007-01-10 16:19:56 +00001892... except ValueError as v:
Guido van Rossumc420b2f2007-02-09 22:09:01 +00001893... print("caught ValueError (%s)" % (v))
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001894>>> import sys
1895>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00001896>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001897
1898>>> g.throw(ValueError) # type only
1899caught ValueError ()
1900
1901>>> g.throw(ValueError("xyz")) # value only
1902caught ValueError (xyz)
1903
1904>>> g.throw(ValueError, ValueError(1)) # value+matching type
1905caught ValueError (1)
1906
1907>>> g.throw(ValueError, TypeError(1)) # mismatched type, rewrapped
1908caught ValueError (1)
1909
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00001910>>> g.throw(ValueError, ValueError(1), None) # explicit None traceback
1911caught ValueError (1)
1912
Tim Peterse9fe7e02005-08-07 03:04:58 +00001913>>> g.throw(ValueError(1), "foo") # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001914Traceback (most recent call last):
1915 ...
1916TypeError: instance exception may not have a separate value
1917
Tim Peterse9fe7e02005-08-07 03:04:58 +00001918>>> g.throw(ValueError, "foo", 23) # bad args
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001919Traceback (most recent call last):
1920 ...
1921TypeError: throw() third argument must be a traceback object
1922
Guido van Rossumbf12cdb2006-08-17 20:24:18 +00001923>>> g.throw("abc")
1924Traceback (most recent call last):
1925 ...
1926TypeError: exceptions must be classes or instances deriving from BaseException, not str
1927
1928>>> g.throw(0)
1929Traceback (most recent call last):
1930 ...
1931TypeError: exceptions must be classes or instances deriving from BaseException, not int
1932
1933>>> g.throw(list)
1934Traceback (most recent call last):
1935 ...
1936TypeError: exceptions must be classes or instances deriving from BaseException, not type
1937
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001938>>> def throw(g,exc):
1939... try:
1940... raise exc
1941... except:
1942... g.throw(*sys.exc_info())
Tim Peterse9fe7e02005-08-07 03:04:58 +00001943>>> throw(g,ValueError) # do it with traceback included
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001944caught ValueError ()
1945
1946>>> g.send(1)
19471
1948
Tim Peterse9fe7e02005-08-07 03:04:58 +00001949>>> throw(g,TypeError) # terminate the generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001950Traceback (most recent call last):
1951 ...
1952TypeError
1953
Guido van Rossum7131f842007-02-09 20:13:25 +00001954>>> print(g.gi_frame)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001955None
1956
1957>>> g.send(2)
1958Traceback (most recent call last):
1959 ...
1960StopIteration
1961
Tim Peterse9fe7e02005-08-07 03:04:58 +00001962>>> g.throw(ValueError,6) # throw on closed generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001963Traceback (most recent call last):
1964 ...
1965ValueError: 6
1966
Tim Peterse9fe7e02005-08-07 03:04:58 +00001967>>> f().throw(ValueError,7) # throw on just-opened generator
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001968Traceback (most recent call last):
1969 ...
1970ValueError: 7
1971
Antoine Pitrou551ba202011-10-18 16:40:50 +02001972Plain "raise" inside a generator should preserve the traceback (#13188).
1973The traceback should have 3 levels:
1974- g.throw()
1975- f()
1976- 1/0
1977
1978>>> def f():
1979... try:
1980... yield
1981... except:
1982... raise
1983>>> g = f()
1984>>> try:
1985... 1/0
1986... except ZeroDivisionError as v:
1987... try:
1988... g.throw(v)
1989... except Exception as w:
1990... tb = w.__traceback__
1991>>> levels = 0
1992>>> while tb:
1993... levels += 1
1994... tb = tb.tb_next
1995>>> levels
19963
1997
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00001998Now let's try closing a generator:
1999
2000>>> def f():
2001... try: yield
2002... except GeneratorExit:
Guido van Rossum7131f842007-02-09 20:13:25 +00002003... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002004
2005>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002006>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002007>>> g.close()
2008exiting
2009>>> g.close() # should be no-op now
2010
2011>>> f().close() # close on just-opened generator should be fine
2012
Tim Peterse9fe7e02005-08-07 03:04:58 +00002013>>> def f(): yield # an even simpler generator
2014>>> f().close() # close before opening
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002015>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002016>>> next(g)
Tim Peterse9fe7e02005-08-07 03:04:58 +00002017>>> g.close() # close normally
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002018
2019And finalization:
2020
2021>>> def f():
2022... try: yield
2023... finally:
Guido van Rossum7131f842007-02-09 20:13:25 +00002024... print("exiting")
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002025
2026>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002027>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002028>>> del g
2029exiting
2030
2031
Christian Heimescbf3b5c2007-12-03 21:02:03 +00002032GeneratorExit is not caught by except Exception:
2033
2034>>> def f():
2035... try: yield
2036... except Exception:
2037... print('except')
2038... finally:
2039... print('finally')
2040
2041>>> g = f()
2042>>> next(g)
2043>>> del g
2044finally
2045
2046
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002047Now let's try some ill-behaved generators:
2048
2049>>> def f():
2050... try: yield
2051... except GeneratorExit:
2052... yield "foo!"
2053>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002054>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002055>>> g.close()
2056Traceback (most recent call last):
2057 ...
2058RuntimeError: generator ignored GeneratorExit
2059>>> g.close()
2060
2061
2062Our ill-behaved code should be invoked during GC:
2063
Guido van Rossum34d19282007-08-09 01:03:29 +00002064>>> import sys, io
2065>>> old, sys.stderr = sys.stderr, io.StringIO()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002066>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002067>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002068>>> del g
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002069>>> "RuntimeError: generator ignored GeneratorExit" in sys.stderr.getvalue()
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002070True
2071>>> sys.stderr = old
2072
2073
2074And errors thrown during closing should propagate:
2075
2076>>> def f():
2077... try: yield
2078... except GeneratorExit:
2079... raise TypeError("fie!")
2080>>> g = f()
Georg Brandla18af4e2007-04-21 15:47:16 +00002081>>> next(g)
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002082>>> g.close()
2083Traceback (most recent call last):
2084 ...
2085TypeError: fie!
2086
2087
2088Ensure that various yield expression constructs make their
2089enclosing function a generator:
2090
2091>>> def f(): x += yield
2092>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07002093<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002094
2095>>> def f(): x = yield
2096>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07002097<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002098
2099>>> def f(): lambda x=(yield): 1
2100>>> type(f())
Benjamin Petersonab078e92016-07-13 21:13:29 -07002101<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002102
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002103>>> def f(d): d[(yield "a")] = d[(yield "b")] = 27
2104>>> data = [1,2]
2105>>> g = f(data)
2106>>> type(g)
Benjamin Petersonab078e92016-07-13 21:13:29 -07002107<class 'generator'>
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002108>>> g.send(None)
2109'a'
2110>>> data
2111[1, 2]
2112>>> g.send(0)
2113'b'
2114>>> data
2115[27, 2]
2116>>> try: g.send(1)
2117... except StopIteration: pass
2118>>> data
2119[27, 27]
2120
2121"""
2122
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002123refleaks_tests = """
2124Prior to adding cycle-GC support to itertools.tee, this code would leak
2125references. We add it to the standard suite so the routine refleak-tests
2126would trigger if it starts being uncleanable again.
2127
2128>>> import itertools
2129>>> def leak():
2130... class gen:
2131... def __iter__(self):
2132... return self
Georg Brandla18af4e2007-04-21 15:47:16 +00002133... def __next__(self):
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002134... return self.item
2135... g = gen()
2136... head, tail = itertools.tee(g)
2137... g.item = head
2138... return head
2139>>> it = leak()
2140
2141Make sure to also test the involvement of the tee-internal teedataobject,
2142which stores returned items.
2143
Georg Brandla18af4e2007-04-21 15:47:16 +00002144>>> item = next(it)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002145
2146
2147
2148This test leaked at one point due to generator finalization/destruction.
2149It was copied from Lib/test/leakers/test_generator_cycle.py before the file
2150was removed.
2151
2152>>> def leak():
2153... def gen():
2154... while True:
2155... yield g
2156... g = gen()
2157
2158>>> leak()
2159
2160
2161
2162This test isn't really generator related, but rather exception-in-cleanup
2163related. The coroutine tests (above) just happen to cause an exception in
2164the generator's __del__ (tp_del) method. We can also test for this
2165explicitly, without generators. We do have to redirect stderr to avoid
2166printing warnings and to doublecheck that we actually tested what we wanted
2167to test.
2168
Guido van Rossum34d19282007-08-09 01:03:29 +00002169>>> import sys, io
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002170>>> old = sys.stderr
2171>>> try:
Guido van Rossum34d19282007-08-09 01:03:29 +00002172... sys.stderr = io.StringIO()
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002173... class Leaker:
2174... def __del__(self):
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002175... def invoke(message):
2176... raise RuntimeError(message)
2177... invoke("test")
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002178...
2179... l = Leaker()
2180... del l
2181... err = sys.stderr.getvalue().strip()
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002182... "Exception ignored in" in err
2183... "RuntimeError: test" in err
2184... "Traceback" in err
2185... "in invoke" in err
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002186... finally:
2187... sys.stderr = old
2188True
2189True
Andrew Svetlov76bcff22012-11-03 15:56:05 +02002190True
2191True
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002192
2193
2194These refleak tests should perhaps be in a testfile of their own,
2195test_generators just happened to be the test that drew these out.
2196
2197"""
2198
Tim Petersf6ed0742001-06-27 07:17:57 +00002199__test__ = {"tut": tutorial_tests,
2200 "pep": pep_tests,
2201 "email": email_tests,
2202 "fun": fun_tests,
Tim Petersbe4f0a72001-06-29 02:41:16 +00002203 "syntax": syntax_tests,
Fred Drake56d12662002-08-09 18:37:10 +00002204 "conjoin": conjoin_tests,
2205 "weakref": weakref_tests,
Phillip J. Eby0d6615f2005-08-02 00:46:46 +00002206 "coroutine": coroutine_tests,
Thomas Wouters49fd7fa2006-04-21 10:40:58 +00002207 "refleaks": refleaks_tests,
Fred Drake56d12662002-08-09 18:37:10 +00002208 }
Tim Peters1def3512001-06-23 20:27:04 +00002209
2210# Magic test name that regrtest.py invokes *after* importing this module.
2211# This worms around a bootstrap problem.
2212# Note that doctest and regrtest both look in sys.argv for a "-v" argument,
2213# so this works as expected in both ways of running regrtest.
Tim Petersa0a62222001-09-09 06:12:01 +00002214def test_main(verbose=None):
Benjamin Petersonee8712c2008-05-20 21:35:26 +00002215 from test import support, test_generators
Antoine Pitrou796564c2013-07-30 19:59:21 +02002216 support.run_unittest(__name__)
Benjamin Petersonab078e92016-07-13 21:13:29 -07002217 support.run_doctest(test_generators, verbose)
Tim Peters1def3512001-06-23 20:27:04 +00002218
2219# This part isn't needed for regrtest, but for running the test directly.
2220if __name__ == "__main__":
Tim Petersa0a62222001-09-09 06:12:01 +00002221 test_main(1)