Skip to content

Commit d64a30f

Browse files
committed
feat: two new default exclusions. #831
1 parent d0672a9 commit d64a30f

File tree

7 files changed

+47
-10
lines changed

7 files changed

+47
-10
lines changed

CHANGES.rst

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ upgrading your version of coverage.py.
2323
Unreleased
2424
----------
2525

26-
Nothing yet.
26+
- Two new exclusion patterns are part of the defaults: `...` is automatically
27+
excluded as a line and `if TYPE_CHECKING` is excluded as a branch. Closes
28+
`issue 831`_.
29+
30+
.. _issue 831: https://github.com/nedbat/coveragepy/issues/831
2731

2832

2933
.. start-releases

coverage/config.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ def getregexlist(self, section: str, option: str) -> list[str]:
152152
# The default line exclusion regexes.
153153
DEFAULT_EXCLUDE = [
154154
r"#\s*(pragma|PRAGMA)[:\s]?\s*(no|NO)\s*(cover|COVER)",
155+
r"^\s*\.\.\.\s*(#|$)",
155156
]
156157

157158
# The default partial branch regexes, to be modified by the user.
@@ -165,6 +166,7 @@ def getregexlist(self, section: str, option: str) -> list[str]:
165166
DEFAULT_PARTIAL_ALWAYS = [
166167
"while (True|1|False|0):",
167168
"if (True|1|False|0):",
169+
r"if (typing\.)?TYPE_CHECKING:",
168170
]
169171

170172

coverage/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
# version_info: same semantics as sys.version_info.
1010
# _dev: the .devN suffix if any.
11-
version_info = (7, 9, 3, "alpha", 0)
11+
version_info = (7, 10, 0, "alpha", 0)
1212
_dev = 1
1313

1414

doc/config.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,7 @@ Settings common to many kinds of reporting.
620620
(multi-string) A list of regular expressions. This setting is similar to
621621
:ref:`config_report_exclude_lines`: it specifies patterns for lines to exclude
622622
from reporting. This setting is preferred, because it will preserve the
623-
default exclude pattern ``pragma: no cover`` instead of overwriting it.
623+
default exclude patterns like ``pragma: no cover`` instead of overwriting them.
624624

625625
See :ref:`config_report_exclude_lines` for further details.
626626

doc/excluding.rst

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,37 @@ Because the ``else`` clause is excluded, the ``if`` only has one possible next
7070
line, so it isn't considered a branch at all.
7171

7272

73+
Default exclusions
74+
------------------
75+
76+
Coverage.py has a set of built-in exclusion patterns. For line coverage, these
77+
lines are automatically excluded:
78+
79+
- Any line with a comment like ``# pragma: no cover``. Other slight
80+
differences in spacing and letter case are also recognized.
81+
82+
- Any line with only ``...`` in the code.
83+
84+
For branch coverage, these kinds of branches are automatically excluded:
85+
86+
- A branch with a comment like ``# pragma: no branch``, including differences
87+
in spacing and letter case.
88+
89+
- Some branches that are known at compile time: ``if True:``, ``while True:``,
90+
and so on.
91+
92+
- A branch just for the type checker: ``if TYPE_CHECKING:``.
93+
94+
7395
Advanced exclusion
7496
------------------
7597

7698
Coverage.py identifies exclusions by matching source code against a list of
7799
regular expressions. Using :ref:`configuration files <config>` or the coverage
78100
:ref:`API <api>`, you can add to that list. This is useful if you have
79101
often-used constructs to exclude that can be matched with a regex. You can
80-
exclude them all at once without littering your code with exclusion pragmas.
102+
exclude them all at once in your configuration without littering your code with
103+
exclusion pragmas.
81104

82105
Before coverage.py 7.6.0, the regexes were matched against single lines of your
83106
source code. Now they can be multi-line regexes that find matches across

tests/test_arcs.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,9 +2160,13 @@ def test_default(self) -> None:
21602160
e = 7
21612161
if e:#\tpragma:\tno branch
21622162
f = 9
2163+
import typing
2164+
if typing.TYPE_CHECKING: # only for mypy
2165+
g = 12
21632166
""",
2164-
lines=[1,2,3,4,5,6,7,8,9],
2165-
branchz="23 24 56 57 89 8.",
2167+
lines=[1,2,3,4,5,6,7,8,9,10,11,12],
2168+
missing="12",
2169+
branchz="23 24 56 57 89 8A BC B.",
21662170
branchz_missing="",
21672171
)
21682172

tests/test_coverage.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,8 +1424,12 @@ def test_default(self) -> None:
14241424
e = 5
14251425
f = 6#\tpragma:\tno cover
14261426
g = 7
1427+
...
1428+
i = 9
1429+
... # we don't care about this line
1430+
k = 11
14271431
""",
1428-
lines=[1,3,5,7],
1432+
lines=[1,3,5,7,9,11],
14291433
)
14301434

14311435
def test_two_excludes(self) -> None:
@@ -1506,13 +1510,13 @@ def test_excluded_comprehension_branches(self) -> None:
15061510
self.check_coverage("""\
15071511
x, y = [0], [1]
15081512
if x == [2]:
1509-
raise NotImplementedError # pragma: NO COVER
1513+
raise NotImplementedError # NOCOVPLZ
15101514
if all(_ == __ for _, __ in zip(x, y)):
1511-
raise NotImplementedError # pragma: NO COVER
1515+
raise NotImplementedError # NOCOVPLZ
15121516
""",
15131517
lines=[1,2,4],
15141518
missing="",
1515-
excludes=['#pragma: NO COVER'],
1519+
excludes=['# NOCOVPLZ'],
15161520
branchz="23 24 45 4.",
15171521
branchz_missing="",
15181522
)

0 commit comments

Comments
 (0)