pre-commit-uv 4.2.1__tar.gz → 4.2.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pre-commit-uv
3
- Version: 4.2.1
3
+ Version: 4.2.2
4
4
  Summary: Run pre-commit with uv
5
5
  Project-URL: Bug Tracker, https://github.com/tox-dev/pre-commit-uv/issues
6
- Project-URL: Changelog, https://github.com/tox-dev/pre-commit-uv/releases
7
6
  Project-URL: Source Code, https://github.com/tox-dev/pre-commit-uv
7
+ Project-URL: Changelog, https://github.com/tox-dev/pre-commit-uv/releases
8
8
  Project-URL: Documentation, https://github.com/tox-dev/pre-commit-uv/
9
9
  Author-email: Bernat Gabor <gaborjbernat@gmail.com>
10
10
  License: Permission is hereby granted, free of charge, to any person obtaining a
@@ -39,11 +39,6 @@ Classifier: Programming Language :: Python :: 3.14
39
39
  Requires-Python: >=3.10
40
40
  Requires-Dist: pre-commit>=4.3
41
41
  Requires-Dist: uv>=0.9.1
42
- Provides-Extra: testing
43
- Requires-Dist: covdefaults>=2.3; extra == 'testing'
44
- Requires-Dist: pytest-cov>=7; extra == 'testing'
45
- Requires-Dist: pytest-mock>=3.15.1; extra == 'testing'
46
- Requires-Dist: pytest>=8.4.2; extra == 'testing'
47
42
  Description-Content-Type: text/markdown
48
43
 
49
44
  # pre-commit-uv
@@ -2,7 +2,7 @@
2
2
  build-backend = "hatchling.build"
3
3
  requires = [
4
4
  "hatch-vcs>=0.5",
5
- "hatchling>=1.27",
5
+ "hatchling>=1.28",
6
6
  ]
7
7
 
8
8
  [project]
@@ -36,18 +36,39 @@ dependencies = [
36
36
  "pre-commit>=4.3",
37
37
  "uv>=0.9.1",
38
38
  ]
