File tree Expand file tree Collapse file tree 4 files changed +52
-3
lines changed Expand file tree Collapse file tree 4 files changed +52
-3
lines changed Original file line number Diff line number Diff line change @@ -341,6 +341,7 @@ Olga Matoula
341341Oliver Bestwalter
342342Omar Kohl
343343Omer Hadari
344+ Omri Golan
344345Ondřej Súkup
345346Oscar Benjamin
346347Parth Patel
Original file line number Diff line number Diff line change 1+ Restore pre-ExceptionGroup semantics for CallInfo.from_call: re-raise exceptions in reraise even when they appear inside a single-level ExceptionGroup. Nested groups remain out of scope of this fix and behave as before.
Original file line number Diff line number Diff line change @@ -342,10 +342,26 @@ def from_call(
342342 instant = timing .Instant ()
343343 try :
344344 result : TResult | None = func ()
345- except BaseException :
345+ except BaseException as caught :
346346 excinfo = ExceptionInfo .from_current ()
347- if reraise is not None and isinstance (excinfo .value , reraise ):
348- raise
347+ val = excinfo .value
348+
349+ if reraise is not None :
350+ reraise_types = (
351+ (reraise ,) if not isinstance (reraise , tuple ) else reraise
352+ )
353+
354+ # EG-aware path (only direct children; no nesting)
355+ if isinstance (val , BaseExceptionGroup ):
356+ exception_group = cast (BaseExceptionGroup , val )
357+ for child in exception_group .exceptions :
358+ if isinstance (child , reraise_types ):
359+ # B904: chain to the original exception we caught
360+ raise child from caught
361+
362+ if isinstance (val , reraise_types ): # non-group or no match
363+ raise
364+
349365 result = None
350366 duration = instant .elapsed ()
351367 return cls (
Original file line number Diff line number Diff line change @@ -1264,3 +1264,34 @@ def test_bar(): pass
12641264 )
12651265 result = pytester .runpytest ("--stepwise" )
12661266 result .assert_outcomes (failed = 1 , errors = 1 )
1267+
1268+
1269+ def test_exit_in_teardown_exception_group_stops_session (pytester : Pytester ) -> None :
1270+ pytester .makepyfile (
1271+ test_it = """
1272+ import pytest
1273+ @pytest.fixture
1274+ def failing_teardown():
1275+ yield
1276+ raise IOError("Exception in teardown")
1277+ @pytest.fixture
1278+ def exit_session():
1279+ yield
1280+ pytest.exit("Forced exit")
1281+ def test_1(): return
1282+ @pytest.mark.usefixtures(
1283+ "failing_teardown",
1284+ "exit_session"
1285+ )
1286+ def test_failure(): return
1287+ def test_3(): return
1288+ """
1289+ )
1290+ result = pytester .runpytest ()
1291+ result .assert_outcomes (passed = 2 )
1292+ result .stdout .fnmatch_lines (
1293+ [
1294+ "!* _pytest.outcomes.Exit: Forced exit !*" ,
1295+ "=* 2 passed in * =*" ,
1296+ ]
1297+ )
You can’t perform that action at this time.
0 commit comments