Skip to content

Commit 07b76b2

Browse files
committed
fix: some clause exclusions were broken #1713
1 parent 962429c commit 07b76b2

File tree

4 files changed

+63
-9
lines changed

4 files changed

+63
-9
lines changed

CHANGES.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,14 @@ development at the same time, such as 4.5.x and 5.0.
2020
Unreleased
2121
----------
2222

23+
- Fix: the change for multi-line signature exclusions in 7.3.3 broke other
24+
forms of nested clauses being excluded properly. This is now fixed, closing
25+
`issue 1713`_.
26+
2327
- Fix: in the HTML report, selecting code for copying won't select the line
2428
numbers also. Thanks, `Robert Harris <pull 1717_>`_.
2529

30+
.. _issue 1713: https://github.com/nedbat/coveragepy/issues/1713
2631
.. _pull 1717: https://github.com/nedbat/coveragepy/pull/1717
2732

2833

coverage/parser.py

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,10 @@ def _raw_parse(self) -> None:
158158
self.raw_classdefs.add(slineno)
159159
elif toktype == token.OP:
160160
if ttext == ":" and nesting == 0:
161-
should_exclude = (elineno in self.raw_excluded) or excluding_decorators
161+
should_exclude = (
162+
self.raw_excluded.intersection(range(first_line, elineno + 1))
163+
or excluding_decorators
164+
)
162165
if not excluding and should_exclude:
163166
# Start excluding a suite. We trigger off of the colon
164167
# token so that the #pragma comment will be recognized on
@@ -190,12 +193,6 @@ def _raw_parse(self) -> None:
190193
# so record a multi-line range.
191194
for l in range(first_line, elineno+1): # type: ignore[unreachable]
192195
self._multiline[l] = first_line
193-
# Check if multi-line was before a suite (trigger by the colon token).
194-
if nesting == 0 and prev_toktype == token.OP and prev_ttext == ":":
195-
statement_multilines = set(range(first_line, elineno + 1))
196-
if statement_multilines & set(self.raw_excluded):
197-
exclude_indent = indent
198-
excluding = True
199196
first_line = None
200197
first_on_line = True
201198

@@ -213,7 +210,6 @@ def _raw_parse(self) -> None:
213210
first_on_line = False
214211

215212
prev_toktype = toktype
216-
prev_ttext = ttext
217213

218214
# Find the starts of the executable statements.
219215
if not empty:

tests/coveragetest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def check_coverage(
193193
# Get the analysis results, and check that they are right.
194194
analysis = cov._analyze(mod)
195195
statements = sorted(analysis.statements)
196-
if lines is not None and len(lines) != 0:
196+
if lines:
197197
if isinstance(lines[0], int):
198198
# lines is just a list of numbers, it must match the statements
199199
# found in the code.

tests/test_coverage.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1740,6 +1740,59 @@ def my_func_2(super_long_input_argument_0=0, super_long_input_argument_1=1, supe
17401740
[], "5", excludes=['my_func']
17411741
)
17421742

1743+
def test_excluding_bug1713(self) -> None:
1744+
if env.PYVERSION >= (3, 10):
1745+
self.check_coverage("""\
1746+
print("1")
1747+
1748+
def hello_3(a): # pragma: no cover
1749+
match a:
1750+
case ("5"
1751+
| "6"):
1752+
print("7")
1753+
case "8":
1754+
print("9")
1755+
1756+
print("11")
1757+
""",
1758+
[1, 11],
1759+
)
1760+
self.check_coverage("""\
1761+
print("1")
1762+
1763+
def hello_3(a): # no thanks
1764+
if ("4" or
1765+
"5"):
1766+
print("6")
1767+
else:
1768+
print("8")
1769+
1770+
print("10")
1771+
""",
1772+
[1, 10], "", excludes=["no thanks"],
1773+
)
1774+
self.check_coverage("""\
1775+
print(1)
1776+
1777+
def func(a, b):
1778+
if a == 4: # pragma: no cover
1779+
func5()
1780+
if b:
1781+
print(7)
1782+
func8()
1783+
1784+
print(10)
1785+
""",
1786+
[1, 3, 10]
1787+
)
1788+
self.check_coverage("""\
1789+
class Foo: # pragma: no cover
1790+
def greet(self):
1791+
print("hello world")
1792+
""",
1793+
[]
1794+
)
1795+
17431796
def test_excluding_method(self) -> None:
17441797
self.check_coverage("""\
17451798
class Fooey:

0 commit comments

Comments
 (0)