Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fd36918

Browse files
committedSep 27, 2022
fix: class statements shouldn't be branches. #1449
Revert "refactor: we no longer need to treat 'class' lines specially" This reverts commit 79f9f45.
1 parent 2c4bd7f commit fd36918

File tree

5 files changed

+26
-7
lines changed

5 files changed

+26
-7
lines changed
 

‎CHANGES.rst

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

23+
- Starting with coverage.py 6.2, ``class`` statements were marked as a branch.
24+
This wasn't right, and has been reverted, fixing `issue 1449`_.
25+
2326
- Packaging is now compliant with `PEP 517`_, closing `issue 1395`_.
2427

2528
- A new debug option ``--debug=pathmap`` shows details of the remapping of
@@ -31,6 +34,7 @@ Unreleased
3134
.. _bug 50381: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=50381
3235
.. _PEP 517: https://peps.python.org/pep-0517/
3336
.. _issue 1395: https://github.com/nedbat/coveragepy/issues/1395
37+
.. _issue 1449: https://github.com/nedbat/coveragepy/issues/1449
3438

3539

3640
.. _changes_6-4-4:

‎coverage/parser.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ def __init__(self, text=None, filename=None, exclude=None):
6767
# The raw line numbers of excluded lines of code, as marked by pragmas.
6868
self.raw_excluded = set()
6969

70+
# The line numbers of class definitions.
71+
self.raw_classdefs = set()
72+
7073
# The line numbers of docstring lines.
7174
self.raw_docstrings = set()
7275

@@ -130,6 +133,12 @@ def _raw_parse(self):
130133
indent += 1
131134
elif toktype == token.DEDENT:
132135
indent -= 1
136+
elif toktype == token.NAME:
137+
if ttext == 'class':
138+
# Class definitions look like branches in the bytecode, so
139+
# we need to exclude them. The simplest way is to note the
140+
# lines with the 'class' keyword.
141+
self.raw_classdefs.add(slineno)
133142
elif toktype == token.OP:
134143
if ttext == ':' and nesting == 0:
135144
should_exclude = (elineno in self.raw_excluded) or excluding_decorators
@@ -292,6 +301,12 @@ def exit_counts(self):
292301
continue
293302
exit_counts[l1] += 1
294303

304+
# Class definitions have one extra exit, so remove one for each:
305+
for l in self.raw_classdefs:
306+
# Ensure key is there: class definitions can include excluded lines.
307+
if l in exit_counts:
308+
exit_counts[l] -= 1
309+
295310
return exit_counts
296311

297312
def missing_arc_description(self, start, end, executed_arcs=None):

‎lab/parser.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ def one_file(self, options, filename):
108108
marks[2] = str(exits)
109109
if lineno in pyparser.raw_docstrings:
110110
marks[3] = '"'
111+
if lineno in pyparser.raw_classdefs:
112+
marks[3] = 'C'
111113
if lineno in pyparser.raw_excluded:
112114
marks[4] = 'x'
113115

‎tests/test_lcov.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,10 +203,8 @@ def test_is_it_x(self):
203203
DA:9,0,FPTWzd68bDx76HN7VHu1wA
204204
LF:6
205205
LH:4
206-
BRDA:0,0,0,1
207-
BRDA:7,0,1,1
208-
BRF:2
209-
BRH:2
206+
BRF:0
207+
BRH:0
210208
end_of_record
211209
""")
212210
actual_result = self.get_lcov_report_content()

‎tests/test_parser.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class Bar:
4343
pass
4444
""")
4545
assert parser.exit_counts() == {
46-
2:2, 3:1, 4:2, 5:1, 7:1, 9:2, 10:1
46+
2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1
4747
}
4848

4949
def test_generator_exit_counts(self):
@@ -89,7 +89,7 @@ class Bar:
8989
pass
9090
""")
9191
assert parser.exit_counts() == {
92-
1:1, 2:1, 3:1
92+
1:0, 2:1, 3:1
9393
}
9494

9595
def test_missing_branch_to_excluded_code(self):
@@ -472,7 +472,7 @@ def foo(self, a):
472472
class Bar:
473473
pass
474474
"""
475-
counts = { 2:2, 3:1, 4:2, 5:1, 7:1, 9:2, 10:1 }
475+
counts = { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 }
476476
fname = slug + ".py"
477477
self.make_file(fname, text, newline=newline)
478478
parser = self.parse_file(fname)

0 commit comments

Comments
 (0)
Please sign in to comment.