chore(deps): update pre-commit hooks (#6126)
* chore(deps): update pre-commit hooks
updates:
- [github.com/pre-commit/mirrors-clang-format: v22.1.5 → v22.1.8](https://github.com/pre-commit/mirrors-clang-format/compare/v22.1.5...v22.1.8)
- [github.com/astral-sh/ruff-pre-commit: v0.15.20 → v0.16.1](https://github.com/astral-sh/ruff-pre-commit/compare/v0.15.20...v0.16.1)
- [github.com/pre-commit/mirrors-mypy: v2.1.0 → v2.3.0](https://github.com/pre-commit/mirrors-mypy/compare/v2.1.0...v2.3.0)
- [github.com/codespell-project/codespell: v2.4.2 → v2.4.3](https://github.com/codespell-project/codespell/compare/v2.4.2...v2.4.3)
* style: pre-commit fixes
* fix: adapt to the ruff 0.16 default rule set
The hook update pulled in ruff 0.16, which expanded its default rules and
autofixed `self: S -> S` to `-> Self`. That fix added a runtime
`typing_extensions` import to setup_helpers.py, which must stay
dependency-free; it broke every test job whose environment does not supply
that package. The import is now guarded by TYPE_CHECKING.
Also replace the `exec` in docs/conf.py with an importlib module load,
parenthesize implicit string concatenations in list literals, mark unused
unpacked variables with a leading underscore, and make noxfile.py
executable to match its shebang.
The remaining new rules are silenced per-file, with reasons: the chrono
tests check naive local time on purpose, and the other rules conflict with
how the tests are written.
Assisted-by: ClaudeCode:claude-opus-5
---------
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Henry Schreiner <henryfs@princeton.edu>
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index aff6954..1934c2d 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -25,14 +25,14 @@
# Clang format the codebase automatically
- repo: https://github.com/pre-commit/mirrors-clang-format
- rev: "v22.1.5"
+ rev: "v22.1.8"
hooks:
- id: clang-format
types_or: [c++, c, cuda]
# Ruff, the Python auto-correcting linter/formatter written in Rust
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.15.20
+ rev: v0.16.1
hooks:
- id: ruff-check
args: ["--fix", "--show-fixes"]
@@ -40,7 +40,7 @@
# Check static types with mypy
- repo: https://github.com/pre-commit/mirrors-mypy
- rev: "v2.1.0"
+ rev: "v2.3.0"
hooks:
- id: mypy
args: []
@@ -112,7 +112,7 @@
# Use tools/codespell_ignore_lines_from_errors.py
# to rebuild .codespell-ignore-lines
- repo: https://github.com/codespell-project/codespell
- rev: "v2.4.2"
+ rev: "v2.4.3"
hooks:
- id: codespell
exclude: "(.supp|^pyproject.toml)$"
diff --git a/docs/conf.py b/docs/conf.py
index 5f216bf..481e04c 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python3
-#
# pybind11 documentation build configuration file, created by
# sphinx-quickstart on Sun Oct 11 19:23:48 2015.
#
@@ -13,6 +11,7 @@
# serve to show the default.
from __future__ import annotations
+import importlib.util
import os
import re
import subprocess
@@ -69,13 +68,14 @@
# Read the listed version
version_file = DIR.parent / "pybind11/_version.py"
-with version_file.open(encoding="utf-8") as f:
- code = compile(f.read(), version_file, "exec")
-loc = {"__file__": str(version_file)}
-exec(code, loc)
+spec = importlib.util.spec_from_file_location("pybind11_version", version_file)
+assert spec is not None
+assert spec.loader is not None
+version_module = importlib.util.module_from_spec(spec)
+spec.loader.exec_module(version_module)
# The full version, including alpha/beta/rc tags.
-version = loc["__version__"]
+version = version_module.__version__
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
diff --git a/noxfile.py b/noxfile.py
old mode 100644
new mode 100755
diff --git a/pybind11/__init__.py b/pybind11/__init__.py
index df5e8ee..3882b2b 100644
--- a/pybind11/__init__.py
+++ b/pybind11/__init__.py
@@ -11,9 +11,9 @@
from .commands import get_cmake_dir, get_include, get_pkgconfig_dir
__all__ = (
- "version_info",
"__version__",
- "get_include",
"get_cmake_dir",
+ "get_include",
"get_pkgconfig_dir",
+ "version_info",
)
diff --git a/pybind11/setup_helpers.py b/pybind11/setup_helpers.py
index 8f42605..66a3eec 100644
--- a/pybind11/setup_helpers.py
+++ b/pybind11/setup_helpers.py
@@ -52,10 +52,10 @@
from functools import lru_cache
from pathlib import Path
from typing import (
+ TYPE_CHECKING,
Any,
Callable,
Optional,
- TypeVar,
Union,
)
@@ -71,6 +71,9 @@
import distutils.ccompiler
import distutils.errors
+if TYPE_CHECKING:
+ from typing_extensions import Self
+
WIN = sys.platform.startswith("win32") and "mingw" not in sysconfig.get_platform()
MACOS = sys.platform.startswith("darwin")
STD_TMPL = "/std:c++{}" if WIN else "-std=c++{}"
@@ -338,8 +341,6 @@
return True
-S = TypeVar("S", bound="ParallelCompile")
-
CCompilerMethod = Callable[
[
distutils.ccompiler.CCompiler,
@@ -397,7 +398,7 @@
called.
"""
- __slots__ = ("envvar", "default", "max", "_old", "needs_recompile")
+ __slots__ = ("_old", "default", "envvar", "max", "needs_recompile")
def __init__(
self,
@@ -477,16 +478,16 @@
return compile_function
- def install(self: S) -> S:
+ def install(self) -> Self:
"""
Installs the compile function into distutils.ccompiler.CCompiler.compile.
"""
distutils.ccompiler.CCompiler.compile = self.function() # type: ignore[assignment]
return self
- def __enter__(self: S) -> S:
+ def __enter__(self) -> Self:
self._old.append(distutils.ccompiler.CCompiler.compile)
return self.install()
- def __exit__(self, *args: Any) -> None:
+ def __exit__(self, *args: object) -> None:
distutils.ccompiler.CCompiler.compile = self._old.pop() # type: ignore[assignment]
diff --git a/pyproject.toml b/pyproject.toml
index caf0a8b..cb5d728 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -181,8 +181,14 @@
"EM",
"N",
"E721",
+ "BLE001", # Tests capture and re-report exceptions from workers and callbacks
+ "DTZ", # test_chrono.py checks naive local-time round-tripping on purpose
+ "FLY002", # Joining a list keeps long signatures one-per-line
+ "RUF012", # ClassVar annotations are noise in test fixtures
+ "RUF063", # test_pytypes.py reads __annotations__ from __dict__ deliberately
]
"tests/test_call_policies.py" = ["PLC1901"]
+"docs/benchmark.py" = ["DTZ"]
[tool.repo-review]
ignore = ["PP"]
diff --git a/tests/extra_python_package/test_files.py b/tests/extra_python_package/test_files.py
index e2c1856..164611d 100644
--- a/tests/extra_python_package/test_files.py
+++ b/tests/extra_python_package/test_files.py
@@ -25,7 +25,7 @@
# Newer pytest has global path setting, but keeping old pytest for now
sys.path.append(str(MAIN_DIR / "tools"))
-from make_global import get_global # noqa: E402
+from make_global import get_global
HAS_UV = shutil.which("uv") is not None
UV_ARGS = ["--installer=uv"] if HAS_UV else []
diff --git a/tests/test_enum.py b/tests/test_enum.py
index 53dcc09..81170c9 100644
--- a/tests/test_enum.py
+++ b/tests/test_enum.py
@@ -71,8 +71,8 @@
assert y != 3
assert 3 != y
# Compare with None
- assert y != None # noqa: E711
- assert not (y == None) # noqa: E711
+ assert y != None
+ assert not (y == None)
# Compare with an object
assert y != object()
assert not (y == object())
@@ -137,8 +137,8 @@
assert z != 3
assert 3 != z
# Compare with None
- assert z != None # noqa: E711
- assert not (z == None) # noqa: E711
+ assert z != None
+ assert not (z == None)
# Compare with an object
assert z != object()
assert not (z == object())
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
index c52a295..aeea5d8 100644
--- a/tests/test_exceptions.py
+++ b/tests/test_exceptions.py
@@ -112,7 +112,7 @@
default_hook = sys.__unraisablehook__
def hook(unraisable_hook_args):
- exc_type, exc_value, exc_tb, err_msg, obj = unraisable_hook_args
+ _exc_type, _exc_value, _exc_tb, _err_msg, obj = unraisable_hook_args
if obj == "already_set demo":
nonlocal triggered
triggered = True
@@ -344,8 +344,10 @@
lines = str(excinfo.value).splitlines()
# PyErr_NormalizeException replaces the original FlakyException with ValueError:
assert lines[:3] == [
- "pybind11::error_already_set: MISMATCH of original and normalized active exception types:"
- " ORIGINAL FlakyException REPLACED BY ValueError: triggered_failure_point_init",
+ (
+ "pybind11::error_already_set: MISMATCH of original and normalized active exception types:"
+ " ORIGINAL FlakyException REPLACED BY ValueError: triggered_failure_point_init"
+ ),
"",
"At:",
]
diff --git a/tests/test_iostream.py b/tests/test_iostream.py
index 857e0b5..8b11997 100644
--- a/tests/test_iostream.py
+++ b/tests/test_iostream.py
@@ -160,16 +160,16 @@
with m.ostream_redirect():
m.noisy_function(msg, flush=False)
- stdout, stderr = capfd.readouterr()
+ stdout, _stderr = capfd.readouterr()
assert not stdout
m.noisy_function(msg2, flush=True)
- stdout, stderr = capfd.readouterr()
+ stdout, _stderr = capfd.readouterr()
assert stdout == msg + msg2
m.noisy_function(msg, flush=False)
- stdout, stderr = capfd.readouterr()
+ stdout, _stderr = capfd.readouterr()
assert stdout == msg
@@ -218,7 +218,7 @@
m.raw_output("b")
m.captured_output("c")
m.raw_output("d")
- stdout, stderr = capfd.readouterr()
+ stdout, _stderr = capfd.readouterr()
assert stdout == "bd"
assert stream.getvalue() == "ac"
@@ -235,21 +235,21 @@
stream = StringIO()
with redirect_stdout(stream):
m.raw_output(msg)
- stdout, stderr = capfd.readouterr()
+ stdout, _stderr = capfd.readouterr()
assert stdout == msg
assert not stream.getvalue()
stream = StringIO()
with redirect_stdout(stream), m.ostream_redirect():
m.raw_output(msg)
- stdout, stderr = capfd.readouterr()
+ stdout, _stderr = capfd.readouterr()
assert not stdout
assert stream.getvalue() == msg
stream = StringIO()
with redirect_stdout(stream):
m.raw_output(msg)
- stdout, stderr = capfd.readouterr()
+ stdout, _stderr = capfd.readouterr()
assert stdout == msg
assert not stream.getvalue()
diff --git a/tests/test_numpy_dtypes.py b/tests/test_numpy_dtypes.py
index 22814ab..ba45d8b 100644
--- a/tests/test_numpy_dtypes.py
+++ b/tests/test_numpy_dtypes.py
@@ -316,12 +316,18 @@
"'offsets':[0,12,20,24],'itemsize':56}"
)
assert m.print_array_array(arr) == [
- "a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1},"
- "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}",
- "a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001},"
- "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}",
- "a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001},"
- "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}",
+ (
+ "a={{A,B,C,D},{K,L,M,N},{U,V,W,X}},b={0,1},"
+ "c={0,1,2},d={{0,1},{10,11},{20,21},{30,31}}"
+ ),
+ (
+ "a={{W,X,Y,Z},{G,H,I,J},{Q,R,S,T}},b={1000,1001},"
+ "c={10,11,12},d={{100,101},{110,111},{120,121},{130,131}}"
+ ),
+ (
+ "a={{S,T,U,V},{C,D,E,F},{M,N,O,P}},b={2000,2001},"
+ "c={20,21,22},d={{200,201},{210,211},{220,221},{230,231}}"
+ ),
]
assert arr["a"].tolist() == [
[b"ABCD", b"KLMN", b"UVWX"],
diff --git a/tests/test_smart_ptr.py b/tests/test_smart_ptr.py
index 7ee4b78..326b768 100644
--- a/tests/test_smart_ptr.py
+++ b/tests/test_smart_ptr.py
@@ -5,7 +5,7 @@
import env # noqa: F401
m = pytest.importorskip("pybind11_tests.smart_ptr")
-from pybind11_tests import ConstructorStats # noqa: E402
+from pybind11_tests import ConstructorStats
@pytest.mark.skipif("env.GRAALPY", reason="Cannot reliably trigger GC")
diff --git a/tests/test_stl.py b/tests/test_stl.py
index c75ccb8..f3f4ccc 100644
--- a/tests/test_stl.py
+++ b/tests/test_stl.py
@@ -818,7 +818,7 @@
def test_set_caster_protocol(doc):
- from collections.abc import Set
+ from collections.abc import Set as AbstractSet
# Implements the Set protocol without explicitly inheriting from collections.abc.Set.
class BareSetLike:
@@ -836,7 +836,7 @@
# Implements the Set protocol by reusing BareSetLike's implementation.
# Additionally, inherits from collections.abc.Set.
- class FormalSetLike(BareSetLike, Set):
+ class FormalSetLike(BareSetLike, AbstractSet):
pass
# convert mode
diff --git a/tests/test_virtual_functions.py b/tests/test_virtual_functions.py
index 617c87b..c2bba47 100644
--- a/tests/test_virtual_functions.py
+++ b/tests/test_virtual_functions.py
@@ -7,7 +7,7 @@
import env
m = pytest.importorskip("pybind11_tests.virtual_functions")
-from pybind11_tests import ConstructorStats # noqa: E402
+from pybind11_tests import ConstructorStats
def test_override(capture, msg):
diff --git a/tools/make_changelog.py b/tools/make_changelog.py
index f872546..8d2c7b0 100755
--- a/tools/make_changelog.py
+++ b/tools/make_changelog.py
@@ -94,8 +94,7 @@
if not msg:
missing.append(issue)
continue
- if msg.startswith("* "):
- msg = msg[2:]
+ msg = msg.removeprefix("* ")
if not msg.startswith("- "):
msg = "- " + msg
if not msg.endswith("."):