Skip to content

Commit 5d8b486

Browse files
committed
Update precommit hooks to latest version
This include updating some repo, renaming some hooks, and run them to fix the corresponding files.
1 parent d51b9c0 commit 5d8b486

File tree

8 files changed

+42
-34
lines changed

8 files changed

+42
-34
lines changed

.pre-commit-config.yaml

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ ci:
44

55
repos:
66
- repo: https://github.com/pre-commit/pre-commit-hooks
7-
rev: v5.0.0
7+
rev: v6.0.0
88
hooks:
99
- id: check-case-conflict
1010
- id: check-ast
@@ -21,11 +21,11 @@ repos:
2121
- id: trailing-whitespace
2222

2323
- repo: https://github.com/python-jsonschema/check-jsonschema
24-
rev: 0.33.0
24+
rev: 0.34.0
2525
hooks:
2626
- id: check-github-workflows
2727

28-
- repo: https://github.com/executablebooks/mdformat
28+
- repo: https://github.com/hukkin/mdformat
2929
rev: 0.7.22
3030
hooks:
3131
- id: mdformat
@@ -39,13 +39,13 @@ repos:
3939
types_or: [yaml, html, json]
4040

4141
- repo: https://github.com/adamchainz/blacken-docs
42-
rev: "1.19.1"
42+
rev: "1.20.0"
4343
hooks:
4444
- id: blacken-docs
4545
additional_dependencies: [black==23.7.0]
4646

4747
- repo: https://github.com/pre-commit/mirrors-mypy
48-
rev: "v1.15.0"
48+
rev: "v1.18.2"
4949
hooks:
5050
- id: mypy
5151
files: jupyter_core
@@ -67,16 +67,16 @@ repos:
6767
- id: rst-inline-touching-normal
6868

6969
- repo: https://github.com/astral-sh/ruff-pre-commit
70-
rev: v0.11.11
70+
rev: v0.14.0
7171
hooks:
72-
- id: ruff
72+
- id: ruff-check
7373
types_or: [python, jupyter]
7474
args: ["--fix", "--show-fixes"]
7575
- id: ruff-format
7676
types_or: [python, jupyter]
7777

7878
- repo: https://github.com/scientific-python/cookie
79-
rev: "2025.05.02"
79+
rev: "2025.10.01"
8080
hooks:
8181
- id: sp-repo-review
8282
additional_dependencies: ["repo-review[cli]"]

jupyter_core/application.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def migrate_config(self) -> None:
177177
f_marker.close()
178178
return # so we must have already migrated -> bail out
179179

180-
from .migrate import get_ipython_dir, migrate
180+
from .migrate import get_ipython_dir, migrate # noqa: PLC0415
181181

182182
# No IPython dir, nothing to migrate
183183
if not Path(get_ipython_dir()).exists():
@@ -264,7 +264,7 @@ def initialize(self, argv: t.Any = None) -> None:
264264
def start(self) -> None:
265265
"""Start the whole thing"""
266266
if self.subcommand:
267-
os.execv(self.subcommand, [self.subcommand] + self.argv[1:]) # noqa: S606
267+
os.execv(self.subcommand, [self.subcommand, *self.argv[1:]]) # noqa: S606
268268
raise NoStart()
269269

270270
if self.subapp:

jupyter_core/command.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def epilog(self, x: Any) -> None:
4343
def argcomplete(self) -> None:
4444
"""Trigger auto-completion, if enabled"""
4545
try:
46-
import argcomplete
46+
import argcomplete # noqa: PLC0415
4747

4848
argcomplete.autocomplete(self)
4949
except ImportError:
@@ -123,10 +123,10 @@ def _execvp(cmd: str, argv: list[str]) -> None:
123123
if cmd_path is None:
124124
msg = f"{cmd!r} not found"
125125
raise OSError(msg, errno.ENOENT)
126-
p = Popen([cmd_path] + argv[1:]) # noqa: S603
126+
p = Popen([cmd_path, *argv[1:]]) # noqa: S603
127127
# Don't raise KeyboardInterrupt in the parent process.
128128
# Set this after spawning, to avoid subprocess inheriting handler.
129-
import signal
129+
import signal # noqa: PLC0415
130130

