Skip to content

Commit 3616ae9

Browse files
committed
fix(tooling): advance exact Python dev pins with just update
- Resolve direct development tools as one compatible cross-platform set. - Preserve runtime and build-system dependency requirements. - Refresh Ruff, Semgrep, Ty, and their compatible transitive dependencies.
1 parent 78ba1c2 commit 3616ae9

13 files changed

Lines changed: 455 additions & 100 deletions

AGENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ just ci # Full CI simulation (checks + tests + examples + bench co
295295
just test # Lib + doc tests (fast)
296296
just test-all # All tests (Rust, benchmark inputs, and Python)
297297
just examples # Run all examples
298-
just update # Update dependency locks and repository-owned Cargo tools
298+
just update # Update dependency requirements, locks, and repository-owned Cargo tools
299299
just update-version vX.Y.Z # Update release metadata without upgrading dependencies
300300
```
301301

CONTRIBUTING.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ Use `just fix` when you intentionally want formatters and automatic fixes to
2626
change files. Run `just --list` for the full command surface.
2727

2828
Use `just update` for deliberate dependency and tool maintenance. It composes
29-
`just update-dependencies`, which advances Cargo dependency requirements and
30-
the Cargo/uv locks, with `just update-cargo-tools`, which upgrades only the
31-
Cargo CLI packages owned by `setup-tools` and atomically reconciles their root
32-
`justfile` pins. The tool updater requires `cargo-install-update` from the
33-
`cargo-update` package and does not touch unrelated Cargo executables or uv's
34-
user-global tool environments.
29+
`just update-dependencies`, which advances Cargo dependency requirements, exact
30+
Python development-tool pins, and the Cargo/uv locks, with
31+
`just update-cargo-tools`, which upgrades only the Cargo CLI packages owned by
32+
`setup-tools` and atomically reconciles their root `justfile` pins. The tool
33+
updater requires `cargo-install-update` from the `cargo-update` package and does
34+
not touch unrelated Cargo executables or uv's user-global tool environments.
3535

3636
The repository uses `cargo-nextest` for runnable Rust tests, `cargo-machete`
3737
for unused-dependency checks, and `just cargo-lock-check` to verify that the

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docs/RELEASING.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ git switch main
2929
git pull --ff-only
3030
```
3131

32-
Refresh dependency requirements, lockfiles, and repository-owned Cargo tool
33-
pins before creating the release branch:
32+
Refresh Cargo dependency requirements, exact Python development-tool pins,
33+
lockfiles, and repository-owned Cargo tool pins before creating the release
34+
branch:
3435

