Skip to content

Commit 5be64c3

Browse files
Merge pull request #11912 from Pierre-Sassoulas/activate-ruff-checks
[pre-commit] Activate ruff checks and fix existing issues
2 parents bdfc5c8 + 233ab89 commit 5be64c3

31 files changed

+64
-67
lines changed

pyproject.toml

+3
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ select = [
133133
"F", # pyflakes
134134
"I", # isort
135135
"UP", # pyupgrade
136+
"RUF", # ruff
136137
"W", # pycodestyle
137138
]
138139
ignore = [
@@ -156,6 +157,8 @@ ignore = [
156157
"D402", # First line should not be the function's signature
157158
"D404", # First word of the docstring should not be "This"
158159
"D415", # First line should end with a period, question mark, or exclamation point
160+
# ruff ignore
161+
"RUF012", # Mutable class attributes should be annotated with `typing.ClassVar`
159162
]
160163

161164
[tool.ruff.format]

scripts/release.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def pre_release(
107107

108108
def changelog(version: str, write_out: bool = False) -> None:
109109
addopts = [] if write_out else ["--draft"]
110-
check_call(["towncrier", "--yes", "--version", version] + addopts)
110+
check_call(["towncrier", "--yes", "--version", version, *addopts])
111111

112112

113113
def main() -> None:

src/_pytest/_code/code.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1018,7 +1018,7 @@ def _truncate_recursive_traceback(
10181018
extraline: Optional[str] = (
10191019
"!!! Recursion error detected, but an error occurred locating the origin of recursion.\n"
10201020
" The following exception happened when comparing locals in the stack frame:\n"
1021-
f" {type(e).__name__}: {str(e)}\n"
1021+
f" {type(e).__name__}: {e!s}\n"
10221022
f" Displaying first and last {max_frames} stack frames out of {len(traceback)}."
10231023
)
10241024
# Type ignored because adding two instances of a List subtype

src/_pytest/_py/path.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -1105,9 +1105,7 @@ def pyimport(self, modname=None, ensuresyspath=True):
11051105
modname = self.purebasename
11061106
spec = importlib.util.spec_from_file_location(modname, str(self))
11071107
if spec is None or spec.loader is None:
1108-
raise ImportError(
1109-
f"Can't find module {modname} at location {str(self)}"
1110-
)
1108+
raise ImportError(f"Can't find module {modname} at location {self!s}")
11111109
mod = importlib.util.module_from_spec(spec)
11121110
spec.loader.exec_module(mod)
11131111
return mod

src/_pytest/assertion/rewrite.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ def visit_Assert(self, assert_: ast.Assert) -> List[ast.stmt]:
925925
# If any hooks implement assert_pass hook
926926
hook_impl_test = ast.If(
927927
self.helper("_check_if_assertion_pass_impl"),
928-
self.expl_stmts + [hook_call_pass],
928+
[*self.expl_stmts, hook_call_pass],
929929
[],
930930
)
931931
statements_pass = [hook_impl_test]

src/_pytest/assertion/truncate.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,8 @@ def _truncate_explanation(
9292
else:
9393
# Add proper ellipsis when we were able to fit a full line exactly
9494
truncated_explanation[-1] = "..."
95-
return truncated_explanation + [
95+
return [
96+
*truncated_explanation,
9697
"",
9798
f"...Full output truncated ({truncated_line_count} line"
9899
f"{'' if truncated_line_count == 1 else 's'} hidden), {USAGE_MSG}",

src/_pytest/assertion/util.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -233,8 +233,8 @@ def assertrepr_compare(
233233
return None
234234

235235
if explanation[0] != "":
236-
explanation = [""] + explanation
237-
return [summary] + explanation
236+
explanation = ["", *explanation]
237+
return [summary, *explanation]
238238

239239

240240
def _compare_eq_any(

src/_pytest/compat.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
# https://www.python.org/dev/peps/pep-0484/#support-for-singleton-types-in-unions
2828
class NotSetType(enum.Enum):
2929
token = 0
30-
NOTSET: Final = NotSetType.token # noqa: E305
30+
NOTSET: Final = NotSetType.token
3131
# fmt: on
3232

3333

src/_pytest/config/__init__.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ def directory_arg(path: str, optname: str) -> str:
238238
"helpconfig", # Provides -p.
239239
)
240240

241-
default_plugins = essential_plugins + (
241+
default_plugins = (
242+
*essential_plugins,
242243
"python",
243244
"terminal",
244245
"debugging",
@@ -671,7 +672,7 @@ def _importconftest(
671672
if dirpath in path.parents or path == dirpath:
672673
if mod in mods:
673674
raise AssertionError(
674-
f"While trying to load conftest path {str(conftestpath)}, "
675+
f"While trying to load conftest path {conftestpath!s}, "
675676
f"found that the module {mod} is already loaded with path {mod.__file__}. "
676677
"This is not supposed to happen. Please report this issue to pytest."
677678
)

src/_pytest/config/argparsing.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ def _getparser(self) -> "MyOptionParser":
122122
from _pytest._argcomplete import filescompleter
123123

124124
optparser = MyOptionParser(self, self.extra_info, prog=self.prog)
125-
groups = self._groups + [self._anonymous]
125+
groups = [*self._groups, self._anonymous]
126126
for group in groups:
127127
if group.options:
128128
desc = group.description or group.name

src/_pytest/fixtures.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1225,7 +1225,7 @@ def fixture(
12251225

12261226

12271227
@overload
1228-
def fixture( # noqa: F811
1228+
def fixture(
12291229
fixture_function: None = ...,
12301230
*,
12311231
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ...,
@@ -1239,7 +1239,7 @@ def fixture( # noqa: F811
12391239
...
12401240

12411241

1242-
def fixture( # noqa: F811
1242+
def fixture(
12431243
fixture_function: Optional[FixtureFunction] = None,
12441244
*,
12451245
scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function",
@@ -1673,7 +1673,7 @@ def parsefactories(
16731673
raise NotImplementedError()
16741674

16751675
@overload
1676-
def parsefactories( # noqa: F811
1676+
def parsefactories(
16771677
self,
16781678
node_or_obj: object,
16791679
nodeid: Optional[str],
@@ -1682,7 +1682,7 @@ def parsefactories( # noqa: F811
16821682
) -> None:
16831683
raise NotImplementedError()
16841684

1685-
def parsefactories( # noqa: F811
1685+
def parsefactories(
16861686
self,
16871687
node_or_obj: Union[nodes.Node, object],
16881688
nodeid: Union[str, NotSetType, None] = NOTSET,

src/_pytest/junitxml.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,7 @@ def record_func(name: str, value: object) -> None:
375375

376376
xml = request.config.stash.get(xml_key, None)
377377
if xml is not None:
378-
record_func = xml.add_global_property # noqa
378+
record_func = xml.add_global_property
379379
return record_func
380380

381381

src/_pytest/main.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -726,12 +726,12 @@ def perform_collect(
726726
...
727727

728728
@overload
729-
def perform_collect( # noqa: F811
729+
def perform_collect(
730730
self, args: Optional[Sequence[str]] = ..., genitems: bool = ...
731731
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
732732
...
733733

734-
def perform_collect( # noqa: F811
734+
def perform_collect(
735735
self, args: Optional[Sequence[str]] = None, genitems: bool = True
736736
) -> Sequence[Union[nodes.Item, nodes.Collector]]:
737737
"""Perform the collection phase for this session.

src/_pytest/mark/structures.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ def normalize_mark_list(
406406
for mark in mark_list:
407407
mark_obj = getattr(mark, "mark", mark)
408408
if not isinstance(mark_obj, Mark):
409-
raise TypeError(f"got {repr(mark_obj)} instead of Mark")
409+
raise TypeError(f"got {mark_obj!r} instead of Mark")
410410
yield mark_obj
411411

412412

src/_pytest/pytester.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ def inline_runsource(self, source: str, *cmdlineargs) -> HookRecorder:
10611061
:param cmdlineargs: Any extra command line arguments to use.
10621062
"""
10631063
p = self.makepyfile(source)
1064-
values = list(cmdlineargs) + [p]
1064+
values = [*list(cmdlineargs), p]
10651065
return self.inline_run(*values)
10661066

10671067
def inline_genitems(self, *args) -> Tuple[List[Item], HookRecorder]:
@@ -1491,10 +1491,10 @@ def runpytest_subprocess(
14911491
"""
14921492
__tracebackhide__ = True
14931493
p = make_numbered_dir(root=self.path, prefix="runpytest-", mode=0o700)
1494-
args = ("--basetemp=%s" % p,) + args
1494+
args = ("--basetemp=%s" % p, *args)
14951495
plugins = [x for x in self.plugins if isinstance(x, str)]
14961496
if plugins:
1497-
args = ("-p", plugins[0]) + args
1497+
args = ("-p", plugins[0], *args)
14981498
args = self._getpytestargs() + args
14991499
return self.run(*args, timeout=timeout)
15001500

src/_pytest/python.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ def reportinfo(self) -> Tuple[Union["os.PathLike[str]", str], Optional[int], str
358358
# hook is not called for them.
359359
# fmt: off
360360
class _EmptyClass: pass # noqa: E701
361-
IGNORED_ATTRIBUTES = frozenset.union( # noqa: E305
361+
IGNORED_ATTRIBUTES = frozenset.union(
362362
frozenset(),
363363
# Module.
364364
dir(types.ModuleType("empty_module")),

src/_pytest/python_api.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -730,7 +730,7 @@ def approx(expected, rel=None, abs=None, nan_ok: bool = False) -> ApproxBase:
730730
# Type ignored because the error is wrong -- not unreachable.
731731
and not isinstance(expected, STRING_TYPES) # type: ignore[unreachable]
732732
):
733-
msg = f"pytest.approx() only supports ordered sequences, but got: {repr(expected)}"
733+
msg = f"pytest.approx() only supports ordered sequences, but got: {expected!r}"
734734
raise TypeError(msg)
735735
else:
736736
cls = ApproxScalar
@@ -780,7 +780,7 @@ def raises(
780780

781781

782782
@overload
783-
def raises( # noqa: F811
783+
def raises(
784784
expected_exception: Union[Type[E], Tuple[Type[E], ...]],
785785
func: Callable[..., Any],
786786
*args: Any,
@@ -789,7 +789,7 @@ def raises( # noqa: F811
789789
...
790790

791791

792-
def raises( # noqa: F811
792+
def raises(
793793
expected_exception: Union[Type[E], Tuple[Type[E], ...]], *args: Any, **kwargs: Any
794794
) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]:
795795
r"""Assert that a code block/function call raises an exception type, or one of its subclasses.

src/_pytest/recwarn.py

+5-7
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,11 @@ def deprecated_call(
4747

4848

4949
@overload
50-
def deprecated_call( # noqa: F811
51-
func: Callable[..., T], *args: Any, **kwargs: Any
52-
) -> T:
50+
def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T:
5351
...
5452

5553

56-
def deprecated_call( # noqa: F811
54+
def deprecated_call(
5755
func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any
5856
) -> Union["WarningsRecorder", Any]:
5957
"""Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning`` or ``FutureWarning``.
@@ -81,7 +79,7 @@ def deprecated_call( # noqa: F811
8179
"""
8280
__tracebackhide__ = True
8381
if func is not None:
84-
args = (func,) + args
82+
args = (func, *args)
8583
return warns(
8684
(DeprecationWarning, PendingDeprecationWarning, FutureWarning), *args, **kwargs
8785
)
@@ -97,7 +95,7 @@ def warns(
9795

9896

9997
@overload
100-
def warns( # noqa: F811
98+
def warns(
10199
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]],
102100
func: Callable[..., T],
103101
*args: Any,
@@ -106,7 +104,7 @@ def warns( # noqa: F811
106104
...
107105

108106

109-
def warns( # noqa: F811
107+
def warns(
110108
expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning,
111109
*args: Any,
112110
match: Optional[Union[str, Pattern[str]]] = None,

testing/_py/test_local.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
def ignore_encoding_warning():
1818
with warnings.catch_warnings():
1919
with contextlib.suppress(NameError): # new in 3.10
20-
warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined] # noqa: F821
20+
warnings.simplefilter("ignore", EncodingWarning) # type: ignore [name-defined]
2121
yield
2222

2323

testing/code/test_excinfo.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1739,7 +1739,7 @@ def test():
17391739
def add_note(err: BaseException, msg: str) -> None:
17401740
"""Adds a note to an exception inplace."""
17411741
if sys.version_info < (3, 11):
1742-
err.__notes__ = getattr(err, "__notes__", []) + [msg] # type: ignore[attr-defined]
1742+
err.__notes__ = [*getattr(err, "__notes__", []), msg] # type: ignore[attr-defined]
17431743
else:
17441744
err.add_note(msg)
17451745

testing/freeze/create_executable.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,5 @@
99
for x in pytest.freeze_includes():
1010
hidden.extend(["--hidden-import", x])
1111
hidden.extend(["--hidden-import", "distutils"])
12-
args = ["pyinstaller", "--noconfirm"] + hidden + ["runtests_script.py"]
12+
args = ["pyinstaller", "--noconfirm", *hidden, "runtests_script.py"]
1313
subprocess.check_call(" ".join(args), shell=True)

testing/io/test_wcwidth.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
("\u1ABE", 0),
1616
("\u0591", 0),
1717
("🉐", 2),
18-
("$", 2),
18+
("$", 2), # noqa: RUF001
1919
],
2020
)
2121
def test_wcwidth(c: str, expected: int) -> None:

testing/logging/test_reporting.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1032,7 +1032,7 @@ def test_log_set_path(pytester: Pytester) -> None:
10321032
def pytest_runtest_setup(item):
10331033
config = item.config
10341034
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
1035-
report_file = os.path.join({repr(report_dir_base)}, item._request.node.name)
1035+
report_file = os.path.join({report_dir_base!r}, item._request.node.name)
10361036
logging_plugin.set_log_path(report_file)
10371037
return (yield)
10381038
"""

testing/python/collect.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1209,7 +1209,7 @@ def test_bar(self):
12091209
classcol = pytester.collect_by_name(modcol, "TestClass")
12101210
assert isinstance(classcol, Class)
12111211
path, lineno, msg = classcol.reportinfo()
1212-
func = list(classcol.collect())[0]
1212+
func = next(iter(classcol.collect()))
12131213
assert isinstance(func, Function)
12141214
path, lineno, msg = func.reportinfo()
12151215

testing/python/fixtures.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -3086,7 +3086,7 @@ def test_baz(base, fix2):
30863086
def test_other():
30873087
pass
30883088
""" # noqa: UP031 (python syntax issues)
3089-
% {"scope": scope} # noqa: UP031 (python syntax issues)
3089+
% {"scope": scope}
30903090
)
30913091
reprec = pytester.inline_run("-lvs")
30923092
reprec.assertoutcome(passed=3)
@@ -4536,5 +4536,5 @@ def test_fixt(custom):
45364536
def test_deduplicate_names() -> None:
45374537
items = deduplicate_names("abacd")
45384538
assert items == ("a", "b", "c", "d")
4539-
items = deduplicate_names(items + ("g", "f", "g", "e", "b"))
4539+
items = deduplicate_names((*items, "g", "f", "g", "e", "b"))
45404540
assert items == ("a", "b", "c", "d", "g", "f", "e")

testing/python/raises.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -147,15 +147,15 @@ def test_no_raise_message(self) -> None:
147147
try:
148148
pytest.raises(ValueError, int, "0")
149149
except pytest.fail.Exception as e:
150-
assert e.msg == f"DID NOT RAISE {repr(ValueError)}"
150+
assert e.msg == f"DID NOT RAISE {ValueError!r}"
151151
else:
152152
assert False, "Expected pytest.raises.Exception"
153153

154154
try:
155155
with pytest.raises(ValueError):
156156
pass
157157
except pytest.fail.Exception as e:
158-
assert e.msg == f"DID NOT RAISE {repr(ValueError)}"
158+
assert e.msg == f"DID NOT RAISE {ValueError!r}"
159159
else:
160160
assert False, "Expected pytest.raises.Exception"
161161

testing/test_assertion.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -914,16 +914,16 @@ def test_nfc_nfd_same_string(self) -> None:
914914
assert expl == [
915915
r"'hyv\xe4' == 'hyva\u0308'",
916916
"",
917-
f"- {str(right)}",
918-
f"+ {str(left)}",
917+
f"- {right!s}",
918+
f"+ {left!s}",
919919
]
920920

921921
expl = callequal(left, right, verbose=2)
922922
assert expl == [
923923
r"'hyv\xe4' == 'hyva\u0308'",
924924
"",
925-
f"- {str(right)}",
926-
f"+ {str(left)}",
925+
f"- {right!s}",
926+
f"+ {left!s}",
927927
]
928928

929929

@@ -1149,7 +1149,7 @@ class SimpleDataObjectTwo:
11491149
def test_attrs_with_auto_detect_and_custom_eq(self) -> None:
11501150
@attr.s(
11511151
auto_detect=True
1152-
) # attr.s doesnt ignore a custom eq if auto_detect=True
1152+
) # attr.s doesn't ignore a custom eq if auto_detect=True
11531153
class SimpleDataObject:
11541154
field_a = attr.ib()
11551155

0 commit comments

Comments
 (0)