Files
Stirling-PDF/scripts/pre-commit/whitespace.py
T
05eb74022a chore(ci): migrate Python tooling to uv and standardize workflow execution (#7386)
# Description of Changes

This PR modernizes the project's Python tooling across GitHub Actions by
migrating CI workflows from pip-based dependency management to `uv` and
aligning Python execution with the engine project's managed environment.

### What was changed

- Replaced `actions/setup-python` and ad-hoc `pip install` steps with
`astral-sh/setup-uv` across CI workflows.
- Configured shared `uv` dependency caching using
`engine/pyproject.toml` and `engine/uv.lock`.
- Updated Python script execution to use `uv run --project engine
--locked` for a consistent runtime environment.
- Replaced package installation steps with `uv sync` for the required
dependency groups (e.g. `tools` and `cucumber`).
- Added Docker image build validation for both production and
development AI engine images.
- Updated workflow cache configuration and Docker build context where
required.
- Removed obsolete Python requirements files that are no longer needed
after the migration.
- Applied minor Python code modernizations, including import cleanup,
modern built-in generic type annotations (`list[...]`, `tuple[...]`,
`float | None`), and small style improvements.
- Removed unnecessary Python formatter/linter extensions from the
development container configuration.

### Why the change was made

- Standardize Python dependency management across the repository.
- Reduce duplicated dependency installation logic in CI.
- Improve workflow performance through shared dependency caching.
- Ensure all Python utilities execute against the same locked dependency
set managed by the engine project.
- Simplify long-term maintenance by eliminating legacy requirements
files and pip-specific workflow steps.


---

## Checklist

### General

- [ ] I have read the [Contribution
Guidelines](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/CONTRIBUTING.md)
- [ ] I have read the [Stirling-PDF Developer
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md)
(if applicable)
- [ ] I have read the [How to add new languages to
Stirling-PDF](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md)
(if applicable)
- [ ] I have performed a self-review of my own code
- [ ] My changes generate no new warnings

### Documentation

- [ ] I have updated relevant docs on [Stirling-PDF's doc
repo](https://github.com/Stirling-Tools/Stirling-Tools.github.io/blob/main/docs/)
(if functionality has heavily changed)
- [ ] I have read the section [Add New Translation
Tags](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/devGuide/HowToAddNewLanguage.md#add-new-translation-tags)
(for new translation tags only)

### Translations (if applicable)

- [ ] I ran
[`scripts/counter_translation.py`](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/docs/counter_translation.md)

### UI Changes (if applicable)

- [ ] Screenshots or videos demonstrating the UI changes are attached
(e.g., as comments or direct attachments in the PR)

### Testing (if applicable)

- [ ] I have run `task check` to verify linters, typechecks, and tests
pass
- [ ] I have tested my changes locally. Refer to the [Testing
Guide](https://github.com/Stirling-Tools/Stirling-PDF/blob/main/DeveloperGuide.md#7-testing)
for more details.

---------

Signed-off-by: Carsten Drewes <c.drewes@stud.uni-hannover.de>
Co-authored-by: albanobattistella <34811668+albanobattistella@users.noreply.github.com>
Co-authored-by: kastenherri <116314318+kastenherri@users.noreply.github.com>
Co-authored-by: Anthony Stirling <77850077+Frooodle@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: James Brunton <jbrunton96@gmail.com>
2026-08-11 08:09:21 +00:00

78 lines
2.3 KiB
Python

#!/usr/bin/env python3
"""Trailing-whitespace and end-of-file normalisation, driven by Task.
Replaces the end-of-file-fixer / trailing-whitespace pre-commit hooks, which
have no read-only mode. Run via `task pre-commit` (check) and `task
pre-commit:fix`.
Takes git pathspecs (not a file list) and runs `git ls-files` itself, so the
matched files never hit the command line - on Windows that list can be ~66KB
and exceed the ~32KB CreateProcess argv limit.
python whitespace.py <pathspec>... # check: report, exit 1 if any need fixing
python whitespace.py --fix <pathspec>... # fix: rewrite in place
Operates on bytes and only ever touches trailing spaces/tabs and the final
newline, so it never mangles content or line endings. Binary files (those with
a NUL byte) are skipped.
"""
from __future__ import annotations
import subprocess
import sys
from pathlib import Path
def tracked_files(pathspecs: list[str]) -> list[str]:
result = subprocess.run(
["git", "ls-files", "-z", *pathspecs],
check=True,
capture_output=True,
text=True,
)
return [path for path in result.stdout.split("\0") if path]
def normalise(data: bytes) -> bytes:
# Strip trailing spaces/tabs from each line (leave \r so CRLF survives).
lines = [line.rstrip(b" \t") for line in data.split(b"\n")]
body = b"\n".join(lines)
# Ensure a non-empty file ends with exactly one newline.
stripped = body.rstrip(b"\r\n")
if not stripped:
return body
newline = b"\r\n" if data.endswith(b"\r\n") else b"\n"
return stripped + newline
def main() -> int:
args = sys.argv[1:]
fix = "--fix" in args
pathspecs = [a for a in args if a != "--fix"]
offenders: list[str] = []
for path in tracked_files(pathspecs):
data = Path(path).read_bytes()
if b"\0" in data:
continue
fixed = normalise(data)
if fixed == data:
continue
offenders.append(path)
if fix:
Path(path).write_bytes(fixed)
if offenders and not fix:
print(f"{len(offenders)} file(s) need whitespace fixing:")
for path in offenders:
print(f" {path}")
return 1
if offenders and fix:
print(f"Fixed whitespace in {len(offenders)} file(s).")
return 0
if __name__ == "__main__":
sys.exit(main())