File tree Expand file tree Collapse file tree 4 files changed +54
-5
lines changed Expand file tree Collapse file tree 4 files changed +54
-5
lines changed Original file line number Diff line number Diff line change @@ -23,7 +23,10 @@ upgrading your version of coverage.py.
2323 Unreleased
2424----------
2525
26- Nothing yet.
26+ - fix: multi-line ``with `` statements could cause contained branches to be
27+ incorrectly marked as missing (`issue 1880 `_). This is now fixed.
28+
29+ .. _issue 1880 : https://github.com/nedbat/coveragepy/issues/1880
2730
2831
2932.. start-releases
Original file line number Diff line number Diff line change @@ -81,6 +81,10 @@ class PYBEHAVIOR:
8181 # When leaving a with-block, do we visit the with-line again for the exit?
8282 exit_through_with = (PYVERSION >= (3 , 10 , 0 , "beta" ))
8383
84+ # When leaving a with-block, do we visit the with-line exactly,
85+ # or the inner-most context manager?
86+ exit_with_through_ctxmgr = (PYVERSION >= (3 , 12 ))
87+
8488 # Match-case construct.
8589 match_case = (PYVERSION >= (3 , 10 ))
8690
Original file line number Diff line number Diff line change @@ -1261,12 +1261,19 @@ def _handle__While(self, node: ast.While) -> set[ArcStart]:
12611261 return exits
12621262
12631263 def _handle__With (self , node : ast .With ) -> set [ArcStart ]:
1264- start = self .line_for_node (node )
1264+ if env .PYBEHAVIOR .exit_with_through_ctxmgr :
1265+ starts = [self .line_for_node (item .context_expr ) for item in node .items ]
1266+ else :
1267+ starts = [self .line_for_node (node )]
12651268 if env .PYBEHAVIOR .exit_through_with :
1266- self .current_with_starts .add (start )
1267- self .all_with_starts .add (start )
1268- exits = self .process_body (node .body , from_start = ArcStart (start ))
1269+ for start in starts :
1270+ self .current_with_starts .add (start )
1271+ self .all_with_starts .add (start )
1272+
1273+ exits = self .process_body (node .body , from_start = ArcStart (starts [- 1 ]))
1274+
12691275 if env .PYBEHAVIOR .exit_through_with :
1276+ start = starts [- 1 ]
12701277 self .current_with_starts .remove (start )
12711278 with_exit = {ArcStart (start )}
12721279 if exits :
Original file line number Diff line number Diff line change @@ -347,6 +347,41 @@ def test_with_with_lambda(self) -> None:
347347 branchz_missing = "" ,
348348 )
349349
350+ def test_multiline_with (self ) -> None :
351+ # https://github.com/nedbat/coveragepy/issues/1880
352+ self .check_coverage ("""\
353+ import contextlib, itertools
354+ nums = itertools.count()
355+ with (
356+ contextlib.nullcontext() as x,
357+ ):
358+ while next(nums) < 6:
359+ y = 7
360+ z = 8
361+ """ ,
362+ branchz = "67 68" ,
363+ branchz_missing = "" ,
364+ )
365+
366+
367+ def test_multi_multiline_with (self ) -> None :
368+ # https://github.com/nedbat/coveragepy/issues/1880
369+ self .check_coverage ("""\
370+ import contextlib, itertools
371+ nums = itertools.count()
372+ with (
373+ contextlib.nullcontext() as x,
374+ contextlib.nullcontext() as y,
375+ contextlib.nullcontext() as z,
376+ ):
377+ while next(nums) < 8:
378+ y = 9
379+ z = 10
380+ """ ,
381+ branchz = "89 8A" ,
382+ branchz_missing = "" ,
383+ )
384+
350385
351386class LoopArcTest (CoverageTest ):
352387 """Arc-measuring tests involving loops."""
You can’t perform that action at this time.
0 commit comments