131131
signal.signal(signal.SIGINT, signal.SIG_IGN)
132132
p.wait()
@@ -203,7 +203,7 @@ def _evaluate_argcomplete(parser: JupyterParser) -> list[str]:
203203
try:
204204
# traitlets >= 5.8 provides some argcomplete support,
205205
# use helper methods to jump to argcomplete
206-
from traitlets.config.argcomplete_config import (
206+
from traitlets.config.argcomplete_config import ( # noqa: PLC0415
207207
get_argcomplete_cwords,
208208
increment_argcomplete_index,
209209
)
@@ -237,7 +237,7 @@ def main() -> None:
237237
# Avoids argparse gobbling up args passed to subcommand, such as `-h`.
238238
subcommand = argv[1]
239239
else:
240-
args, opts = parser.parse_known_args()
240+
args, _opts = parser.parse_known_args()
241241
subcommand = args.subcommand
242242
if args.version:
243243
print("Selected Jupyter core packages...")
@@ -399,7 +399,7 @@ def main() -> None:
399399
sys.exit(str(e))
400400

401401
try:
402-
_execvp(command, [command] + argv[2:])
402+
_execvp(command, [command, *argv[2:]])
403403
except OSError as e:
404404
sys.exit(f"Error executing Jupyter command {subcommand!r}: {e}")
405405

jupyter_core/paths.py

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
import sys
1616
import tempfile
1717
import warnings
18+
from collections.abc import Iterator
1819
from contextlib import contextmanager
1920
from pathlib import Path
20-
from typing import Any, Iterator, Literal, Optional, overload
21+
from typing import Any, overload
2122

2223
import platformdirs
2324

@@ -43,10 +44,10 @@ def envset(name: str, default: bool = False) -> bool: ...
4344

4445

4546
@overload
46-
def envset(name: str, default: Literal[None]) -> Optional[bool]: ...
47+
def envset(name: str, default: None) -> bool | None: ...
4748

4849

49-
def envset(name: str, default: Optional[bool] = False) -> Optional[bool]:
50+
def envset(name: str, default: bool | None = False) -> bool | None:
5051
"""Return the boolean value of a given environment variable.
5152
5253
An environment variable is considered set if it is assigned to a value
@@ -182,12 +183,14 @@ def jupyter_data_dir() -> str:
182183

183184
if sys.platform == "darwin":
184185
return str(Path(home, "Library", "Jupyter"))
186+
# Bug in mypy which thinks it's unreachable: https://github.com/python/mypy/issues/10773
185187
if sys.platform == "win32":
186188
appdata = os.environ.get("APPDATA", None)
187189
if appdata:
188190
return str(Path(appdata, "jupyter").resolve())
189191
return pjoin(jupyter_config_dir(), "data")
190192
# Linux, non-OS X Unix, AIX, etc.
193+
# Bug in mypy which thinks it's unreachable: https://github.com/python/mypy/issues/10773
191194
xdg = env.get("XDG_DATA_HOME", None)
192195
if not xdg:
193196
xdg = pjoin(home, ".local", "share")
@@ -303,7 +306,7 @@ def jupyter_path(*subdirs: str) -> list[str]:
303306
if site.ENABLE_USER_SITE:
304307
# Check if site.getuserbase() exists to be compatible with virtualenv,
305308
# which often does not have this method.
306-
userbase: Optional[str]
309+
userbase: str | None
307310
userbase = site.getuserbase() if hasattr(site, "getuserbase") else site.USER_BASE
308311

309312
if userbase:
@@ -400,7 +403,7 @@ def jupyter_config_path() -> list[str]:
400403
# Next is environment or user, depending on the JUPYTER_PREFER_ENV_PATH flag
401404
user = [jupyter_config_dir()]
402405
if site.ENABLE_USER_SITE:
403-
userbase: Optional[str]
406+
userbase: str | None
404407
# Check if site.getuserbase() exists to be compatible with virtualenv,
405408
# which often does not have this method.
406409
userbase = site.getuserbase() if hasattr(site, "getuserbase") else site.USER_BASE
@@ -442,7 +445,7 @@ def exists(path: str) -> bool:
442445
return True
443446

444447

445-
def is_file_hidden_win(abs_path: str, stat_res: Optional[Any] = None) -> bool:
448+
def is_file_hidden_win(abs_path: str, stat_res: Any | None = None) -> bool:
446449
"""Is a file hidden?
447450
448451
This only checks the file itself; it should be called in combination with
@@ -487,7 +490,7 @@ def is_file_hidden_win(abs_path: str, stat_res: Optional[Any] = None) -> bool:
487490
return False
488491

489492

490-
def is_file_hidden_posix(abs_path: str, stat_res: Optional[Any] = None) -> bool:
493+
def is_file_hidden_posix(abs_path: str, stat_res: Any | None = None) -> bool:
491494
"""Is a file hidden?
492495
493496
This only checks the file itself; it should be called in combination with
@@ -602,12 +605,12 @@ def win32_restrict_file_to_user(fname: str) -> None:
602605
The path to the file to secure
603606
"""
604607
try:
605-
import win32api
608+
import win32api # noqa: PLC0415
606609
except ImportError:
607610
return _win32_restrict_file_to_user_ctypes(fname)
608611

609-
import ntsecuritycon as con
610-
import win32security
612+
import ntsecuritycon as con # noqa: PLC0415
613+
import win32security # noqa: PLC0415
611614

612615
# everyone, _domain, _type = win32security.LookupAccountName("", "Everyone")
613616
admins = win32security.CreateWellKnownSid(win32security.WinBuiltinAdministratorsSid)
@@ -646,8 +649,8 @@ def _win32_restrict_file_to_user_ctypes(fname: str) -> None:
646649
fname : unicode
647650
The path to the file to secure
648651
"""
649-
import ctypes
650-
from ctypes import wintypes
652+
import ctypes # noqa: PLC0415
653+
from ctypes import wintypes # noqa: PLC0415
651654

652655
advapi32 = ctypes.WinDLL("advapi32", use_last_error=True) # type:ignore[attr-defined]
653656
secur32 = ctypes.WinDLL("secur32", use_last_error=True) # type:ignore[attr-defined]

jupyter_core/troubleshoot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@
1010
import platform
1111
import subprocess
1212
import sys
13-
from typing import Any, Optional, Union
13+
from typing import Any, Union
1414

1515

16-
def subs(cmd: Union[list[str], str]) -> Optional[str]:
16+
def subs(cmd: Union[list[str], str]) -> str | None:
1717
"""
1818
get data from commands that we need to run outside of python
1919
"""

pyproject.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ dependencies = ["pre-commit"]
9797
detached = true
9898
[tool.hatch.envs.lint.scripts]
9999
build = [
100-
"pre-commit run --all-files ruff",
100+
"pre-commit run --all-files ruff-check",
101101
"pre-commit run --all-files ruff-format"
102102
]
103103

@@ -111,6 +111,11 @@ disallow_incomplete_defs = true
111111
disallow_untyped_defs = true
112112
warn_redundant_casts = true
113113
disallow_untyped_calls = true
114+
# This is a workaround for a mypy bug which is incapable of treating sys.platform
115+
# correctly https://github.com/python/mypy/issues/10773
116+
# With pre-commit running on user platform and linux on CI you can't get the
117+
# types right, so we pin platform to linux
118+
platform = "linux"
114119

115120
[tool.pytest.ini_options]
116121
minversion = "7.0"

tests/test_command.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def write_executable(path, source):
6565

6666
if sys.platform == "win32":
6767
try:
68-
import importlib.resources
68+
import importlib.resources # noqa: PLC0415
6969

7070
if not hasattr(importlib.resources, "files"):
7171
raise ImportError
@@ -152,7 +152,7 @@ def test_subcommand_not_found():
152152
assert "Jupyter command `jupyter-nonexistant-subcommand` not found." in stderr
153153

154154

155-
@patch.object(sys, "argv", [__file__] + sys.argv[1:])
155+
@patch.object(sys, "argv", [__file__, *sys.argv[1:]])
156156
def test_subcommand_list(tmpdir):
157157
a = tmpdir.mkdir("a")
158158
for cmd in ("jupyter-foo-bar", "jupyter-xyz", "jupyter-babel-fish"):

tests/test_paths.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -499,7 +499,7 @@ def test_is_hidden_win32_cpython():
499499
reason="only run on windows/pypy < 7.3.6: https://foss.heptapod.net/pypy/pypy/-/issues/3469",
500500
)
501501
def test_is_hidden_win32_pypy():
502-
import ctypes # noqa: F401
502+
import ctypes # noqa: F401, PLC0415
503503

504504
with tempfile.TemporaryDirectory() as root:
505505
subdir1 = os.path.join(root, "subdir")

0 commit comments

Comments
 (0)