Skip to content

Commit 8d4fcbf

Browse files
authored
Replace flake8 and black with ruff (gcovr#1007)
* Replace black and flake8 with ruff, reformat code * Move pytest and coverage configuration to toml
1 parent ea44603 commit 8d4fcbf

18 files changed

+122
-95
lines changed

.vscode/tasks.json

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,9 @@
3939
"group": "build"
4040
},
4141
{
42-
"label": "Run black",
42+
"label": "Run ruff",
4343
"type": "shell",
44-
"command": "nox --reuse-existing-virtualenvs $(if [ -n \"${env:NOX_ENV_DIR}\" ] ; then echo \"--envdir ${env:NOX_ENV_DIR}\" ; fi) -s black",
45-
"group": "build"
46-
},
47-
{
48-
"label": "Run flake8",
49-
"type": "shell",
50-
"command": "nox --reuse-existing-virtualenvs $(if [ -n \"${env:NOX_ENV_DIR}\" ] ; then echo \"--envdir ${env:NOX_ENV_DIR}\" ; fi) -s flake8",
44+
"command": "nox --reuse-existing-virtualenvs $(if [ -n \"${env:NOX_ENV_DIR}\" ] ; then echo \"--envdir ${env:NOX_ENV_DIR}\" ; fi) -s ruff",
5145
"group": "build"
5246
},
5347
{
@@ -77,7 +71,7 @@
7771
{
7872
"label": "Format current file",
7973
"type": "shell",
80-
"command": "nox --reuse-existing-virtualenvs $(if [ -n \"${env:NOX_ENV_DIR}\" ] ; then echo \"--envdir ${env:NOX_ENV_DIR}\" ; fi) -s black -- ${file}",
74+
"command": "nox --reuse-existing-virtualenvs $(if [ -n \"${env:NOX_ENV_DIR}\" ] ; then echo \"--envdir ${env:NOX_ENV_DIR}\" ; fi) -s ruff -- format ${file}",
8175
"group": "build"
8276
},
8377
{

CHANGELOG.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ Internal changes:
2929

3030
- Add MacOs 15 and clang-16 to the GitHub test workflow. (:issue:`1004`)
3131
- Fix sporadic timestamp mismatch in development build package. (:issue:`1006`)
32+
- Replace ``black`` and ``flake8`` with ``ruff`` and move configuration of ``pytest`` to ``pyproject.toml``. (:issue:`1007`)
3233

3334
8.2 (13 October 2024)
3435
---------------------

CONTRIBUTING.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ and a comprehensive corpus of example projects
267267
that are executed as the ``test_gcovr.py`` integration test.
268268
Each ``tests/*`` directory is one such example project.
269269

270-
You can format files with ``python3 -m nox --session black``)
270+
You can format files with ``python3 -m nox --session ruff -- format path/to/file``)
271271

272272
To get a list of all available sessions run ``python3 -m nox -l``.
273273

@@ -276,6 +276,9 @@ the :ref:`structure of integration tests <integration tests>`,
276276
how to :ref:`run and filter tests <run tests>`,
277277
and how to :ref:`run tests with Docker <docker tests>`.
278278

279+
.. versionchanged:: NEXT
280+
black is replaced by ruff.
281+
279282
.. versionchanged:: 5.2
280283
If black is called without arguments, all files are reformated
281284
instead of checked. To check the format use the session lint.

admin/Dockerfile.qa

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ RUN echo "docker:docker" | chpasswd
106106
USER docker:docker
107107

108108
# Select language-agnostic "C" locale.
109-
# Unicode is necessary for some tools like "black" to work.
109+
# Unicode is necessary for some tools to work.
110110
ENV LC_ALL=C.UTF-8 LANG=C.UTF-8
111111

112112
WORKDIR /gcovr

admin/bump_version.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,21 @@
4949

5050

5151
def getLicenseSection(comment_char: str = "#"):
52-
yield comment_char + " ************************** Copyrights and license ***************************"
52+
yield (
53+
comment_char
54+
+ " ************************** Copyrights and license ***************************"
55+
)
5356
yield comment_char
54-
yield comment_char + f" This file is part of gcovr {VERSION}, a parsing and reporting tool for gcov."
57+
yield (
58+
comment_char
59+
+ f" This file is part of gcovr {VERSION}, a parsing and reporting tool for gcov."
60+
)
5561
yield comment_char + f" https://gcovr.com/en/{READTHEDOCS_VERSION}"
5662
yield comment_char
57-
yield comment_char + " _____________________________________________________________________________"
63+
yield (
64+
comment_char
65+
+ " _____________________________________________________________________________"
66+
)
5867
yield comment_char
5968
for line in COPYRIGHT:
6069
yield comment_char + " " + line

cspell.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,10 @@
7272
"googletest",
7373
"gtest",
7474
"Hashbang",
75+
"htmlcov",
7576
"iostream",
7677
"jacoco",
7778
"kcov",
78-
"latk",
7979
"lcov",
8080
"LDFLAGS",
8181
"levelname",
@@ -120,6 +120,7 @@
120120
"stylesheet",
121121
"Traceback",
122122
"tracefile",
123+
"unfixable",
123124
"venv",
124125
"versionadded",
125126
"versionchanged",
@@ -145,6 +146,7 @@
145146
"includecss",
146147
"keil",
147148
"kMGTPEZY",
149+
"latk",
148150
"levelno",
149151
"linenos",
150152
"linkcss",
@@ -158,6 +160,7 @@
158160
"pydevproject",
159161
"Sandia",
160162
"strerror",
163+
"subdir",
161164
"testcase",
162165
"userdel",
163166
"userid",

gcovr/configuration.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ def get_boolean(silent_error: bool = False):
224224
try:
225225
value = converter(cfg_entry.value)
226226
except (ValueError, ArgumentTypeError) as err:
227-
raise cfg_entry.error(str(err))
227+
raise cfg_entry.error(str(err)) from None
228228

229229
elif option.name == "json_add_tracefile": # Special case for patterns
230230
if cfg_entry.filename is None:
@@ -316,7 +316,6 @@ def merge_options_and_set_defaults(
316316
target: Dict[str, Any] = {}
317317
for namespace in partial_namespaces:
318318
for option in all_options:
319-
320319
if option.name not in namespace:
321320
continue
322321

@@ -794,15 +793,15 @@ def parse_config_file(
794793
test.cfg: 7: optional = spaces
795794
"""
796795

796+
def error(pattern: str, *args, **kwargs):
797+
# pylint: disable=cell-var-from-loop
798+
message = pattern.format(*args, **kwargs)
799+
message += f"\non this line: {line}"
800+
return SyntaxError(": ".join([filename, str(lineno), message]))
801+
797802
for lineno, line in enumerate(open_file, first_lineno):
798803
line = line.rstrip()
799804

800-
def error(pattern: str, *args, **kwargs):
801-
# pylint: disable=cell-var-from-loop
802-
message = pattern.format(*args, **kwargs)
803-
message += "\non this line: " + line
804-
return SyntaxError(": ".join([filename, str(lineno), message]))
805-
806805
# strip (trailing) comments
807806
line = CONFIG_HASH_COMMENT.sub("", line)
808807

gcovr/formats/cobertura/read.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,9 @@ def read_report(options: Options) -> CovData:
6868
LOGGER.debug(f"Processing XML file: {filename}")
6969

7070
try:
71-
root = etree.parse(
72-
filename
73-
).getroot() # nosec # We parse the file given by the user
71+
root = etree.parse(filename).getroot() # nosec # We parse the file given by the user
7472
except Exception as e:
75-
raise RuntimeError(f"Bad --cobertura-add-tracefile option.\n{e}")
73+
raise RuntimeError(f"Bad --cobertura-add-tracefile option.\n{e}") from None
7674

7775
for gcovr_file in root.xpath("./packages//class"):
7876
if gcovr_file.get("filename") is None: # pragma: no cover
@@ -106,15 +104,15 @@ def _line_from_xml(filename: str, xml_line) -> LineCoverage:
106104
raise RuntimeError(
107105
"Bad --covertura-add-tracefile option.\n"
108106
f"'number' attribute is required and must be an integer: {etree.tostring(xml_line).decode()}\n"
109-
)
107+
) from None
110108

111109
try:
112110
count = int(xml_line.get("hits"))
113111
except Exception: # pragma: no cover
114112
raise RuntimeError(
115113
"Bad --covertura-add-tracefile option.\n"
116114
f"'hits' attribute is required and must be an integer: {etree.tostring(xml_line).decode()}\n"
117-
)
115+
) from None
118116

119117
is_branch = xml_line.get("branch") == "true"
120118
branch_msg = xml_line.get("condition-coverage")

gcovr/formats/coveralls/write.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,6 @@ def run_git_log_cmd(arg):
173173
# Loop through each coverage file collecting details
174174
json_dict["source_files"] = []
175175
for file_path in sorted(covdata):
176-
177176
# File data has been compiled
178177
json_dict["source_files"].append(_make_source_file(covdata[file_path], options))
179178

gcovr/formats/gcov/parser.py

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
"""
3636
# pylint: disable=too-many-lines
3737

38-
3938
import enum
4039
import logging
4140
import re
@@ -315,7 +314,6 @@ def parse_metadata(lines: List[str]) -> Dict[str, Optional[str]]:
315314
"""
316315
collected = {}
317316
for line in lines:
318-
319317
# empty lines shouldn't occur in reality, but are common in testing
320318
if not line:
321319
continue
@@ -369,7 +367,6 @@ def parse_coverage(
369367
tokenized_lines: List[Tuple[_Line, str]] = []
370368
persistent_states: Dict[str, Any] = {}
371369
for raw_line in lines:
372-
373370
# empty lines shouldn't occur in reality, but are common in testing
374371
if not raw_line:
375372
continue
@@ -607,7 +604,9 @@ def _report_lines_with_errors(
607604

608605

609606
def _parse_line(
610-
line: str, ignore_parse_errors: set = (), persistent_states: dict = {}
607+
line: str,
608+
ignore_parse_errors: Optional[set] = None,
609+
persistent_states: Optional[dict] = None,
611610
) -> _Line:
612611
"""
613612
Categorize/parse individual lines without further processing.
@@ -729,6 +728,10 @@ def _parse_line(
729728
gcovr.formats.gcov.parser.UnknownLineType: nonexistent_tag foo bar
730729
"""
731730
# pylint: disable=too-many-branches
731+
if ignore_parse_errors is None:
732+
ignore_parse_errors = set([])
733+
if persistent_states is None:
734+
persistent_states = {}
732735

733736
tag = _parse_tag_line(line, ignore_parse_errors, persistent_states)
734737
if tag is not None:
@@ -838,10 +841,16 @@ def _parse_line(
838841

839842

840843
def _parse_tag_line(
841-
line: str, ignore_parse_errors: set = (), persistent_states: dict = {}
844+
line: str,
845+
ignore_parse_errors: Optional[set] = None,
846+
persistent_states: Optional[dict] = None,
842847
) -> Optional[_Line]:
843848
"""A tag line is any gcov line that starts in the first column."""
844849
# pylint: disable=too-many-return-statements
850+
if ignore_parse_errors is None:
851+
ignore_parse_errors = set([])
852+
if persistent_states is None:
853+
persistent_states = {}
845854

846855
# Tag lines never start with whitespace.
847856
#

gcovr/formats/html/write.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,6 @@ def get_theme_color(html_theme: str) -> str:
8484
# This speeds up text and XML output.
8585
@Lazy
8686
def templates(options):
87-
8887
from jinja2 import ChoiceLoader, Environment, FileSystemLoader, PackageLoader
8988

9089
# As default use the package loader
@@ -129,7 +128,6 @@ def load_user_template(template):
129128

130129

131130
class CssRenderer:
132-
133131
THEMES = [
134132
"green",
135133
"blue",
@@ -523,7 +521,6 @@ def write_source_pages(
523521
cdata_sourcefile: Dict[str, str],
524522
data: Dict[str, Any],
525523
) -> bool:
526-
527524
error_no_files_not_found = 0
528525
all_functions = dict()
529526
for fname, cdata in covdata.items():
@@ -614,7 +611,6 @@ def write_single_page(
614611
cdata_sourcefile: Dict[str, str],
615612
data: Dict[str, Any],
616613
) -> bool:
617-
618614
error_no_files_not_found = 0
619615
files = []
620616
all_functions = dict()

gcovr/formats/lcov/write.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ def write_report(covdata: CovData, output_file: str, options: Options) -> None:
4848
# TN:<test name>
4949
fh.write(f"TN:{options.lcov_test_name}\n")
5050

51+
def postfix():
52+
return f"_{lineno}" if len(linenos) > 1 else ""
53+
5154
for key in keys:
5255
filename = force_unix_separator(covdata[key].filename)
5356

@@ -68,9 +71,6 @@ def write_report(covdata: CovData, output_file: str, options: Options) -> None:
6871
linenos = list(covdata[key].functions[function_name].count)
6972
functions += len(linenos)
7073

71-
def postfix():
72-
return f"_{lineno}" if len(linenos) > 1 else ""
73-
7474
for lineno in sorted(linenos):
7575
# FN:<line number of function start>,[<line number of function end>,]<function name>
7676
fh.write(f"FN:{lineno},{function_name}{postfix()}\n")
@@ -92,7 +92,7 @@ def postfix():
9292
for lineno in sorted_lines:
9393
line_coverage = covdata[key].lines[lineno]
9494
if line_coverage.excluded:
95-
next
95+
continue
9696
branches += len(line_coverage.branches)
9797
for branch in sorted(line_coverage.branches):
9898
branch_coverage = line_coverage.branches[branch]

0 commit comments

Comments
 (0)