@@ -748,6 +748,39 @@ def test_exit_suppress(self):
748
748
stack .push (lambda * exc : True )
749
749
1 / 0
750
750
751
+ def test_exit_exception_traceback (self ):
752
+ # This test captures the current behavior of ExitStack so that we know
753
+ # if we ever unintendedly change it. It is not a statement of what the
754
+ # desired behavior is (for instance, we may want to remove some of the
755
+ # internal contextlib frames).
756
+
757
+ def raise_exc (exc ):
758
+ raise exc
759
+
760
+ try :
761
+ with self .exit_stack () as stack :
762
+ stack .callback (raise_exc , ValueError )
763
+ 1 / 0
764
+ except ValueError as e :
765
+ exc = e
766
+
767
+ self .assertIsInstance (exc , ValueError )
768
+ ve_frames = traceback .extract_tb (exc .__traceback__ )
769
+ self .assertEqual (len (ve_frames ), 5 )
770
+ self .assertEqual (
771
+ [(f .name , f .line ) for f in ve_frames ],
772
+ [('test_exit_exception_traceback' , 'with self.exit_stack() as stack:' ),
773
+ ('__exit__' , 'raise exc_details[1]' ),
774
+ ('__exit__' , 'if cb(*exc_details):' ),
775
+ ('_exit_wrapper' , 'callback(*args, **kwds)' ),
776
+ ('raise_exc' , 'raise exc' )])
777
+
778
+ self .assertIsInstance (exc .__context__ , ZeroDivisionError )
779
+ zde_frames = traceback .extract_tb (exc .__context__ .__traceback__ )
780
+ self .assertEqual (len (zde_frames ), 1 )
781
+ self .assertEqual ([(f .name , f .line ) for f in zde_frames ],
782
+ [('test_exit_exception_traceback' , '1/0' )])
783
+
751
784
def test_exit_exception_chaining_reference (self ):
752
785
# Sanity check to make sure that ExitStack chaining matches
753
786
# actual nested with statements
0 commit comments