fix: nested context managers shouldn't cause a phantom missing branch… · nedbat/coveragepy@378c321 (original) (raw)
3 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -23,10 +23,15 @@ upgrading your version of coverage.py. | ||
23 | 23 | Unreleased |
24 | 24 | ---------- |
25 | 25 | |
26 | +- Fix: nested context managers could incorrectly be analyzed to flag a missing | |
27 | + branch on the last context manager, as described in `issue 1876`_. This is | |
28 | + now fixed. | |
29 | + | |
26 | 30 | - Fix: the missing branch message about not exiting a module had an extra |
27 | 31 | "didn't," as described in `issue 1873`_. This is now fixed. |
28 | 32 | |
29 | 33 | .. _issue 1873: https://github.com/nedbat/coveragepy/issues/1873 |
34 | +.. _issue 1876: https://github.com/nedbat/coveragepy/issues/1876 | |
30 | 35 | |
31 | 36 | |
32 | 37 | .. start-releases |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -315,12 +315,18 @@ def fix_with_jumps(self, arcs: Iterable[TArc]) -> set[TArc]: | ||
315 | 315 | to_add = set() |
316 | 316 | for arc in arcs: |
317 | 317 | if arc in self._with_jump_fixers: |
318 | +start = arc[0] | |
319 | +to_remove.add(arc) | |
318 | 320 | start_next, prev_next = self._with_jump_fixers[arc] |
319 | -if start_next in arcs: | |
320 | -to_add.add(prev_next) | |
321 | -to_remove.add(arc) | |
321 | +while start_next in self._with_jump_fixers: | |
322 | 322 | to_remove.add(start_next) |
323 | -return (set(arcs) | to_add) - to_remove | |
323 | +start_next, prev_next = self._with_jump_fixers[start_next] | |
324 | +to_remove.add(prev_next) | |
325 | +to_add.add((start, prev_next[1])) | |
326 | +to_remove.add(arc) | |
327 | +to_remove.add(start_next) | |
328 | +arcs = (set(arcs) | to_add) - to_remove | |
329 | +return arcs | |
324 | 330 | |
325 | 331 | @functools.lru_cache |
326 | 332 | def exit_counts(self) -> dict[TLineNo, int]: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -151,6 +151,24 @@ def bar(self): | ||
151 | 151 | assert expected_arcs == parser.arcs() |
152 | 152 | assert expected_exits == parser.exit_counts() |
153 | 153 | |
154 | +def test_nested_context_managers(self) -> None: | |
155 | +# https://github.com/nedbat/coveragepy/issues/1876 | |
156 | +parser = self.parse_text("""\ | |
157 | + a = 1 | |
158 | + with suppress(ValueError): | |
159 | + with suppress(ValueError): | |
160 | + x = 4 | |
161 | + with suppress(ValueError): | |
162 | + x = 6 | |
163 | + with suppress(ValueError): | |
164 | + x = 8 | |
165 | + a = 9 | |
166 | + """) | |
167 | + | |
168 | +one_nine = set(range(1, 10)) | |
169 | +assert parser.statements == one_nine | |
170 | +assert parser.exit_counts() == dict.fromkeys(one_nine, 1) | |
171 | + | |
154 | 172 | def test_module_docstrings(self) -> None: |
155 | 173 | parser = self.parse_text("""\ |
156 | 174 | '''The docstring on line 1''' |