39
- optional-dependencies.testing = [
39
+ urls."Bug Tracker" = "https://github.com/tox-dev/pre-commit-uv/issues"
40
+ urls."Source Code" = "https://github.com/tox-dev/pre-commit-uv"
41
+ urls.Changelog = "https://github.com/tox-dev/pre-commit-uv/releases"
42
+ urls.Documentation = "https://github.com/tox-dev/pre-commit-uv/"
43
+
44
+ [dependency-groups]
45
+ dev = [
46
+ { include-group = "lint" },
47
+ { include-group = "pkg-meta" },
48
+ { include-group = "test" },
49
+ { include-group = "type" },
50
+ ]
51
+ test = [
40
52
  "covdefaults>=2.3",
41
53
  "pytest>=8.4.2",
42
54
  "pytest-cov>=7",
43
55
  "pytest-mock>=3.15.1",
44
56
  ]
45
- urls."Bug Tracker" = "https://github.com/tox-dev/pre-commit-uv/issues"
46
- urls."Changelog" = "https://github.com/tox-dev/pre-commit-uv/releases"
47
- urls."Source Code" = "https://github.com/tox-dev/pre-commit-uv"
48
- urls.Documentation = "https://github.com/tox-dev/pre-commit-uv/"
57
+ type = [
58
+ "ty>=0.0.17",
59
+ { include-group = "test" },
60
+ ]
61
+ lint = [
62
+ "pre-commit-uv>=4.2",
63
+ ]
64
+ pkg-meta = [
65
+ "check-wheel-contents>=0.6.3",
66
+ "twine>=6.2",
67
+ "uv>=0.10.2",
68
+ ]
49
69
 
50
70
  [tool.hatch]
71
+ version.source = "vcs"
51
72
  build.dev-mode-dirs = [
52
73
  "src",
53
74
  ]
@@ -58,7 +79,6 @@ build.targets.sdist.include = [
58
79
  ]
59
80
  build.targets.wheel.only-include = [ "src" ]
60
81
  build.targets.wheel.sources = [ "src" ]
61
- version.source = "vcs"
62
82
 
63
83
  [tool.ruff]
64
84
  line-length = 120
@@ -69,7 +89,6 @@ lint.select = [
69
89
  "ALL",
70
90
  ]
71
91
  lint.ignore = [
72
- "ANN101", # no type annotation for self
73
92
  "ANN401", # allow Any as type annotation
74
93
  "COM812", # Conflict with formatter
75
94
  "CPY", # No copyright statements
@@ -105,6 +124,9 @@ count = true
105
124
  [tool.pyproject-fmt]
106
125
  max_supported_python = "3.14"
107
126
 
127
+ [tool.ty]
128
+ environment.python-version = "3.14"
129
+
108
130
  [tool.pytest]
109
131
  ini_options.testpaths = [
110
132
  "tests",
@@ -127,12 +149,3 @@ paths.source = [
127
149
  report.fail_under = 63
128
150
  html.show_contexts = true
129
151
  html.skip_covered = false
130
-
131
- [tool.mypy]
132
- show_error_codes = true
133
- strict = true
134
- overrides = [
135
- { module = [
136
- "pre_commit.*",
137
- ], ignore_missing_imports = true },
138
- ]
@@ -4,7 +4,20 @@ from __future__ import annotations
4
4
 
5
5
  # only import built-ins at top level to avoid interpreter startup overhead
6
6
  import os
7
+ import pathlib
7
8
  import sys
9
+ from typing import TYPE_CHECKING, cast
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import Callable, Sequence
13
+ from typing import Protocol
14
+
15
+ from pre_commit.prefix import Prefix
16
+
17
+ class _PatchablePython(Protocol):
18
+ install_environment: Callable[[Prefix, str, Sequence[str]], None]
19
+ health_check: Callable[[Prefix, str], str | None]
20
+
8
21
 
9
22
  _original_main = None
10
23
 
@@ -33,7 +46,7 @@ def _patch() -> None:
33
46
  if _is_calling_pre_commit() and os.environ.get("DISABLE_PRE_COMMIT_UV_PATCH") is None:
34
47
  from pre_commit import main # noqa: PLC0415
35
48
 
36
- _original_main, main.main = main.main, _new_main
49
+ _original_main, main.main = main.main, _new_main # ty: ignore[invalid-assignment]
37
50
  if "--version" in sys.argv:
38
51
  from importlib.metadata import version as _metadata_version # noqa: PLC0415
39
52
 
@@ -47,18 +60,12 @@ def _patch() -> None:
47
60
  )
48
61
 
49
62
 
50
- def _new_main(argv: list[str] | None = None) -> int:
63
+ def _new_main(argv: Sequence[str] | None = None) -> int:
51
64
  # imports applied locally to avoid patching import overhead cost
52
65
  from functools import cache # noqa: PLC0415
53
- from typing import TYPE_CHECKING, cast # noqa: PLC0415
54
66
 
55
67
  from pre_commit.languages import python # noqa: PLC0415
56
68
 
57
- if TYPE_CHECKING:
58
- from collections.abc import Sequence # noqa: PLC0415
59
-
60
- from pre_commit.prefix import Prefix # noqa: PLC0415
61
-
62
69
  def _install_environment(
63
70
  prefix: Prefix,
64
71
  version: str,
@@ -120,17 +127,48 @@ def _new_main(argv: list[str] | None = None) -> int:
120
127
 
121
128
  return _metadata_version("uv")
122
129
 
123
- @cache
124
- def _version_info(exe: str) -> str:
125
- from pre_commit.util import CalledProcessError, cmd_output # noqa: PLC0415
130
+ patched = cast("_PatchablePython", python)
131
+ patched.install_environment = _install_environment
132
+ patched.health_check = _health_check
133
+ assert _original_main is not None # noqa: S101
134
+ return _original_main(argv)
126
135
 
127
- prog = 'import sys;print(".".join(str(p) for p in sys.version_info[0:3]))'
128
- try:
129
- return cast("str", cmd_output(exe, "-S", "-c", prog)[1].strip())
130
- except CalledProcessError:
131
- return f"<<error retrieving version from {exe}>>"
132
136
 
133
- python.install_environment = _install_environment
134
- python._version_info = _version_info # noqa: SLF001
135
- assert _original_main is not None # noqa: S101
136
- return cast("int", _original_main(argv))
137
+ def _version_info(exe: str) -> str:
138
+ from pre_commit.util import CalledProcessError, cmd_output # noqa: PLC0415
139
+
140
+ prog = 'import sys;print(".".join(str(p) for p in sys.version_info[0:3]))'
141
+ try:
142
+ return cmd_output(exe, "-S", "-c", prog)[1].strip()
143
+ except CalledProcessError:
144
+ return f"<<error retrieving version from {exe}>>"
145
+
146
+
147
+ def _health_check(prefix: Prefix, version: str) -> str | None:
148
+ # uv may record fewer version components in pyvenv.cfg than pre-commit expects (e.g. "3.14" vs "3.14.6"),
149
+ # so compare only the components uv actually wrote rather than requiring an exact string match
150
+ from pre_commit.lang_base import environment_dir # noqa: PLC0415
151
+ from pre_commit.languages import python # noqa: PLC0415
152
+ from pre_commit.util import win_exe # noqa: PLC0415
153
+
154
+ pyvenv_cfg = pathlib.Path(environment_dir(prefix, python.ENVIRONMENT_DIR, version)) / "pyvenv.cfg"
155
+ if not pyvenv_cfg.exists():
156
+ return "pyvenv.cfg does not exist (old virtualenv?)"
157
+
158
+ cfg = python._read_pyvenv_cfg(str(pyvenv_cfg)) # noqa: SLF001
159
+ if "version_info" not in cfg:
160
+ return "created virtualenv's pyvenv.cfg is missing `version_info`"
161
+ expected = cfg["version_info"].split(".")
162
+
163
+ py_exe = prefix.path(python.bin_dir(str(pyvenv_cfg.parent)), win_exe("python"))
164
+ targets = [("virtualenv python", py_exe)]
165
+ if "base-executable" in cfg:
166
+ targets.append(("base executable", cfg["base-executable"]))
167
+ for label, exe in targets:
168
+ if (actual := _version_info(exe)).split(".")[: len(expected)] != expected:
169
+ return (
170
+ f"{label} version did not match created version:\n"
171
+ f"- actual version: {actual}\n"
172
+ f"- expected version: {cfg['version_info']}\n"
173
+ )
174
+ return None
@@ -0,0 +1,77 @@
1
+ from __future__ import annotations
2
+
3
+ import sys
4
+ from typing import TYPE_CHECKING
5
+
6
+ from pre_commit.languages import python
7
+ from pre_commit.prefix import Prefix
8
+
9
+ from pre_commit_uv import _health_check
10
+
11
+ if TYPE_CHECKING:
12
+ from pathlib import Path
13
+
14
+ version = "default"
15
+ major_minor = f"{sys.version_info[0]}.{sys.version_info[1]}"
16
+ full_version = ".".join(str(p) for p in sys.version_info[0:3])
17
+ wrong_version = f"{sys.version_info[0]}.{sys.version_info[1] + 1}"
18
+
19
+
20
+ def _make_env(tmp_path: Path, pyvenv_cfg: str | None) -> Prefix:
21
+ envdir = tmp_path / f"py_env-{version}"
22
+ bin_dir = python.bin_dir(str(envdir))
23
+ (tmp_path / bin_dir).mkdir(parents=True)
24
+ (tmp_path / bin_dir / python.win_exe("python")).symlink_to(sys.executable)
25
+ if pyvenv_cfg is not None:
26
+ (envdir / "pyvenv.cfg").write_text(pyvenv_cfg)
27
+ return Prefix(str(tmp_path))
28
+
29
+
30
+ def test_health_check_truncated_version_passes(tmp_path: Path) -> None:
31
+ """uv >=0.11.22 writes only the major.minor into pyvenv.cfg (see issue #152)."""
32
+ prefix = _make_env(tmp_path, f"version_info = {major_minor}\nbase-executable = {sys.executable}\n")
33
+
34
+ assert _health_check(prefix, version) is None
35
+
36
+
37
+ def test_health_check_full_version_passes(tmp_path: Path) -> None:
38
+ prefix = _make_env(tmp_path, f"version_info = {full_version}\nbase-executable = {sys.executable}\n")
39
+
40
+ assert _health_check(prefix, version) is None
41
+
42
+
43
+ def test_health_check_no_base_executable_passes(tmp_path: Path) -> None:
44
+ prefix = _make_env(tmp_path, f"version_info = {major_minor}\n")
45
+
46
+ assert _health_check(prefix, version) is None
47
+
48
+
49
+ def test_health_check_version_mismatch_fails(tmp_path: Path) -> None:
50
+ prefix = _make_env(tmp_path, f"version_info = {wrong_version}\n")
51
+
52
+ result = _health_check(prefix, version)
53
+
54
+ assert result is not None
55
+ assert "virtualenv python version did not match created version" in result
56
+ assert f"- expected version: {wrong_version}" in result
57
+
58
+
59
+ def test_health_check_base_executable_mismatch_fails(tmp_path: Path) -> None:
60
+ prefix = _make_env(tmp_path, f"version_info = {major_minor}\nbase-executable = /does/not/exist/python\n")
61
+
62
+ result = _health_check(prefix, version)
63
+
64
+ assert result is not None
65
+ assert "base executable version did not match created version" in result
66
+
67
+
68
+ def test_health_check_missing_pyvenv_cfg(tmp_path: Path) -> None:
69
+ prefix = _make_env(tmp_path, None)
70
+
71
+ assert _health_check(prefix, version) == "pyvenv.cfg does not exist (old virtualenv?)"
72
+
73
+
74
+ def test_health_check_missing_version_info(tmp_path: Path) -> None:
75
+ prefix = _make_env(tmp_path, "home = /usr\n")
76
+
77
+ assert _health_check(prefix, version) == "created virtualenv's pyvenv.cfg is missing `version_info`"
@@ -1,70 +0,0 @@
1
- [tox]
2
- requires =
3
- tox>=4.31
4
- tox-uv>=1.28.1
5
- env_list =
6
- fix
7
- 3.14
8
- 3.13
9
- 3.12
10
- 3.11
11
- 3.10
12
- 3.9
13
- 3.8
14
- type
15
- pkg_meta
16
- skip_missing_interpreters = true
17
-
18
- [testenv]
19
- description = run the unit tests with pytest under {base_python}
20
- package = wheel
21
- wheel_build_env = .pkg
22
- extras =
23
- testing
24
- pass_env =
25
- PYTEST_*
26
- set_env =
27
- COVERAGE_FILE = {work_dir}/.coverage.{env_name}
28
- commands =
29
- python -m pytest {tty:--color=yes} {posargs: \
30
- --cov {env_site_packages_dir}{/}pre_commit_uv --cov {tox_root}{/}tests \
31
- --cov-config=pyproject.toml --no-cov-on-fail --cov-report term-missing:skip-covered --cov-context=test \
32
- --cov-report html:{env_tmp_dir}{/}htmlcov --cov-report xml:{work_dir}{/}coverage.{env_name}.xml \
33
- --junitxml {work_dir}{/}junit.{env_name}.xml \
34
- tests}
35
-
36
- [testenv:fix]
37
- description = format the code base to adhere to our styles, and complain about what we cannot do automatically
38
- skip_install = true
39
- deps =
40
- pre-commit-uv>=4.1.1
41
- commands =
42
- pre-commit run --all-files --show-diff-on-failure
43
-
44
- [testenv:type]
45
- description = run type check on code base
46
- deps =
47
- mypy==1.18.2
48
- commands =
49
- mypy src
50
- mypy tests
51
-
52
- [testenv:pkg_meta]
53
- description = check that the long description is valid
54
- skip_install = true
55
- deps =
56
- check-wheel-contents>=0.6.3
57
- twine>=6.2
58
- uv>=0.9.1
59
- commands =
60
- uv build --sdist --wheel --out-dir {env_tmp_dir} .
61
- twine check {env_tmp_dir}{/}*
62
- check-wheel-contents --no-config {env_tmp_dir}
63
-
64
- [testenv:dev]
65
- description = generate a DEV environment
66
- package = editable
67
- commands =
68
- uv tree
69
- python -c 'import sys; print(sys.executable)'
70
- python task/dev_pth.py {env_site_packages_dir}
File without changes
File without changes
File without changes