From 4689cd45bc7bf4321c4585848a51ec154dfd9394 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Doubravsk=C3=BD?= Date: Tue, 13 Oct 2026 17:58:03 +0200 Subject: [PATCH] Migrate Python guidelines from Poetry to uv --- CHANGELOG.md | 21 ++++++++++ Python/.gitignore | 4 +- Python/DESIGN_DOCUMENT_PYTHON.md | 33 +++++++++------- Python/DESIGN_DOCUMENT_PYTHON_MODULE.md | 52 +++++++++++++------------ Python/TEMPLATE.md | 4 +- README.md | 2 +- Zscaler/ZSCALER_CERTIFICATE.md | 6 +-- 7 files changed, 75 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4adea3..459af3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,27 @@ ships documents, so it uses the same `v#` scheme as the documents themselves. Individual guideline documents carry their own `Document Version` header, and the skills carry `metadata.version`; both are independent of the revisions below. +## v10 — 2026-10-13 + +### Changed +- **Python tooling moved from Poetry to uv** — `Python/DESIGN_DOCUMENT_PYTHON.md` v11 → v12 and + `Python/DESIGN_DOCUMENT_PYTHON_MODULE.md` v4 → v5. Section 11 is now "uv": `uv sync`, `uv add`, + `uv add --dev`, `uv remove`, `uv run`, and for libraries `uv build` / `uv publish`. The lock file is + `uv.lock`, with the same rule as before — committed for applications, ignored for libraries +- uv also manages the interpreter — section 11 gained `uv python install ` and states that + the interpreter is a uv-managed Python, no pyenv and no system Python +- The application document's new text is taken from the copy already migrated by hand in Curator, so + that copy and the master are one and the same v12 +- Library `pyproject.toml` example uses the `uv_build` backend in place of `poetry-core`. The + `[tool.poetry] packages` table is gone — `uv_build` finds `src//` by itself — and the ban on + entry points now names `[project.scripts]` +- `Python/TEMPLATE.md`, `Python/.gitignore` and the README conventions line follow: `uv.lock` in place + of `poetry.lock` +- `Zscaler/ZSCALER_CERTIFICATE.md` — uv does not read `REQUESTS_CA_BUNDLE`, so it moved to the + `SSL_CERT_FILE` row; the verification command is `uv run` + +--- + ## v9 — 2026-10-07 ### Added diff --git a/Python/.gitignore b/Python/.gitignore index 0522a36..f04e536 100644 --- a/Python/.gitignore +++ b/Python/.gitignore @@ -23,6 +23,6 @@ build/ # dist/ # --- Lock file --- -# Applications commit poetry.lock — leave the line below commented out. +# Applications commit uv.lock — leave the line below commented out. # Libraries do not commit it — uncomment it there. -# poetry.lock +# uv.lock diff --git a/Python/DESIGN_DOCUMENT_PYTHON.md b/Python/DESIGN_DOCUMENT_PYTHON.md index cee3199..cdbf6c9 100644 --- a/Python/DESIGN_DOCUMENT_PYTHON.md +++ b/Python/DESIGN_DOCUMENT_PYTHON.md @@ -1,6 +1,6 @@ # Python Development Guidelines -**Document Version:** v11 +**Document Version:** v12 > **Note on Versioning:** > - This document version is independent — reused across projects @@ -129,28 +129,31 @@ Define specific exception types. Use a fail-fast approach — surface errors ear Run before every commit: ```bash -poetry run ruff check -poetry run mypy -poetry run pytest +uv run ruff check +uv run mypy +uv run pytest ``` --- -## 11. Poetry +## 11. uv ```bash -poetry install # Install all dependencies -poetry add # Add runtime dependency -poetry add --group dev # Add dev dependency -poetry remove # Remove dependency -poetry run # Run command in virtualenv +uv sync # Install all dependencies +uv add # Add runtime dependency +uv add --dev # Add dev dependency +uv remove # Remove dependency +uv run # Run command in virtualenv +uv python install # Install a uv-managed Python ``` Never edit `pyproject.toml` directly to add or remove dependencies. -### poetry.lock +The interpreter is a uv-managed Python — no pyenv, no system Python. -`poetry.lock` **is committed** for applications — it pins the exact dependency graph and keeps builds reproducible. +### uv.lock + +`uv.lock` **is committed** for applications — it pins the exact dependency graph and keeps builds reproducible. --- @@ -162,7 +165,7 @@ project/ ├── src/ # All application modules ├── tests/ # Tests ├── docs/ # Detailed documentation -├── .venv/ # Virtual environment (managed by Poetry) +├── .venv/ # Virtual environment (managed by uv) └── pyproject.toml # Project config and dependencies ``` @@ -193,8 +196,8 @@ When a project is distributed as a standalone executable (no Python required on Build commands: ```bash -poetry run python prebuild.py -poetry run pyinstaller ToolName.spec +uv run python prebuild.py +uv run pyinstaller ToolName.spec ``` > This section applies only to projects that produce standalone executables. Skip for libraries or web services. diff --git a/Python/DESIGN_DOCUMENT_PYTHON_MODULE.md b/Python/DESIGN_DOCUMENT_PYTHON_MODULE.md index 590a799..b155527 100644 --- a/Python/DESIGN_DOCUMENT_PYTHON_MODULE.md +++ b/Python/DESIGN_DOCUMENT_PYTHON_MODULE.md @@ -1,6 +1,6 @@ # Python Library Development Guidelines -**Document Version:** v4 +**Document Version:** v5 > **Note on Versioning:** > - This document version is independent — reused across projects @@ -140,27 +140,30 @@ Define specific exception types in `src//exceptions.py`. Use a fail-fas Run before every commit: ```bash -poetry run ruff check -poetry run mypy -poetry run pytest +uv run ruff check +uv run mypy +uv run pytest ``` --- -## 11. Poetry +## 11. uv ```bash -poetry install # Install all dependencies -poetry add # Add runtime dependency -poetry add --group dev # Add dev dependency -poetry remove # Remove dependency -poetry run # Run command in virtualenv -poetry build # Build sdist and wheel into dist/ -poetry publish # Publish to PyPI +uv sync # Install all dependencies +uv add # Add runtime dependency +uv add --dev # Add dev dependency +uv remove # Remove dependency +uv run # Run command in virtualenv +uv build # Build sdist and wheel into dist/ +uv publish # Publish to PyPI +uv python install # Install a uv-managed Python ``` Never edit `pyproject.toml` directly to add or remove dependencies. +The interpreter is a uv-managed Python — no pyenv, no system Python. + ### pyproject.toml configuration for a library ```toml @@ -171,19 +174,20 @@ description = "Short description" requires-python = ">=3.x" dependencies = [] -[tool.poetry] -packages = [{include = "your_library", from = "src"}] - [build-system] -requires = ["poetry-core>=2.0.0,<3.0.0"] -build-backend = "poetry.core.masonry.api" +requires = ["uv_build>=0.13.0,<0.14.0"] +build-backend = "uv_build" ``` -Do **not** add `[tool.poetry.scripts]` — libraries have no entry points. +`uv_build` finds the package at `src//` on its own, with the dashes in the project name turned +into underscores — no package list is needed. Keep the upper bound on `uv_build`; `uv init --lib` +writes the range that matches the installed uv. -### poetry.lock +Do **not** add `[project.scripts]` — libraries have no entry points. -Do **not** commit `poetry.lock` for libraries. It is only committed for applications. Add `poetry.lock` to `.gitignore`. +### uv.lock + +Do **not** commit `uv.lock` for libraries. It is only committed for applications. Add `uv.lock` to `.gitignore`. --- @@ -198,7 +202,7 @@ project/ │ └── ... # Internal modules ├── tests/ # Tests ├── docs/ # Detailed documentation -├── .venv/ # Virtual environment (managed by Poetry) +├── .venv/ # Virtual environment (managed by uv) └── pyproject.toml # Project config and dependencies ``` @@ -218,11 +222,11 @@ project/ ## 14. Distribution -Build and publish with Poetry: +Build and publish with uv: ```bash -poetry build # Creates dist/*.tar.gz and dist/*.whl -poetry publish # Publishes to PyPI (requires credentials) +uv build # Creates dist/*.tar.gz and dist/*.whl +uv publish # Publishes to PyPI (requires credentials) ``` `dist/` is **not committed** to the repository — add it to `.gitignore`. diff --git a/Python/TEMPLATE.md b/Python/TEMPLATE.md index b999a2c..f822d61 100644 --- a/Python/TEMPLATE.md +++ b/Python/TEMPLATE.md @@ -14,7 +14,7 @@ template/ ├── .py # Entry point — named by purpose or tool name ├── .spec # PyInstaller spec (only for projects shipping an .exe) ├── prebuild.py # Pre-build script: venv check, version print, console= rewrite -├── pyproject.toml # Poetry config (ruff, mypy, pytest) +├── pyproject.toml # Project config (ruff, mypy, pytest) ├── docs/ │ └── .gitkeep # Detailed documentation lives here, never in the root ├── src/ @@ -36,7 +36,7 @@ copies themselves **are committed** with the project and are never edited in pla - **DEBUG mode** via `ENV_DEBUG=true` in `.env` (adds "DEV" suffix to version: v1.2.3DEV) - **Build configuration** via `ENV_BUILD_CONSOLE` and `ENV_BUILD_SPEC` in `.env`, applied by `prebuild.py` - **loguru** for logging (never print for debugging) -- **Poetry** for dependency management, `poetry.lock` committed +- **uv** for dependency management and Python versions, `uv.lock` committed - **pytest** for testing (no unittest) - **ruff + mypy** for linting and type checking (120-character lines) diff --git a/README.md b/README.md index d149bea..d932216 100644 --- a/README.md +++ b/README.md @@ -147,7 +147,7 @@ Two rules keep the two sides from drifting apart: ## Key Conventions -- **Python tooling:** Poetry · Ruff · mypy · pytest · loguru +- **Python tooling:** uv · Ruff · mypy · pytest · loguru - **Rust tooling:** Cargo · rustfmt · clippy · tracing (`thiserror` / `anyhow` for errors) - **Godot tooling:** gdformat · gdlint · GUT - **No `print()` for debugging** — the language's logging library, everywhere diff --git a/Zscaler/ZSCALER_CERTIFICATE.md b/Zscaler/ZSCALER_CERTIFICATE.md index 3df7768..312f313 100644 --- a/Zscaler/ZSCALER_CERTIFICATE.md +++ b/Zscaler/ZSCALER_CERTIFICATE.md @@ -40,8 +40,8 @@ Set these as **user** variables on Windows: | Variable | Used by | Value | |----------|---------|-------| | `NODE_EXTRA_CA_CERTS` | Node.js, npm, Electron, VS Code extensions | `C:\certs\ZscalerRootCertificate-2048-SHA256.crt` | -| `REQUESTS_CA_BUNDLE` | Python `requests`, Poetry, pip | same path | -| `SSL_CERT_FILE` | OpenSSL, Python `ssl` / `httpx` / `aiohttp` | same path | +| `REQUESTS_CA_BUNDLE` | Python `requests`, pip | same path | +| `SSL_CERT_FILE` | OpenSSL, Python `ssl` / `httpx` / `aiohttp`, uv | same path | | `CURL_CA_BUNDLE` | curl | same path | | `CARGO_HTTP_CAINFO` | cargo, crates.io | same path | @@ -66,7 +66,7 @@ remote, not just the ones behind Zscaler. curl -sSI https://pypi.org | head -1 git ls-remote https://github.com/git/git HEAD node -e "require('https').get('https://registry.npmjs.org', r => console.log(r.statusCode))" -poetry run python -c "import requests; print(requests.get('https://pypi.org', timeout=10).status_code)" +uv run python -c "import requests; print(requests.get('https://pypi.org', timeout=10).status_code)" ``` All four must succeed without a certificate error.