From ee012145f97ba593685f9f322ee51fbc396cf8ef Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 27 Feb 2026 10:17:14 +0100 Subject: [PATCH 1/5] [pre-commit] Fix the version of pyproject-fmt by using our fork --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d53253810c5..dcae1c110c0 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -67,7 +67,7 @@ repos: - exceptiongroup>=1.0.0rc8 # Manual because passing pyright is a work in progress. stages: [manual] -- repo: https://github.com/tox-dev/pyproject-fmt +- repo: https://github.com/pytest-dev/pyproject-fmt rev: "v2.12.1" hooks: - id: pyproject-fmt From d996e4d4e8962e8082e8fdf20359426b5280679a Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 13 Feb 2026 08:22:07 +0100 Subject: [PATCH 2/5] [ruff] Upgrade ruff to 0.15.4 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/astral-sh/ruff-pre-commit: v0.14.14 → v0.15.4](https://github.com/astral-sh/ruff-pre-commit/compare/v0.14.14...v0.15.4) --- .pre-commit-config.yaml | 2 +- pyproject.toml | 3 +++ src/_pytest/config/findpaths.py | 2 +- src/_pytest/terminal.py | 6 ++++-- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dcae1c110c0..00f62a76551 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ minimum_pre_commit_version: "4.4.0" repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: "v0.14.14" + rev: "v0.15.4" hooks: - id: ruff-check args: ["--fix"] diff --git a/pyproject.toml b/pyproject.toml index 7ae76a3c8dd..7b6c5a157ad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -155,12 +155,14 @@ lint.ignore = [ "PLR2004", # Magic value used in comparison "PLR2044", # Line with empty comment "PLR5501", # Use `elif` instead of `else` then `if` + "PLW0108", # Lambda may be unnecessary; consider inlining inner function "PLW0120", # remove the else and dedent its contents "PLW0603", # Using the global statement "PLW1641", # Does not implement the __hash__ method "PLW2901", # for loop variable overwritten by assignment target # ruff ignore "RUF012", # Mutable class attributes should be annotated with `typing.ClassVar` + "RUF061", # Use context-manager form of `pytest.raises()` ] lint.per-file-ignores."src/_pytest/_py/**/*.py" = [ "B", @@ -169,6 +171,7 @@ lint.per-file-ignores."src/_pytest/_py/**/*.py" = [ lint.per-file-ignores."src/_pytest/_version.py" = [ "I001", ] +lint.per-file-ignores."testing/**/*.py" = [ "RUF060" ] # can't be disabled on a line-by-line basis in file lint.per-file-ignores."testing/code/test_source.py" = [ "F841", diff --git a/src/_pytest/config/findpaths.py b/src/_pytest/config/findpaths.py index 3c628a09c2d..e74546c6e28 100644 --- a/src/_pytest/config/findpaths.py +++ b/src/_pytest/config/findpaths.py @@ -233,7 +233,7 @@ def is_option(x: str) -> bool: return x.startswith("-") def get_file_part_from_node_id(x: str) -> str: - return x.split("::")[0] + return x.split("::", maxsplit=1)[0] def get_dir_from_path(path: Path) -> Path: if path.is_dir(): diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index bb6f35633b9..1a4b6f20b44 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -476,7 +476,7 @@ def hasopt(self, char: str) -> bool: return char in self.reportchars def write_fspath_result(self, nodeid: str, res: str, **markup: bool) -> None: - fspath = self.config.rootpath / nodeid.split("::")[0] + fspath = self.config.rootpath / nodeid.split("::", maxsplit=1)[0] if self.currentfspath is None or fspath != self.currentfspath: if self.currentfspath is not None and self._show_progress_info: self._write_progress_information_filling_space() @@ -1034,7 +1034,9 @@ def mkrel(nodeid: str) -> str: # fspath comes from testid which has a "/"-normalized path. if fspath: res = mkrel(nodeid) - if self.verbosity >= 2 and nodeid.split("::")[0] != nodes.norm_sep(fspath): + if self.verbosity >= 2 and nodeid.split("::", maxsplit=1)[ + 0 + ] != nodes.norm_sep(fspath): res += " <- " + bestrelpath(self.startpath, Path(fspath)) else: res = "[location]" From bcb3366fe9bf1fe2ad08f33dddc241c01a8cb3e4 Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 13 Feb 2026 08:05:11 +0100 Subject: [PATCH 3/5] [ruff-fmt] Nudge the auto-formatter to properly separate lines --- src/_pytest/terminal.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/_pytest/terminal.py b/src/_pytest/terminal.py index 1a4b6f20b44..e9049bb82ec 100644 --- a/src/_pytest/terminal.py +++ b/src/_pytest/terminal.py @@ -1034,9 +1034,9 @@ def mkrel(nodeid: str) -> str: # fspath comes from testid which has a "/"-normalized path. if fspath: res = mkrel(nodeid) - if self.verbosity >= 2 and nodeid.split("::", maxsplit=1)[ - 0 - ] != nodes.norm_sep(fspath): + if self.verbosity >= 2 and ( + nodeid.split("::", maxsplit=1)[0] != nodes.norm_sep(fspath) + ): res += " <- " + bestrelpath(self.startpath, Path(fspath)) else: res = "[location]" From 37f56da6d39ad2f75497fb21d0372d090957aeae Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Tue, 10 Feb 2026 15:36:50 +0100 Subject: [PATCH 4/5] [lint] PLW0108: lambda used to correctly get the mocked time via `MockTiming` --- pyproject.toml | 1 - src/_pytest/timing.py | 5 +++-- testing/_py/test_local.py | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7b6c5a157ad..317279450c8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -155,7 +155,6 @@ lint.ignore = [ "PLR2004", # Magic value used in comparison "PLR2044", # Line with empty comment "PLR5501", # Use `elif` instead of `else` then `if` - "PLW0108", # Lambda may be unnecessary; consider inlining inner function "PLW0120", # remove the else and dedent its contents "PLW0603", # Using the global statement "PLW1641", # Does not implement the __hash__ method diff --git a/src/_pytest/timing.py b/src/_pytest/timing.py index 51c3db23f6f..232e2e38464 100644 --- a/src/_pytest/timing.py +++ b/src/_pytest/timing.py @@ -32,12 +32,13 @@ class Instant: # Creation time of this instant, using time.time(), to measure actual time. # Note: using a `lambda` to correctly get the mocked time via `MockTiming`. - time: float = dataclasses.field(default_factory=lambda: time(), init=False) + time: float = dataclasses.field(default_factory=lambda: time(), init=False) # noqa: PLW0108 # Performance counter tick of the instant, used to measure precise elapsed time. # Note: using a `lambda` to correctly get the mocked time via `MockTiming`. perf_count: float = dataclasses.field( - default_factory=lambda: perf_counter(), init=False + default_factory=lambda: perf_counter(), # noqa: PLW0108 + init=False, ) def elapsed(self) -> Duration: diff --git a/testing/_py/test_local.py b/testing/_py/test_local.py index 6b7d756a45c..c32e71f6542 100644 --- a/testing/_py/test_local.py +++ b/testing/_py/test_local.py @@ -1388,7 +1388,7 @@ def test_stat_helpers(self, tmpdir, monkeypatch): def test_stat_non_raising(self, tmpdir): path1 = tmpdir.join("file") - pytest.raises(error.ENOENT, lambda: path1.stat()) + pytest.raises(error.ENOENT, path1.stat) res = path1.stat(raising=False) assert res is None From c6e3a59c4e096a448e1765acac259fd1588b637f Mon Sep 17 00:00:00 2001 From: Pierre Sassoulas Date: Fri, 13 Feb 2026 08:33:27 +0100 Subject: [PATCH 5/5] [pylint] sort the disable alphabetically, remove duplicate --- pyproject.toml | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 317279450c8..1968870ed13 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -219,31 +219,30 @@ disable = [ "comparison-with-callable", "comparison-with-itself", # PLR0124 from ruff "condition-evals-to-constant", - "consider-alternative-union-syntax", "confusing-consecutive-elif", + "consider-alternative-union-syntax", + "consider-ternary-expression", "consider-using-assignment-expr", "consider-using-dict-items", - "consider-using-from-import", + "consider-using-from-import", # not activated by default, PLR0402 disabled in ruff "consider-using-f-string", "consider-using-in", "consider-using-namedtuple-or-dataclass", "consider-using-ternary", "consider-using-tuple", "consider-using-with", - "consider-using-from-import", # not activated by default, PLR0402 disabled in ruff - "consider-ternary-expression", "cyclic-import", - "differing-param-doc", - "docstring-first-line-empty", "deprecated-argument", "deprecated-attribute", "deprecated-class", + "differing-param-doc", "disallowed-name", # foo / bar are used often in tests + "docstring-first-line-empty", "duplicate-code", "else-if-used", # not activated by default, PLR5501 disabled in ruff "empty-comment", # not activated by default, PLR2044 disabled in ruff - "eval-used", "eq-without-hash", # PLW1641 disabled in ruff + "eval-used", "exec-used", "expression-not-assigned", "fixme", @@ -260,13 +259,13 @@ disable = [ "line-too-long", "magic-value-comparison", # not activated by default, PLR2004 disabled in ruff "method-hidden", + "misplaced-bare-raise", # PLE0704 from ruff + "misplaced-comparison-constant", "missing-docstring", "missing-param-doc", "missing-raises-doc", "missing-timeout", "missing-type-doc", - "misplaced-bare-raise", # PLE0704 from ruff - "misplaced-comparison-constant", "multiple-statements", # multiple-statements-on-one-line-colon (E701) from ruff "no-else-break", "no-else-continue", @@ -331,10 +330,10 @@ disable = [ "use-dict-literal", "use-implicit-booleaness-not-comparison", "use-implicit-booleaness-not-len", - "use-set-for-membership", "useless-else-on-loop", # PLC0414 disabled in ruff "useless-import-alias", "useless-return", + "use-set-for-membership", "using-constant-test", "while-used", "wrong-import-order", # handled by isort / ruff