Skip to content

Commit 21e726f

Browse files
OlenaYefymenkowebknjaznedbat
authored
feat: support .coveragerc.toml for configuration (#1952)
* Add .coveragerc.toml to configuration file search order This adds .coveragerc.toml to the list of configuration files that coverage.py will automatically search for, with higher priority than pyproject.toml but lower than .coveragerc. * Parametrize TOML tests to include .coveragerc.toml Converts existing pyproject.toml tests to be parametrized to also test .coveragerc.toml functionality, ensuring both TOML config formats work identically. * Add test for .coveragerc.toml priority over pyproject.toml This test ensures that when both .coveragerc.toml and pyproject.toml are present, .coveragerc.toml takes precedence as intended. * Update documentation, changelog, and contributors list for new .coveragerc.toml configuration file support * Update the documentation and fix code formatting in tests/test_config.py * Provide typing for the new functions from code review Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> * Add the correct format in the documentation Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> * Add the correct description in the documentation Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> * Fix the test for non-coverage pyproject.toml without toml installed * Fix the linting issues * Edit D001 Line too long * Move coveragerc.toml description to unreleased section * Add support for unprefixed sections in the configuration * Update cog-generated documentation * Verify that unprefixed sections are ignored when present in pyproject.toml * Use fr-string instead of escaped backslashes Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> * Fix error according to Ruff standards * Apply suggestions from code review Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> * Update CHANGES.rst --------- Co-authored-by: 🇺🇦 Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]> Co-authored-by: Ned Batchelder <[email protected]>
1 parent 3914e50 commit 21e726f

File tree

12 files changed

+283
-63
lines changed

12 files changed

+283
-63
lines changed

CHANGES.rst

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

26+
- New feature: coverage.py now supports :file:`.coveragerc.toml` configuration
27+
files. These files use TOML syntax and take priority over
28+
:file:`pyproject.toml` but lower priority than :file:`.coveragerc` files.
29+
Closes `issue 1643`_ thanks to `Olena Yefymenko <pull 1952_>`_.
30+
2631
- The .pth file we install was done incorrectly and didn't work when using
2732
the source wheel (`py3-none-any`). This is now fixed. Thanks, `Henry
2833
Schreiner <pull 2100_>`_.
@@ -32,6 +37,8 @@ Unreleased
3237
3.10). The second and third of these are not needed and will eventually be
3338
removed.
3439

40+
.. _issue 1643: https://github.com/coveragepy/coveragepy/issues/1643
41+
.. _pull 1952: https://github.com/coveragepy/coveragepy/pull/1952
3542
.. _pull 2100: https://github.com/coveragepy/coveragepy/pull/2100
3643

3744
.. start-releases

CONTRIBUTORS.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ Nils Kattenbeck
188188
Noel O'Boyle
189189
Oleg Höfling
190190
Oleh Krehel
191+
Olena Yefymenko
191192
Olivier Grisel
192193
Ori Avtalion
193194
Pablo Carballo

