@@ -661,6 +661,52 @@ def g():
661661 pass
662662 self .assertEqual (sys .exc_info (), (None , None , None ))
663663
664+ def test_generator_leaking3 (self ):
665+ # See issue #23353. When gen.throw() is called, the caller's
666+ # exception state should be save and restored.
667+ def g ():
668+ try :
669+ yield
670+ except ZeroDivisionError :
671+ yield sys .exc_info ()[1 ]
672+ it = g ()
673+ next (it )
674+ try :
675+ 1 / 0
676+ except ZeroDivisionError as e :
677+ self .assertIs (sys .exc_info ()[1 ], e )
678+ gen_exc = it .throw (e )
679+ self .assertIs (sys .exc_info ()[1 ], e )
680+ self .assertIs (gen_exc , e )
681+ self .assertEqual (sys .exc_info (), (None , None , None ))
682+
683+ def test_generator_leaking4 (self ):
684+ # See issue #23353. When an exception is raised by a generator,
685+ # the caller's exception state should still be restored.
686+ def g ():
687+ try :
688+ 1 / 0
689+ except ZeroDivisionError :
690+ yield sys .exc_info ()[0 ]
691+ raise
692+ it = g ()
693+ try :
694+ raise TypeError
695+ except TypeError :
696+ # The caller's exception state (TypeError) is temporarily
697+ # saved in the generator.
698+ tp = next (it )
699+ self .assertIs (tp , ZeroDivisionError )
700+ try :
701+ next (it )
702+ # We can't check it immediately, but while next() returns
703+ # with an exception, it shouldn't have restored the old
704+ # exception state (TypeError).
705+ except ZeroDivisionError as e :
706+ self .assertIs (sys .exc_info ()[1 ], e )
707+ # We used to find TypeError here.
708+ self .assertEqual (sys .exc_info (), (None , None , None ))
709+
664710 def test_generator_doesnt_retain_old_exc (self ):
665711 def g ():
666712 self .assertIsInstance (sys .exc_info ()[1 ], RuntimeError )
0 commit comments