3536
```bash
3637
just update

justfile

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1084,11 +1084,20 @@ update-cargo-tools: _ensure-uv
10841084
cargo install-update --locked "${packages[@]}"
10851085
uv run --locked update-cargo-tool-pins
10861086
1087-
# Advance Cargo dependency declarations, update Cargo and uv locks, then sync uv dev tools.
1088-
[doc('Update Cargo.toml dependency requirements and all Cargo/uv locked dependencies.')]
1089-
update-dependencies: _ensure-uv _ensure-cargo-edit
1087+
# Advance Cargo and exact Python development requirements plus their lockfiles.
1088+
[doc('Update Cargo and Python development requirements plus all Cargo/uv locked dependencies.')]
1089+
update-dependencies: update-cargo-dependencies update-python-dependencies
1090+
1091+
# Advance Cargo dependency declarations and lockfile entries.
1092+
[doc('Update Cargo.toml dependency requirements and Cargo.lock.')]
1093+
update-cargo-dependencies: _ensure-cargo-edit
10901094
cargo upgrade
10911095
cargo update
1096+
1097+
# Resolve latest Python development tools, retain exact pins, and sync the environment.
1098+
[doc('Update exact dependency-groups.dev pins and uv.lock through uv.')]
1099+
update-python-dependencies: _ensure-uv
1100+
uv run --locked update-python-dev-pins
10921101
uv lock --upgrade
10931102
uv sync --locked --group dev
10941103

pyproject.toml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,12 @@ tag-release = "tag_release:main"
4343
check-docs-version-sync = "check_docs_version_sync:main"
4444
update-release-version = "update_release_version:main"
4545
update-cargo-tool-pins = "update_cargo_tool_pins:main"
46+
update-python-dev-pins = "update_python_dev_pins:main"
4647

4748
# Configure setuptools to find modules in scripts/ directory.
4849
[tool.setuptools]
4950
package-dir = { "" = "scripts" }
50-
py-modules = [ "archive_changelog", "archive_performance", "bench_compare", "benchmark_contract", "check_docs_version_sync", "check_semgrep_fixtures", "criterion_dim_plot", "performance_artifacts", "postprocess_changelog", "subprocess_utils", "tag_release", "update_cargo_tool_pins", "update_release_version" ]
51+
py-modules = [ "archive_changelog", "archive_performance", "bench_compare", "benchmark_contract", "check_docs_version_sync", "check_semgrep_fixtures", "criterion_dim_plot", "performance_artifacts", "postprocess_changelog", "subprocess_utils", "tag_release", "update_cargo_tool_pins", "update_python_dev_pins", "update_release_version" ]
5152

5253
[tool.ruff]
5354
line-length = 160
@@ -99,6 +100,7 @@ known-first-party = [
99100
"subprocess_utils",
100101
"tag_release",
101102
"update_cargo_tool_pins",
103+
"update_python_dev_pins",
102104
]
103105
force-single-line = false
104106
split-on-trailing-comma = true
@@ -149,10 +151,10 @@ package = true
149151
dev = [
150152
"actionlint-py==1.7.12.24",
151153
"pytest==9.1.1",
152-
"ruff==0.16.2",
153-
"semgrep==1.172.0",
154+
"ruff==0.16.4",
155+
"semgrep==1.174.0",
154156
"shellcheck-py==0.11.0.1",
155157
"shfmt-py==4.0.0",
156-
"ty==0.0.69",
158+
"ty==0.0.73",
157159
"yamllint==1.38.0",
158160
]

scripts/README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ uv sync --locked --group dev
2727
### Updating dependencies and repository-owned tools
2828

2929
Run `just update` for the deliberate maintenance workflow. It updates Cargo and
30-
uv dependency declarations and locks, upgrades only the Cargo CLI packages
31-
owned by `setup-tools`, and then uses `update-cargo-tool-pins` to reconcile the
32-
installed package versions with the root `justfile` atomically.
30+
exact Python development-tool declarations and their locks, upgrades only the
31+
Cargo CLI packages owned by `setup-tools`, and then reconciles the installed
32+
package versions with the root `justfile` atomically. The Python updater asks
33+
uv to resolve one cross-platform tool set before applying all changed exact
34+
pins together; it does not change runtime or build-system requirements.
3335

3436
## How to use it
3537

@@ -282,6 +284,7 @@ validates SemVer, and handles GitHub's 125KB tag-annotation size limit.
282284
| `postprocess_changelog.py` | Normalize and reflow generated git-cliff Markdown safely |
283285
| `subprocess_utils.py` | Safe subprocess wrappers for git commands |
284286
| `update_cargo_tool_pins.py` | Reconcile repository-owned Cargo tool pins with installed versions |
287+
| `update_python_dev_pins.py` | Resolve and advance exact Python development-tool pins through uv |
285288
| `update_release_version.py` | Transactionally update deterministic release-version metadata |
286289

287290
See `docs/RELEASING.md` for the full release workflow.

scripts/postprocess_changelog.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import sys
2424
from dataclasses import dataclass
2525
from pathlib import Path
26+
from typing import cast
2627

2728
# rumdl MD013 line-length limit used by this project.
2829
MAX_LINE_WIDTH = 160
@@ -216,17 +217,17 @@ def _squash_heading_parts(line: str) -> tuple[str, str, str] | None:
216217
if match is None:
217218
return None
218219

219-
raw_prefix = match.group("prefix")
220+
raw_prefix = cast("str", match.group("prefix"))
220221
kind = re.sub(r"\([^)]+\)", "", raw_prefix).rstrip("!").casefold()
221222
label = _SQUASH_HEADING_LABELS.get(kind)
222223
if label is None:
223224
return None
224225

225-
title = match.group("title").strip()
226+
title = cast("str", match.group("title")).strip()
226227
if not title:
227228
return None
228229

229-
return match.group("indent"), label, title[0].upper() + title[1:]
230+
return cast("str", match.group("indent")), label, title[0].upper() + title[1:]
230231

231232

232233
def _normalize_squash_heading(line: str, *, nested: bool = False) -> str:
@@ -678,7 +679,11 @@ def _fence_parts(line: str) -> tuple[str, str, str] | None:
678679
match = _FENCE_RE.fullmatch(line)
679680
if match is None:
680681
return None
681-
return match.group("indent"), match.group("fence"), match.group("info")
682+
return (
683+
cast("str", match.group("indent")),
684+
cast("str", match.group("fence")),
685+
cast("str", match.group("info")),
686+
)
682687

683688

684689
def _opening_code_fence(line: str) -> _CodeFence | None:

scripts/subprocess_utils.py

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
import subprocess
1919
import tempfile
2020
from pathlib import Path
21-
from typing import Any
21+
from typing import Any, cast
2222

2323
type RunKwargs = dict[str, Any]
2424

@@ -105,10 +105,13 @@ def run_git_command(
105105
"""
106106
git_path = get_safe_executable("git")
107107
run_kwargs = _build_run_kwargs("run_git_command", **kwargs)
108-
return subprocess.run( # noqa: S603,PLW1510
109-
[git_path, *args],
110-
cwd=cwd,
111-
**run_kwargs,
108+
return cast(
109+
"subprocess.CompletedProcess[str]",
110+
subprocess.run( # noqa: S603,PLW1510
111+
[git_path, *args],
112+
cwd=cwd,
113+
**run_kwargs,
114+
),
112115
)
113116

114117

@@ -134,10 +137,13 @@ def run_cargo_command(
134137
"""
135138
cargo_path = get_safe_executable("cargo")
136139
run_kwargs = _build_run_kwargs("run_cargo_command", **kwargs)
137-
return subprocess.run( # noqa: S603,PLW1510
138-
[cargo_path, *args],
139-
cwd=cwd,
140-
**run_kwargs,
140+
return cast(
141+
"subprocess.CompletedProcess[str]",
142+
subprocess.run( # noqa: S603,PLW1510
143+
[cargo_path, *args],
144+
cwd=cwd,
145+
**run_kwargs,
146+
),
141147
)
142148

143149

@@ -165,10 +171,13 @@ def run_safe_command(
165171
"""
166172
command_path = get_safe_executable(command)
167173
run_kwargs = _build_run_kwargs(f"run_safe_command for {command}", **kwargs)
168-
return subprocess.run( # noqa: S603,PLW1510
169-
[command_path, *args],
170-
cwd=cwd,
171-
**run_kwargs,
174+
return cast(
175+
"subprocess.CompletedProcess[str]",
176+
subprocess.run( # noqa: S603,PLW1510
177+
[command_path, *args],
178+
cwd=cwd,
179+
**run_kwargs,
180+
),
172181
)
173182

174183

@@ -279,11 +288,14 @@ def run_git_command_with_input(
279288
with tempfile.TemporaryFile() as stdin:
280289
stdin.write(payload)
281290
stdin.seek(0)
282-
return subprocess.run( # noqa: S603,PLW1510
283-
[git_path, *args],
284-
cwd=cwd,
285-
stdin=stdin,
286-
**run_kwargs,
291+
return cast(
292+
"subprocess.CompletedProcess[str]",
293+
subprocess.run( # noqa: S603,PLW1510
294+
[git_path, *args],
295+
cwd=cwd,
296+
stdin=stdin,
297+
**run_kwargs,
298+
),
287299
)
288300

289301

scripts/tests/test_justfile_discoverability.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,17 @@ def test_update_workflow_composes_scoped_dependency_and_tool_updates() -> None:
7777
"""Update recipes should cover repo state without touching unrelated global tools."""
7878
recipes = just_recipes()
7979
update_dependencies = {dependency["recipe"] for dependency in recipes["update"]["dependencies"]}
80+
dependency_updates = {dependency["recipe"] for dependency in recipes["update-dependencies"]["dependencies"]}
8081

8182
assert update_dependencies == {"update-cargo-tools", "update-dependencies"}
83+
assert dependency_updates == {"update-cargo-dependencies", "update-python-dependencies"}
8284

8385
dependency_result = run_just("--dry-run", "update-dependencies")
8486
dependency_update = dependency_result.stdout + dependency_result.stderr
8587
assert "cargo upgrade" in dependency_update
8688
assert "cargo upgrade --incompatible allow" not in dependency_update
8789
assert "cargo update" in dependency_update
90+
assert "update-python-dev-pins" in dependency_update
8891
assert "uv lock --upgrade" in dependency_update
8992
assert "uv sync --locked --group dev" in dependency_update
9093
assert "cargo install-update --all" not in dependency_update

0 commit comments

Comments
 (0)