Skip to content

Commit e087e3f

Browse files
Merge pull request #13009 from pytest-dev/pre-commit-ci-update-config
Upgrade ruff to 0.8.1 and fix existing issues
2 parents d65d991 + 17c5bbb commit e087e3f

30 files changed

+112
-136
lines changed

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/astral-sh/ruff-pre-commit
3-
rev: "v0.7.4"
3+
rev: "v0.8.1"
44
hooks:
55
- id: ruff
66
args: ["--fix"]

bench/empty.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33

44
for i in range(1000):
5-
exec("def test_func_%d(): pass" % i)
5+
exec(f"def test_func_{i}(): pass")

src/_pytest/_code/__init__.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,11 @@
1616
__all__ = [
1717
"Code",
1818
"ExceptionInfo",
19-
"filter_traceback",
2019
"Frame",
21-
"getfslineno",
22-
"getrawcode",
20+
"Source",
2321
"Traceback",
2422
"TracebackEntry",
25-
"Source",
23+
"filter_traceback",
24+
"getfslineno",
25+
"getrawcode",
2626
]

src/_pytest/_code/code.py

+6-13
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@ def relline(self) -> int:
217217
return self.lineno - self.frame.code.firstlineno
218218

219219
def __repr__(self) -> str:
220-
return "<TracebackEntry %s:%d>" % (self.frame.code.path, self.lineno + 1)
220+
return f"<TracebackEntry {self.frame.code.path}:{self.lineno+1}>"
221221

222222
@property
223223
def statement(self) -> Source:
@@ -303,12 +303,7 @@ def __str__(self) -> str:
303303
# This output does not quite match Python's repr for traceback entries,
304304
# but changing it to do so would break certain plugins. See
305305
# https://github.com/pytest-dev/pytest/pull/7535/ for details.
306-
return " File %r:%d in %s\n %s\n" % (
307-
str(self.path),
308-
self.lineno + 1,
309-
name,
310-
line,
311-
)
306+
return f" File '{self.path}':{self.lineno+1} in {name}\n {line}\n"
312307

