Migrate Python guidelines from Poetry to uv
This commit is contained in:
@@ -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
|
Individual guideline documents carry their own `Document Version` header, and the skills carry
|
||||||
`metadata.version`; both are independent of the revisions below.
|
`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 <version>` 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/<name>/` 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
|
## v9 — 2026-10-07
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
+2
-2
@@ -23,6 +23,6 @@ build/
|
|||||||
# dist/
|
# dist/
|
||||||
|
|
||||||
# --- Lock file ---
|
# --- 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.
|
# Libraries do not commit it — uncomment it there.
|
||||||
# poetry.lock
|
# uv.lock
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Python Development Guidelines
|
# Python Development Guidelines
|
||||||
|
|
||||||
**Document Version:** v11
|
**Document Version:** v12
|
||||||
|
|
||||||
> **Note on Versioning:**
|
> **Note on Versioning:**
|
||||||
> - This document version is independent — reused across projects
|
> - 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:
|
Run before every commit:
|
||||||
```bash
|
```bash
|
||||||
poetry run ruff check
|
uv run ruff check
|
||||||
poetry run mypy
|
uv run mypy
|
||||||
poetry run pytest
|
uv run pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Poetry
|
## 11. uv
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
poetry install # Install all dependencies
|
uv sync # Install all dependencies
|
||||||
poetry add <pkg> # Add runtime dependency
|
uv add <pkg> # Add runtime dependency
|
||||||
poetry add --group dev <pkg> # Add dev dependency
|
uv add --dev <pkg> # Add dev dependency
|
||||||
poetry remove <pkg> # Remove dependency
|
uv remove <pkg> # Remove dependency
|
||||||
poetry run <cmd> # Run command in virtualenv
|
uv run <cmd> # Run command in virtualenv
|
||||||
|
uv python install <version> # Install a uv-managed Python
|
||||||
```
|
```
|
||||||
|
|
||||||
Never edit `pyproject.toml` directly to add or remove dependencies.
|
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
|
├── src/ # All application modules
|
||||||
├── tests/ # Tests
|
├── tests/ # Tests
|
||||||
├── docs/ # Detailed documentation
|
├── docs/ # Detailed documentation
|
||||||
├── .venv/ # Virtual environment (managed by Poetry)
|
├── .venv/ # Virtual environment (managed by uv)
|
||||||
└── pyproject.toml # Project config and dependencies
|
└── 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:
|
Build commands:
|
||||||
```bash
|
```bash
|
||||||
poetry run python prebuild.py
|
uv run python prebuild.py
|
||||||
poetry run pyinstaller ToolName.spec
|
uv run pyinstaller ToolName.spec
|
||||||
```
|
```
|
||||||
|
|
||||||
> This section applies only to projects that produce standalone executables. Skip for libraries or web services.
|
> This section applies only to projects that produce standalone executables. Skip for libraries or web services.
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Python Library Development Guidelines
|
# Python Library Development Guidelines
|
||||||
|
|
||||||
**Document Version:** v4
|
**Document Version:** v5
|
||||||
|
|
||||||
> **Note on Versioning:**
|
> **Note on Versioning:**
|
||||||
> - This document version is independent — reused across projects
|
> - This document version is independent — reused across projects
|
||||||
@@ -140,27 +140,30 @@ Define specific exception types in `src/<package>/exceptions.py`. Use a fail-fas
|
|||||||
|
|
||||||
Run before every commit:
|
Run before every commit:
|
||||||
```bash
|
```bash
|
||||||
poetry run ruff check
|
uv run ruff check
|
||||||
poetry run mypy
|
uv run mypy
|
||||||
poetry run pytest
|
uv run pytest
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 11. Poetry
|
## 11. uv
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
poetry install # Install all dependencies
|
uv sync # Install all dependencies
|
||||||
poetry add <pkg> # Add runtime dependency
|
uv add <pkg> # Add runtime dependency
|
||||||
poetry add --group dev <pkg> # Add dev dependency
|
uv add --dev <pkg> # Add dev dependency
|
||||||
poetry remove <pkg> # Remove dependency
|
uv remove <pkg> # Remove dependency
|
||||||
poetry run <cmd> # Run command in virtualenv
|
uv run <cmd> # Run command in virtualenv
|
||||||
poetry build # Build sdist and wheel into dist/
|
uv build # Build sdist and wheel into dist/
|
||||||
poetry publish # Publish to PyPI
|
uv publish # Publish to PyPI
|
||||||
|
uv python install <version> # Install a uv-managed Python
|
||||||
```
|
```
|
||||||
|
|
||||||
Never edit `pyproject.toml` directly to add or remove dependencies.
|
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
|
### pyproject.toml configuration for a library
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
@@ -171,19 +174,20 @@ description = "Short description"
|
|||||||
requires-python = ">=3.x"
|
requires-python = ">=3.x"
|
||||||
dependencies = []
|
dependencies = []
|
||||||
|
|
||||||
[tool.poetry]
|
|
||||||
packages = [{include = "your_library", from = "src"}]
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
requires = ["uv_build>=0.13.0,<0.14.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "uv_build"
|
||||||
```
|
```
|
||||||
|
|
||||||
Do **not** add `[tool.poetry.scripts]` — libraries have no entry points.
|
`uv_build` finds the package at `src/<name>/` 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
|
│ └── ... # Internal modules
|
||||||
├── tests/ # Tests
|
├── tests/ # Tests
|
||||||
├── docs/ # Detailed documentation
|
├── docs/ # Detailed documentation
|
||||||
├── .venv/ # Virtual environment (managed by Poetry)
|
├── .venv/ # Virtual environment (managed by uv)
|
||||||
└── pyproject.toml # Project config and dependencies
|
└── pyproject.toml # Project config and dependencies
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -218,11 +222,11 @@ project/
|
|||||||
|
|
||||||
## 14. Distribution
|
## 14. Distribution
|
||||||
|
|
||||||
Build and publish with Poetry:
|
Build and publish with uv:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
poetry build # Creates dist/*.tar.gz and dist/*.whl
|
uv build # Creates dist/*.tar.gz and dist/*.whl
|
||||||
poetry publish # Publishes to PyPI (requires credentials)
|
uv publish # Publishes to PyPI (requires credentials)
|
||||||
```
|
```
|
||||||
|
|
||||||
`dist/` is **not committed** to the repository — add it to `.gitignore`.
|
`dist/` is **not committed** to the repository — add it to `.gitignore`.
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@ template/
|
|||||||
├── <tool_name>.py # Entry point — named by purpose or tool name
|
├── <tool_name>.py # Entry point — named by purpose or tool name
|
||||||
├── <tool_name>.spec # PyInstaller spec (only for projects shipping an .exe)
|
├── <tool_name>.spec # PyInstaller spec (only for projects shipping an .exe)
|
||||||
├── prebuild.py # Pre-build script: venv check, version print, console= rewrite
|
├── 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/
|
├── docs/
|
||||||
│ └── .gitkeep # Detailed documentation lives here, never in the root
|
│ └── .gitkeep # Detailed documentation lives here, never in the root
|
||||||
├── src/
|
├── 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)
|
- **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`
|
- **Build configuration** via `ENV_BUILD_CONSOLE` and `ENV_BUILD_SPEC` in `.env`, applied by `prebuild.py`
|
||||||
- **loguru** for logging (never print for debugging)
|
- **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)
|
- **pytest** for testing (no unittest)
|
||||||
- **ruff + mypy** for linting and type checking (120-character lines)
|
- **ruff + mypy** for linting and type checking (120-character lines)
|
||||||
|
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ Two rules keep the two sides from drifting apart:
|
|||||||
|
|
||||||
## Key Conventions
|
## 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)
|
- **Rust tooling:** Cargo · rustfmt · clippy · tracing (`thiserror` / `anyhow` for errors)
|
||||||
- **Godot tooling:** gdformat · gdlint · GUT
|
- **Godot tooling:** gdformat · gdlint · GUT
|
||||||
- **No `print()` for debugging** — the language's logging library, everywhere
|
- **No `print()` for debugging** — the language's logging library, everywhere
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ Set these as **user** variables on Windows:
|
|||||||
| Variable | Used by | Value |
|
| Variable | Used by | Value |
|
||||||
|----------|---------|-------|
|
|----------|---------|-------|
|
||||||
| `NODE_EXTRA_CA_CERTS` | Node.js, npm, Electron, VS Code extensions | `C:\certs\ZscalerRootCertificate-2048-SHA256.crt` |
|
| `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 |
|
| `REQUESTS_CA_BUNDLE` | Python `requests`, pip | same path |
|
||||||
| `SSL_CERT_FILE` | OpenSSL, Python `ssl` / `httpx` / `aiohttp` | same path |
|
| `SSL_CERT_FILE` | OpenSSL, Python `ssl` / `httpx` / `aiohttp`, uv | same path |
|
||||||
| `CURL_CA_BUNDLE` | curl | same path |
|
| `CURL_CA_BUNDLE` | curl | same path |
|
||||||
| `CARGO_HTTP_CAINFO` | cargo, crates.io | 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
|
curl -sSI https://pypi.org | head -1
|
||||||
git ls-remote https://github.com/git/git HEAD
|
git ls-remote https://github.com/git/git HEAD
|
||||||
node -e "require('https').get('https://registry.npmjs.org', r => console.log(r.statusCode))"
|
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.
|
All four must succeed without a certificate error.
|
||||||
|
|||||||
Reference in New Issue
Block a user