Skip to content

Commit

Permalink
docs: explain the need for non-greedy wildcards
Browse files Browse the repository at this point in the history
  • Loading branch information
nedbat committed Jul 4, 2024
1 parent 1fe897d commit 7ea6c39
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 15 deletions.
2 changes: 1 addition & 1 deletion doc/cog_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ def show_configs(ini, toml):
toml, toml_vals = _read_config(toml, "covrc.toml")
for key, val in ini_vals.items():
if val != toml_vals[key]:
cog.error(f"Mismatch! {key}: {val!r} vs {toml_vals[key]!r}")
cog.error(f"Mismatch! {key}:\nini: {val!r}\ntoml: {toml_vals[key]!r}")

ini2 = re.sub(r"(?m)^\[", "[coverage:", ini)
print()
Expand Down
42 changes: 30 additions & 12 deletions doc/excluding.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,17 +258,21 @@ Here are some examples:
ini=r"""
[report]
exclude_also =
; Exclude an except clause of a specific form:
; 1. Exclude an except clause of a specific form:
except ValueError:\n\s*assume\(False\)
; A pragma comment that excludes an entire file:
; 2. Comments to turn coverage on and off:
no cover: start(?s:.)*?no cover: stop
; 3. A pragma comment that excludes an entire file:
(?s)\A.*# pragma: exclude file.*\Z
""",
toml=r"""
[tool.coverage.report]
exclude_also = [
# Exclude an except clause of a specific form:
# 1. Exclude an except clause of a specific form:
"except ValueError:\\n\\s*assume\\(False\\)",
# A pragma comment that excludes an entire file:
# 2. Comments to turn coverage on and off:
"no cover: start(?s:.)*?no cover: stop",
# 3. A pragma comment that excludes an entire file:
"(?s)\\A.*# pragma: exclude file.*\\Z",
]
""",
Expand All @@ -282,19 +286,23 @@ Here are some examples:

[report]
exclude_also =
; Exclude an except clause of a specific form:
; 1. Exclude an except clause of a specific form:
except ValueError:\n\s*assume\(False\)
; A pragma comment that excludes an entire file:
; 2. Comments to turn coverage on and off:
no cover: start(?s:.)*?no cover: stop
; 3. A pragma comment that excludes an entire file:
(?s)\A.*# pragma: exclude file.*\Z

.. code-tab:: toml
:caption: pyproject.toml

[tool.coverage.report]
exclude_also = [
# Exclude an except clause of a specific form:
# 1. Exclude an except clause of a specific form:
"except ValueError:\\n\\s*assume\\(False\\)",
# A pragma comment that excludes an entire file:
# 2. Comments to turn coverage on and off:
"no cover: start(?s:.)*?no cover: stop",
# 3. A pragma comment that excludes an entire file:
"(?s)\\A.*# pragma: exclude file.*\\Z",
]

Expand All @@ -303,19 +311,29 @@ Here are some examples:

[coverage:report]
exclude_also =
; Exclude an except clause of a specific form:
; 1. Exclude an except clause of a specific form:
except ValueError:\n\s*assume\(False\)
; A pragma comment that excludes an entire file:
; 2. Comments to turn coverage on and off:
no cover: start(?s:.)*?no cover: stop
; 3. A pragma comment that excludes an entire file:
(?s)\A.*# pragma: exclude file.*\Z

.. [[[end]]] (checksum: 8892a4efef9da67fb0080d15811e1c19)
.. [[[end]]] (checksum: 22ff0a1433f00d3b4d13544623aaf884)
The first regex matches a specific except line followed by a specific function
call. Both lines must be present for the exclusion to take effect. Note that
the regex uses ``"\n\s*"`` to match the newline and the indentation of the
second line. Without these, the regex won't match.

The second regex matches the entire text of a file containing the comment ``#
The second regex creates a pair of comments that can be used to exclude
statements between them. All lines between ``# no cover: start`` and ``# no
cover: stop`` will be excluded. The regex doesn't start with ``#`` because
that's a comment in a .coveragerc file. Be careful with wildcards: we've used
the non-greedy ``*?`` to match the fewest possible characters between the
comments. If you used the greedy ``*`` instead, the star would match as many
as possible, and you could accidentally exclude large swaths of code.

The third regex matches the entire text of a file containing the comment ``#
pragma: exclude file``. This lets you exclude files from coverage measurement
with an internal comment instead of naming them in a settings file. This regex
uses the ``"(?s)"`` regex flag to let a dot match any character including a
Expand Down
4 changes: 2 additions & 2 deletions tests/test_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ def foo():

def test_multiline_exclusion_block(self) -> None:
# https://github.com/nedbat/coveragepy/issues/1803
regex = "# no cover: start(?s:.)*# no cover: stop"
regex = "# no cover: start(?s:.)*?# no cover: stop"
parser = self.parse_text("""\
a = my_function1()
if debug:
Expand Down Expand Up @@ -924,7 +924,7 @@ def test_multiline_exclusion_block2(self) -> None:
def test_multiline_exclusion_block3(self) -> None:
# https://github.com/nedbat/coveragepy/issues/1741
# This will only work if there's exactly one return statement in the rest of the function
regex = r"# no cover: to return(?s:.)*return"
regex = r"# no cover: to return(?s:.)*?return"
parser = self.parse_text("""\
def my_function(args, j):
if args.command == Commands.CMD.value:
Expand Down

0 comments on commit 7ea6c39

Please sign in to comment.