coverage/config.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,7 @@ def config_files_to_try(config_file: bool | str) -> list[tuple[str, bool, bool]]
658658
assert isinstance(config_file, str)
659659
files_to_try = [
660660
(config_file, True, specified_file),
661+
(".coveragerc.toml", True, False),
661662
("setup.cfg", False, False),
662663
("tox.ini", False, False),
663664
("pyproject.toml", False, False),

coverage/tomlconfig.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ def _get_section(self, section: str) -> tuple[str | None, TConfigSectionOut | No
8484
8585
"""
8686
prefixes = ["tool.coverage."]
87+
if self.our_file:
88+
prefixes.append("")
8789
for prefix in prefixes:
8890
real_section = prefix + section
8991
parts = real_section.split(".")

doc/cog_helpers.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def show_configs(ini, toml):
7676
The equivalence is checked for accuracy, and the process fails if there's
7777
a mismatch.
7878
79-
A three-tabbed box will be produced.
79+
A four-tabbed box will be produced.
8080
"""
8181
ini, ini_vals = _read_config(ini, "covrc")
8282
toml, toml_vals = _read_config(toml, "covrc.toml")
@@ -89,11 +89,15 @@ def show_configs(ini, toml):
8989
)
9090

9191
ini2 = re.sub(r"(?m)^\[", "[coverage:", ini)
92+
toml2 = "# You can also use sections like [tool.coverage.run]\n"
93+
toml2 += toml.replace("[tool.coverage.", "[")
94+
9295
print()
9396
print(".. tabs::\n")
9497
for name, syntax, text in [
95-
(".coveragerc", "ini", ini),
9698
("pyproject.toml", "toml", toml),
99+
(".coveragerc", "ini", ini),
100+
(".coveragerc.toml", "toml", toml2),
97101
("setup.cfg or tox.ini", "ini", ini2),
98102
]:
99103
print(f" .. code-tab:: {syntax}")

doc/config.rst

Lines changed: 53 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ environment variable.
3939

4040
If ``.coveragerc`` doesn't exist and another file hasn't been specified, then
4141
coverage.py will look for settings in other common configuration files, in this
42-
order: setup.cfg, tox.ini, or pyproject.toml. The first file found with
43-
coverage.py settings will be used and other files won't be consulted.
42+
order: :file:`.coveragerc.toml`, :file:`setup.cfg`, :file:`tox.ini`, or
43+
:file:`pyproject.toml`. The first file found with coverage.py settings will be
44+
used and other files won't be consulted.
4445

4546
Coverage.py will read from "pyproject.toml" if TOML support is available,
4647
either because you are running on Python 3.11 or later, or because you
@@ -169,6 +170,36 @@ Here's a sample configuration file, in each syntax:
169170
170171
.. tabs::
171172

173+
.. code-tab:: toml
174+
:caption: pyproject.toml
175+
176+
[tool.coverage.run]
177+
branch = true
178+
179+
[tool.coverage.report]
180+
# Regexes for lines to exclude from consideration
181+
exclude_also = [
182+
# Don't complain about missing debug-only code:
183+
"def __repr__",
184+
"if self\\.debug",
185+
186+
# Don't complain if tests don't hit defensive assertion code:
187+
"raise AssertionError",
188+
"raise NotImplementedError",
189+
190+
# Don't complain if non-runnable code isn't run:
191+
"if 0:",
192+
"if __name__ == .__main__.:",
193+
194+
# Don't complain about abstract methods, they aren't run:
195+
"@(abc\\.)?abstractmethod",
196+
]
197+
198+
ignore_errors = true
199+
200+
[tool.coverage.html]
201+
directory = "coverage_html_report"
202+
172203
.. code-tab:: ini
173204
:caption: .coveragerc
174205

@@ -199,12 +230,13 @@ Here's a sample configuration file, in each syntax:
199230
directory = coverage_html_report
200231

201232
.. code-tab:: toml
202-
:caption: pyproject.toml
233+
:caption: .coveragerc.toml
203234

204-
[tool.coverage.run]
235+
# You can also use sections like [tool.coverage.run]
236+
[run]
205237
branch = true
206238

207-
[tool.coverage.report]
239+
[report]
208240
# Regexes for lines to exclude from consideration
209241
exclude_also = [
210242
# Don't complain about missing debug-only code:
@@ -225,7 +257,7 @@ Here's a sample configuration file, in each syntax:
225257

226258
ignore_errors = true
227259

228-
[tool.coverage.html]
260+
[html]
229261
directory = "coverage_html_report"
230262

231263
.. code-tab:: ini
@@ -257,7 +289,7 @@ Here's a sample configuration file, in each syntax:
257289
[coverage:html]
258290
directory = coverage_html_report
259291

260-
.. [[[end]]] (sum: HU1Z62mvRK)
292+
.. [[[end]]] (sum: qYCtIxMe+3)
261293
262294
263295
The specific configuration settings are described below. Many sections and
@@ -596,6 +628,16 @@ equivalent when combining data from different machines:
596628
597629
.. tabs::
598630

631+
.. code-tab:: toml
632+
:caption: pyproject.toml
633+
634+
[tool.coverage.paths]
635+
source = [
636+
"src/",
637+
"/jenkins/build/*/src",
638+
"c:\\myproj\\src",
639+
]
640+
599641
.. code-tab:: ini
600642
:caption: .coveragerc
601643

@@ -606,9 +648,10 @@ equivalent when combining data from different machines:
606648
c:\myproj\src
607649
608650
.. code-tab:: toml
609-
:caption: pyproject.toml
651+
:caption: .coveragerc.toml
610652

611-
[tool.coverage.paths]
653+
# You can also use sections like [tool.coverage.run]
654+
[paths]
612655
source = [
613656
"src/",
614657
"/jenkins/build/*/src",
@@ -624,7 +667,7 @@ equivalent when combining data from different machines:
624667
/jenkins/build/*/src
625668
c:\myproj\src
626669
627-
.. [[[end]]] (sum: oHSl8SGiMT)
670+
.. [[[end]]] (sum: Aq4877/XV0)
628671
629672
630673
The names of the entries ("source" in this example) are ignored, you may choose

doc/contexts.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,23 @@ The ``[run] dynamic_context`` setting has only one option now. Set it to
9090
9191
.. tabs::
9292

93+
.. code-tab:: toml
94+
:caption: pyproject.toml
95+
96+
[tool.coverage.run]
97+
dynamic_context = "test_function"
98+
9399
.. code-tab:: ini
94100
:caption: .coveragerc
95101

96102
[run]
97103
dynamic_context = test_function
98104

99105
.. code-tab:: toml
100-
:caption: pyproject.toml
106+
:caption: .coveragerc.toml
101107

102-
[tool.coverage.run]
108+
# You can also use sections like [tool.coverage.run]
109+
[run]
103110
dynamic_context = "test_function"
104111

105112
.. code-tab:: ini
@@ -108,7 +115,7 @@ The ``[run] dynamic_context`` setting has only one option now. Set it to
108115
[coverage:run]
109116
dynamic_context = test_function
110117

111-
.. [[[end]]] (sum: dZTDYjHw71)
118+
.. [[[end]]] (sum: G1Fc1tVhgd)
112119
113120
Each test function you run will be considered a separate dynamic context, and
114121
coverage data will be segregated for each. A test function is any function

doc/excluding.rst

Lines changed: 50 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,14 @@ all of them by adding a regex to the exclusion list:
137137
138138
.. tabs::
139139

140+
.. code-tab:: toml
141+
:caption: pyproject.toml
142+
143+
[tool.coverage.report]
144+
exclude_also = [
145+
"def __repr__",
146+
]
147+
140148
.. code-tab:: ini
141149
:caption: .coveragerc
142150

@@ -145,9 +153,10 @@ all of them by adding a regex to the exclusion list:
145153
def __repr__
146154

147155
.. code-tab:: toml
148-
:caption: pyproject.toml
156+
:caption: .coveragerc.toml
149157

150-
[tool.coverage.report]
158+
# You can also use sections like [tool.coverage.run]
159+
[report]
151160
exclude_also = [
152161
"def __repr__",
153162
]
@@ -159,7 +168,7 @@ all of them by adding a regex to the exclusion list:
159168
exclude_also =
160169
def __repr__
161170

162-
.. [[[end]]] (sum: 8+cOvxKPvv)
171+
.. [[[end]]] (sum: pma7Vgh8a0)
163172
164173
For example, here's a list of exclusions I've used:
165174

@@ -199,6 +208,23 @@ For example, here's a list of exclusions I've used:
199208
200209
.. tabs::
201210

211+
.. code-tab:: toml
212+
:caption: pyproject.toml
213+
214+
[tool.coverage.report]
215+
exclude_also = [
216+
'def __repr__',
217+
'if self.debug:',
218+
'if settings.DEBUG',
219+
'raise AssertionError',
220+
'raise NotImplementedError',
221+
'if 0:',
222+
'if __name__ == .__main__.:',
223+
'if TYPE_CHECKING:',
224+
'class .*\bProtocol\):',
225+
'@(abc\.)?abstractmethod',
226+
]
227+
202228
.. code-tab:: ini
203229
:caption: .coveragerc
204230

@@ -216,9 +242,10 @@ For example, here's a list of exclusions I've used:
216242
@(abc\.)?abstractmethod
217243

218244
.. code-tab:: toml
219-
:caption: pyproject.toml
245+
:caption: .coveragerc.toml
220246

221-
[tool.coverage.report]
247+
# You can also use sections like [tool.coverage.run]
248+
[report]
222249
exclude_also = [
223250
'def __repr__',
224251
'if self.debug:',
@@ -248,7 +275,7 @@ For example, here's a list of exclusions I've used:
248275
class .*\bProtocol\):
249276
@(abc\.)?abstractmethod
250277

251-
.. [[[end]]] (sum: ZQsgnt0nES)
278+
.. [[[end]]] (sum: QV2NECVQ1X)
252279
253280
The :ref:`config_report_exclude_also` option adds regexes to the built-in
254281
default list so that you can add your own exclusions. The older
@@ -306,6 +333,19 @@ Here are some examples:
306333
307334
.. tabs::
308335

336+
.. code-tab:: toml
337+
:caption: pyproject.toml
338+
339+
[tool.coverage.report]
340+
exclude_also = [
341+
# 1. Exclude an except clause of a specific form:
342+
'except ValueError:\n\s*assume\(False\)',
343+
# 2. Comments to turn coverage on and off:
344+
'no cover: start(?s:.)*?no cover: stop',
345+
# 3. A pragma comment that excludes an entire file:
346+
'\A(?s:.*# pragma: exclude file.*)\Z',
347+
]
348+
309349
.. code-tab:: ini
310350
:caption: .coveragerc
311351

@@ -319,9 +359,10 @@ Here are some examples:
319359
\A(?s:.*# pragma: exclude file.*)\Z
320360

321361
.. code-tab:: toml
322-
:caption: pyproject.toml
362+
:caption: .coveragerc.toml
323363

324-
[tool.coverage.report]
364+
# You can also use sections like [tool.coverage.run]
365+
[report]
325366
exclude_also = [
326367
# 1. Exclude an except clause of a specific form:
327368
'except ValueError:\n\s*assume\(False\)',
@@ -343,7 +384,7 @@ Here are some examples:
343384
; 3. A pragma comment that excludes an entire file:
344385
\A(?s:.*# pragma: exclude file.*)\Z
345386

346-
.. [[[end]]] (sum: xG6Bmtmh06)
387+
.. [[[end]]] (sum: LAn0Y4yP/X)
347388
348389
The first regex matches a specific except line followed by a specific function
349390
call. Both lines must be present for the exclusion to take effect. Note that

doc/messages.rst

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -184,16 +184,23 @@ file:
184184
185185
.. tabs::
186186

187+
.. code-tab:: toml
188+
:caption: pyproject.toml
189+
190+
[tool.coverage.run]
191+
disable_warnings = ["no-data-collected"]
192+
187193
.. code-tab:: ini
188194
:caption: .coveragerc
189195

190196
[run]
191197
disable_warnings = no-data-collected
192198

193199
.. code-tab:: toml
194-
:caption: pyproject.toml
200+
:caption: .coveragerc.toml
195201

196-
[tool.coverage.run]
202+
# You can also use sections like [tool.coverage.run]
203+
[run]
197204
disable_warnings = ["no-data-collected"]
198205

199206
.. code-tab:: ini
@@ -202,4 +209,4 @@ file:
202209
[coverage:run]
203210
disable_warnings = no-data-collected
204211

205-
.. [[[end]]] (sum: SJKFvPoXO2)
212+
.. [[[end]]] (sum: 29eQyqSCXt)

0 commit comments

Comments
 (0)