Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 07b76b2

Browse filesBrowse files
committed
fix: some clause exclusions were broken #1713
1 parent 962429c commit 07b76b2
Copy full SHA for 07b76b2

File tree

Expand file treeCollapse file tree

4 files changed

+63
-9
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+63
-9
lines changed

‎CHANGES.rst

Copy file name to clipboardExpand all lines: CHANGES.rst
+5Lines 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

Copy file name to clipboardExpand all lines: coverage/parser.py
+4-8Lines 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

Copy file name to clipboardExpand all lines: tests/coveragetest.py
+1-1Lines 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

Copy file name to clipboardExpand all lines: tests/test_coverage.py
+53Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.