313308
@property
314309
def name(self) -> str:
@@ -953,7 +948,7 @@ def repr_traceback_entry(
953948
if short:
954949
message = f"in {entry.name}"
955950
else:
956-
message = excinfo and excinfo.typename or ""
951+
message = (excinfo and excinfo.typename) or ""
957952
entry_path = entry.path
958953
path = self._makepath(entry_path)
959954
reprfileloc = ReprFileLocation(path, entry.lineno + 1, message)
@@ -1182,10 +1177,8 @@ def toterminal(self, tw: TerminalWriter) -> None:
11821177
entry.toterminal(tw)
11831178
if i < len(self.reprentries) - 1:
11841179
next_entry = self.reprentries[i + 1]
1185-
if (
1186-
entry.style == "long"
1187-
or entry.style == "short"
1188-
and next_entry.style == "long"
1180+
if entry.style == "long" or (
1181+
entry.style == "short" and next_entry.style == "long"
11891182
):
11901183
tw.sep(self.entrysep)
11911184

@@ -1369,7 +1362,7 @@ def getfslineno(obj: object) -> tuple[str | Path, int]:
13691362
except TypeError:
13701363
return "", -1
13711364

1372-
fspath = fn and absolutepath(fn) or ""
1365+
fspath = (fn and absolutepath(fn)) or ""
13731366
lineno = -1
13741367
if fspath:
13751368
try:

src/_pytest/_io/pprint.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ def _pprint_deque(
540540
) -> None:
541541
stream.write(object.__class__.__name__ + "(")
542542
if object.maxlen is not None:
543-
stream.write("maxlen=%d, " % object.maxlen)
543+
stream.write(f"maxlen={object.maxlen}, ")
544544
stream.write("[")
545545

546546
self._format_items(object, stream, indent, allowance + 1, context, level)

src/_pytest/_py/error.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def _geterrnoclass(self, eno: int) -> type[Error]:
6969
try:
7070
return self._errno2class[eno]
7171
except KeyError:
72-
clsname = errno.errorcode.get(eno, "UnknownErrno%d" % (eno,))
72+
clsname = errno.errorcode.get(eno, f"UnknownErrno{eno}")
7373
errorcls = type(
7474
clsname,
7575
(Error,),

src/_pytest/assertion/rewrite.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class Sentinel:
5353

5454
# pytest caches rewritten pycs in pycache dirs
5555
PYTEST_TAG = f"{sys.implementation.cache_tag}-pytest-{version}"
56-
PYC_EXT = ".py" + (__debug__ and "c" or "o")
56+
PYC_EXT = ".py" + ((__debug__ and "c") or "o")
5757
PYC_TAIL = "." + PYTEST_TAG + PYC_EXT
5858

5959
# Special marker that denotes we have just left a scope definition
@@ -481,7 +481,7 @@ def _should_repr_global_name(obj: object) -> bool:
481481

482482

483483
def _format_boolop(explanations: Iterable[str], is_or: bool) -> str:
484-
explanation = "(" + (is_or and " or " or " and ").join(explanations) + ")"
484+
explanation = "(" + ((is_or and " or ") or " and ").join(explanations) + ")"
485485
return explanation.replace("%", "%%")
486486

487487

src/_pytest/assertion/util.py

+3-6
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,7 @@ def _compare_eq_sequence(
406406
]
407407
else:
408408
explanation += [
409-
"%s contains %d more items, first extra item: %s"
410-
% (dir_with_more, len_diff, highlighter(extra))
409+
f"{dir_with_more} contains {len_diff} more items, first extra item: {highlighter(extra)}"
411410
]
412411
return explanation
413412

@@ -510,8 +509,7 @@ def _compare_eq_dict(
510509
len_extra_left = len(extra_left)
511510
if len_extra_left:
512511
explanation.append(
513-
"Left contains %d more item%s:"
514-
% (len_extra_left, "" if len_extra_left == 1 else "s")
512+
f"Left contains {len_extra_left} more item{'' if len_extra_left == 1 else 's'}:"
515513
)
516514
explanation.extend(
517515
highlighter(pprint.pformat({k: left[k] for k in extra_left})).splitlines()
@@ -520,8 +518,7 @@ def _compare_eq_dict(
520518
len_extra_right = len(extra_right)
521519
if len_extra_right:
522520
explanation.append(
523-
"Right contains %d more item%s:"
524-
% (len_extra_right, "" if len_extra_right == 1 else "s")
521+
f"Right contains {len_extra_right} more item{'' if len_extra_right == 1 else 's'}:"
525522
)
526523
explanation.extend(
527524
highlighter(pprint.pformat({k: right[k] for k in extra_right})).splitlines()

src/_pytest/cacheprovider.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -388,8 +388,8 @@ def pytest_collection_modifyitems(
388388
if not previously_failed:
389389
# Running a subset of all tests with recorded failures
390390
# only outside of it.
391-
self._report_status = "%d known failures not in selected tests" % (
392-
len(self.lastfailed),
391+
self._report_status = (
392+
f"{len(self.lastfailed)} known failures not in selected tests"
393393
)
394394
else:
395395
if self.config.getoption("lf"):
@@ -622,5 +622,5 @@ def cacheshow(config: Config, session: Session) -> int:
622622
# print("%s/" % p.relative_to(basedir))
623623
if p.is_file():
624624
key = str(p.relative_to(basedir))
625-
tw.line(f"{key} is a file of length {p.stat().st_size:d}")
625+
tw.line(f"{key} is a file of length {p.stat().st_size}")
626626
return 0

src/_pytest/capture.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,7 @@ def repr(self, class_name: str) -> str:
360360
return "<{} {} _old={} _state={!r} tmpfile={!r}>".format(
361361
class_name,
362362
self.name,
363-
hasattr(self, "_old") and repr(self._old) or "<UNSET>",
363+
(hasattr(self, "_old") and repr(self._old)) or "<UNSET>",
364364
self._state,
365365
self.tmpfile,
366366
)
@@ -369,7 +369,7 @@ def __repr__(self) -> str:
369369
return "<{} {} _old={} _state={!r} tmpfile={!r}>".format(
370370
self.__class__.__name__,
371371
self.name,
372-
hasattr(self, "_old") and repr(self._old) or "<UNSET>",
372+
(hasattr(self, "_old") and repr(self._old)) or "<UNSET>",
373373
self._state,
374374
self.tmpfile,
375375
)

src/_pytest/compat.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,8 @@ def getlocation(function, curdir: str | os.PathLike[str] | None = None) -> str:
7171
except ValueError:
7272
pass
7373
else:
74-
return "%s:%d" % (relfn, lineno + 1)
75-
return "%s:%d" % (fn, lineno + 1)
74+
return f"{relfn}:{lineno+1}"
75+
return f"{fn}:{lineno+1}"
7676

7777

7878
def num_mock_patch_args(function) -> int:

src/_pytest/doctest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -353,7 +353,7 @@ def repr_failure( # type: ignore[override]
353353
# add line numbers to the left of the error message
354354
assert test.lineno is not None
355355
lines = [
356-
"%03d %s" % (i + test.lineno + 1, x) for (i, x) in enumerate(lines)
356+
f"{i + test.lineno + 1:03d} {x}" for (i, x) in enumerate(lines)
357357
]
358358
# trim docstring error lines to 10
359359
lines = lines[max(example.lineno - 9, 0) : example.lineno + 1]

src/_pytest/fixtures.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ class FuncFixtureInfo:
305305
these are not reflected here.
306306
"""
307307

308-
__slots__ = ("argnames", "initialnames", "names_closure", "name2fixturedefs")
308+
__slots__ = ("argnames", "initialnames", "name2fixturedefs", "names_closure")
309309

310310
# Fixture names that the item requests directly by function parameters.
311311
argnames: tuple[str, ...]
@@ -884,7 +884,7 @@ def toterminal(self, tw: TerminalWriter) -> None:
884884
red=True,
885885
)
886886
tw.line()
887-
tw.line("%s:%d" % (os.fspath(self.filename), self.firstlineno + 1))
887+
tw.line(f"{os.fspath(self.filename)}:{self.firstlineno + 1}")
888888

889889

890890
def call_fixture_func(

src/_pytest/main.py

+8-10
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,7 @@ def pytest_collection(session: Session) -> None:
349349
def pytest_runtestloop(session: Session) -> bool:
350350
if session.testsfailed and not session.config.option.continue_on_collection_errors:
351351
raise session.Interrupted(
352-
"%d error%s during collection"
353-
% (session.testsfailed, "s" if session.testsfailed != 1 else "")
352+
f"{session.testsfailed} error{'s' if session.testsfailed != 1 else ''} during collection"
354353
)
355354

356355
if session.config.option.collectonly:
@@ -585,13 +584,12 @@ def from_config(cls, config: Config) -> Session:
585584
return session
586585

587586
def __repr__(self) -> str:
588-
return "<%s %s exitstatus=%r testsfailed=%d testscollected=%d>" % (
589-
self.__class__.__name__,
590-
self.name,
591-
getattr(self, "exitstatus", "<UNSET>"),
592-
self.testsfailed,
593-
self.testscollected,
594-
)
587+
return (
588+
f"<{self.__class__.__name__} {self.name} "
589+
f"exitstatus=%r "
590+
f"testsfailed={self.testsfailed} "
591+
f"testscollected={self.testscollected}>"
592+
) % getattr(self, "exitstatus", "<UNSET>")
595593

596594
@property
597595
def shouldstop(self) -> bool | str:
@@ -654,7 +652,7 @@ def pytest_runtest_logreport(self, report: TestReport | CollectReport) -> None:
654652
self.testsfailed += 1
655653
maxfail = self.config.getvalue("maxfail")
656654
if maxfail and self.testsfailed >= maxfail:
657-
self.shouldfail = "stopping after %d failures" % (self.testsfailed)
655+
self.shouldfail = f"stopping after {self.testsfailed} failures"
658656

659657
pytest_collectreport = pytest_runtest_logreport
660658

src/_pytest/mark/expression.py

+4-6
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ class TokenType(enum.Enum):
5858

5959
@dataclasses.dataclass(frozen=True)
6060
class Token:
61-
__slots__ = ("type", "value", "pos")
61+
__slots__ = ("pos", "type", "value")
6262
type: TokenType
6363
value: str
6464
pos: int
@@ -80,7 +80,7 @@ def __str__(self) -> str:
8080

8181

8282
class Scanner:
83-
__slots__ = ("tokens", "current")
83+
__slots__ = ("current", "tokens")
8484

8585
def __init__(self, input: str) -> None:
8686
self.tokens = self.lex(input)
@@ -238,10 +238,8 @@ def single_kwarg(s: Scanner) -> ast.keyword:
238238
value: str | int | bool | None = value_token.value[1:-1] # strip quotes
239239
else:
240240
value_token = s.accept(TokenType.IDENT, reject=True)
241-
if (
242-
(number := value_token.value).isdigit()
243-
or number.startswith("-")
244-
and number[1:].isdigit()
241+
if (number := value_token.value).isdigit() or (
242+
number.startswith("-") and number[1:].isdigit()
245243
):
246244
value = int(number)
247245
elif value_token.value in BUILTIN_MATCHERS:

src/_pytest/mark/structures.py

+5-13
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,7 @@ def get_empty_parameterset_mark(
4848
from ..nodes import Collector
4949

5050
fs, lineno = getfslineno(func)
51-
reason = "got empty parameter set %r, function %s at %s:%d" % (
52-
argnames,
53-
func.__name__,
54-
fs,
55-
lineno,
56-
)
57-
51+
reason = f"got empty parameter set {argnames!r}, function {func.__name__} at {fs}:{lineno}"
5852
requested_mark = config.getini(EMPTY_PARAMETERSET_OPTION)
5953
if requested_mark in ("", None, "skip"):
6054
mark = MARK_GEN.skip(reason=reason)
@@ -64,7 +58,7 @@ def get_empty_parameterset_mark(
6458
f_name = func.__name__
6559
_, lineno = getfslineno(func)
6660
raise Collector.CollectError(
67-
"Empty parameter set in '%s' at line %d" % (f_name, lineno + 1)
61+
f"Empty parameter set in '{f_name}' at line {lineno + 1}"
6862
)
6963
else:
7064
raise LookupError(requested_mark)
@@ -562,7 +556,7 @@ def __getattr__(self, name: str) -> MarkDecorator:
562556

563557
@final
564558
class NodeKeywords(MutableMapping[str, Any]):
565-
__slots__ = ("node", "parent", "_markers")
559+
__slots__ = ("_markers", "node", "parent")
566560

567561
def __init__(self, node: Node) -> None:
568562
self.node = node
@@ -584,10 +578,8 @@ def __setitem__(self, key: str, value: Any) -> None:
584578
# below and use the collections.abc fallback, but that would be slow.
585579

586580
def __contains__(self, key: object) -> bool:
587-
return (
588-
key in self._markers
589-
or self.parent is not None
590-
and key in self.parent.keywords
581+
return key in self._markers or (
582+
self.parent is not None and key in self.parent.keywords
591583
)
592584

593585
def update( # type: ignore[override]

src/_pytest/nodes.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -143,14 +143,14 @@ class Node(abc.ABC, metaclass=NodeMeta):
143143
# Use __slots__ to make attribute access faster.
144144
# Note that __dict__ is still available.
145145
__slots__ = (
146+
"__dict__",
147+
"_nodeid",
148+
"_store",
149+
"config",
146150
"name",
147151
"parent",
148-
"config",
149-
"session",
150152
"path",
151-
"_nodeid",
152-
"_store",
153-
"__dict__",
153+
"session",
154154
)
155155

156156
def __init__(

src/_pytest/pytester.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -547,8 +547,10 @@ def __init__(
547547

548548
def __repr__(self) -> str:
549549
return (
550-
"<RunResult ret=%s len(stdout.lines)=%d len(stderr.lines)=%d duration=%.2fs>"
551-
% (self.ret, len(self.stdout.lines), len(self.stderr.lines), self.duration)
550+
f"<RunResult ret={self.ret!s} "
551+
f"len(stdout.lines)={len(self.stdout.lines)} "
552+
f"len(stderr.lines)={len(self.stderr.lines)} "
553+
f"duration={self.duration:.2f}s>"
552554
)
553555

554556
def parseoutcomes(self) -> dict[str, int]:

src/_pytest/python.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,7 @@ def _genfunctions(self, name: str, funcobj) -> Iterator[Function]:
431431
assert modulecol is not None
432432
module = modulecol.obj
433433
clscol = self.getparent(Class)
434-
cls = clscol and clscol.obj or None
434+
cls = (clscol and clscol.obj) or None
435435

436436
definition = FunctionDefinition.from_parent(self, name=name, callobj=funcobj)
437437
fixtureinfo = definition._fixtureinfo
@@ -848,12 +848,12 @@ class IdMaker:
848848

849849
__slots__ = (
850850
"argnames",
851-
"parametersets",
851+
"config",
852+
"func_name",
852853
"idfn",
853854
"ids",
854-
"config",
855855
"nodeid",
856-
"func_name",
856+
"parametersets",
857857
)
858858

859859
# The argnames of the parametrization.

0 commit comments

Comments
 (0)