python-env
Fast Python environment management with uv (10-100x faster than pip). Triggers on: uv, venv, pip, pyproject, python environment, install package, dependencies.
Install
npx skills add https://github.com/0xDarkMatter/claude-mods/tree/main/skills/python-env
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install 0xdarkmatter-claude-mods@llmmart
git clone https://github.com/0xDarkMatter/claude-mods.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole 0xdarkmatter/claude-mods collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Python Environment
Fast Python environment management with uv. Prefer the uv project workflow
(uv add / uv sync / uv run) over the uv pip compatibility layer — it
manages pyproject.toml + a lockfile for you and is reproducible.
Quick Commands
| Task | Command |
|---|---|
| Start a project | uv init <name> (app) · uv init --package <name> (installable, src/ layout) |
| Add dependency | uv add httpx |
| Add dev dependency | uv add --dev pytest ruff |
| Remove dependency | uv remove httpx |
| Sync env from lockfile | uv sync |
| Run in project env | uv run pytest |
| Update lockfile | uv lock |
| Install a CLI tool | uv tool install ruff · one-shot: uvx ruff |
| Install a Python | uv python install 3.12 |
Start a Project
# Application (flat layout, no package build)
uv init myapp
# Installable package (src/ layout — separate tests/ that import by name)
uv init --package wordtools
# → src/wordtools/__init__.py, pyproject.toml with build-system
uv init creates pyproject.toml, pins a Python version, and prepares the
project for uv add / uv sync. The --package (src) layout is preferred for
anything with a test suite or that you intend to ship.
Manage Dependencies
# Add runtime deps (writes to [project.dependencies] + updates the lockfile)
uv add "httpx>=0.25" pydantic
# Add dev-only deps (writes to the dev dependency-group)
uv add --dev pytest ruff mypy
# Add with extras
uv add "fastapi[standard]"
# Remove
uv remove httpx
# Install everything from pyproject + uv.lock into .venv (reproducible)
uv sync
# Refresh the lockfile (e.g. after manual pyproject edits)
uv lock
uv creates and manages .venv automatically — you rarely activate it; just
prefix commands with uv run.
Run Code
uv run python script.py # run a script in the project env
uv run pytest # run a tool from the dev group
uv run -- ruff check . # `--` ends uv flag parsing
Never call bare python / pytest / ruff in a uv project — they may resolve
to a different interpreter. Always uv run.
CLI Tools (global, not project deps)
uv tool install ruff # persistent, isolated, on PATH
uv tool upgrade ruff
uvx ruff check . # ephemeral one-shot run, nothing installed
Use uv tool / uvx for developer CLIs (ruff, pre-commit, httpie). Use
uv add only for things your code imports.
Python Versions
uv python install 3.12 # download a managed interpreter
uv python list # show available + installed
uv init --python 3.12 app # pin a project to a version
Check python.org for the current stable (3.14 as of 2026-07; recent releases add
opt-in free-threading and a JIT). 3.11+ is a sensible floor for new projects
(TaskGroup, Self, faster interpreter).
Minimal pyproject.toml
[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"httpx>=0.25",
"pydantic>=2.0",
]
# Dev deps live here; `uv add --dev <pkg>` manages this group.
[dependency-groups]
dev = [
"pytest>=8.0",
"ruff>=0.4",
"mypy>=1.10",
]
Compatibility Layer (uv pip) — last resort
uv pip mirrors pip's interface for environments uv doesn't manage (a hand-made
venv, a legacy requirements.txt, CI that isn't uv-native). It does not
update pyproject.toml or the lockfile — prefer uv add / uv sync whenever
you control the project.
uv venv # bare venv (no project)
uv pip install -r requirements.txt # legacy requirements file
uv pip install -e . # editable install into an unmanaged venv
uv pip compile requirements.in -o requirements.txt # pin a requirements.txt
Troubleshooting
| Issue | Solution |
|---|---|
| "No Python found" | uv python install 3.12 |
| Pin project Python | uv init --python 3.12 or edit requires-python |
| Lock/resolve conflict | uv lock --resolution=lowest-direct to probe, then loosen bounds |
| Stale env after pull | uv sync |
| Cache issues | uv cache clean |
When to Use
- Always use uv over pip — 10-100x faster
uv add/uv remove/uv syncfor project dependencies (notuv pip install)uv runto execute anything inside the project envuv tool install/uvxfor standalone developer CLIsuv piponly for environments uv doesn't manage
Additional Resources
For detailed patterns, load:
./references/pyproject-patterns.md- Full pyproject.toml examples, tool configs./references/dependency-management.md- Lock files, workspaces, private packages./references/publishing.md- PyPI publishing, versioning, CI/CD
See Also
This is a foundation skill with no prerequisites.
Build on this skill:
python-typing-ops- Type hints for projectspython-pytest-ops- Testing infrastructurepython-fastapi-ops- Web API development
Files (claude-mods)
-
assets
-
.gitkeep 0 B · in bundle
-
-
references
-
dependency-management.md 6.5 KB
# Python Dependency Management Advanced patterns for managing Python dependencies with uv. ## Project Lockfile (uv.lock) — preferred For any project with a `pyproject.toml`, uv manages a `uv.lock` automatically. This is the reproducible, uv-native workflow — prefer it over a hand-managed `requirements.txt`. ```bash uv add "flask>=2.0" sqlalchemy # add runtime deps; uv.lock updated uv add --dev pytest ruff mypy # dev-only dependency group uv remove flask # drop a dep uv sync # install exactly from uv.lock uv sync --frozen # CI: fail if uv.lock is stale, don't re-resolve uv lock --upgrade # bump everything within constraints uv lock --upgrade-package flask # bump just one ``` ## requirements.txt Workflow (uv pip compile) Use this only when you specifically need a `requirements.txt` — Docker layer caching, non-uv CI, or legacy tooling. Otherwise prefer `uv.lock` above. ### Basic Lock Pattern ```bash # requirements.in (loose constraints) flask>=2.0 sqlalchemy>=2.0 pydantic>=2.0 # Generate locked requirements.txt uv pip compile requirements.in -o requirements.txt # Install exact versions uv pip sync requirements.txt ``` ### Separate Dev Dependencies ```bash # requirements.in flask>=2.0 sqlalchemy>=2.0 # requirements-dev.in -r requirements.in pytest>=7.0 ruff>=0.1 mypy>=1.0 # Compile both uv pip compile requirements.in -o requirements.txt uv pip compile requirements-dev.in -o requirements-dev.txt # Install for development uv pip sync requirements-dev.txt ``` ### Update Workflow ```bash # Update all packages to latest compatible versions uv pip compile requirements.in -o requirements.txt --upgrade # Update specific package uv pip compile requirements.in -o requirements.txt --upgrade-package flask # Update with constraints uv pip compile requirements.in -o requirements.txt --upgrade --constraint constraints.txt ``` ## Constraint Files ```bash # constraints.txt # Pin versions that need to be consistent across projects numpy==1.26.0 pandas==2.0.0 # Use constraints during compile uv pip compile requirements.in -o requirements.txt --constraint constraints.txt ``` ## Multiple Environments ### Python Version Specific ```bash # Python 3.10 uv pip compile requirements.in -o requirements-py310.txt --python-version 3.10 # Python 3.11 uv pip compile requirements.in -o requirements-py311.txt --python-version 3.11 ``` ### Platform Specific ```bash # Linux uv pip compile requirements.in -o requirements-linux.txt --platform linux # macOS uv pip compile requirements.in -o requirements-macos.txt --platform macos # Windows uv pip compile requirements.in -o requirements-windows.txt --platform windows ``` ## Workspace/Monorepo ### Structure ``` my-monorepo/ ├── pyproject.toml # Root workspace config ├── packages/ │ ├── core/ │ │ └── pyproject.toml │ ├── api/ │ │ └── pyproject.toml │ └── cli/ │ └── pyproject.toml ``` ### Root pyproject.toml ```toml [tool.uv.workspace] members = ["packages/*"] [tool.uv.sources] my-core = { workspace = true } my-api = { workspace = true } ``` ### Package pyproject.toml ```toml # packages/core/pyproject.toml [project] name = "my-core" version = "0.1.0" dependencies = ["pydantic>=2.0"] # packages/api/pyproject.toml [project] name = "my-api" version = "0.1.0" dependencies = ["my-core", "fastapi>=0.100"] ``` ### Workspace Commands ```bash # Install all workspace members into one env (native — no editable pip installs) uv sync # Run a command in the workspace env uv run pytest # Operate on a specific member uv run --package my-api pytest ``` ## Private Packages ### Configure Index (pyproject.toml) ```toml [[tool.uv.index]] name = "private" url = "https://pypi.private.com/simple/" ``` ```bash uv add my-private-package # resolves against configured indexes ``` ### Authentication via environment ```bash # Per-index credentials: UV_INDEX_<NAME>_USERNAME / _PASSWORD export UV_INDEX_PRIVATE_USERNAME=user export UV_INDEX_PRIVATE_PASSWORD=token uv add my-private-package ``` ### requirements.txt workflow ``` --extra-index-url https://pypi.private.com/simple/ my-public-package>=1.0 my-private-package>=2.0 ``` ## Git Dependencies ```toml # In pyproject.toml [project] dependencies = [ "my-package @ git+https://github.com/user/repo.git", "my-package @ git+https://github.com/user/repo.git@v1.0.0", "my-package @ git+https://github.com/user/repo.git@main", "my-package @ git+ssh://git@github.com/user/repo.git", ] ``` ```bash # requirements.in git+https://github.com/user/repo.git@main#egg=my-package ``` ## Local Dependencies ```toml # In pyproject.toml [project] dependencies = [ "my-local @ file:///path/to/package", ] # Relative path [tool.uv.sources] my-local = { path = "../my-local-package" } ``` ## Dependency Resolution ### Resolver Options ```bash # Use backtracking resolver (more thorough but slower) uv pip compile requirements.in -o requirements.txt --resolver=backtracking # Allow prereleases uv pip compile requirements.in -o requirements.txt --prerelease=allow # Exclude specific packages from upgrade uv pip compile requirements.in -o requirements.txt --upgrade --no-upgrade-package numpy ``` ### Resolution Troubleshooting ```bash # Show why a version was chosen uv pip compile requirements.in --verbose # Generate dependency tree uv pip tree # Check for conflicts uv pip check ``` ## Caching ```bash # Clear uv cache uv cache clean # Show cache location uv cache dir # Disable cache for one command uv pip install --no-cache package-name ``` ## CI/CD Patterns ### GitHub Actions ```yaml - name: Install uv uses: astral-sh/setup-uv@v5 - name: Install dependencies run: uv sync --frozen - name: Run tests run: uv run pytest ``` ### Cache Dependencies ```yaml - name: Cache uv uses: actions/cache@v3 with: path: ~/.cache/uv key: uv-${{ hashFiles('uv.lock') }} restore-keys: uv- ``` ### Lock File in CI ```yaml - name: Verify lock file is up to date run: uv lock --check ``` ## Best Practices 1. **Always use lock files in production** - Reproducible builds 2. **Separate dev dependencies** - Smaller production installs 3. **Use constraints for shared deps** - Consistent versions across packages 4. **Pin Python version** - Avoid compatibility surprises 5. **Run `uv pip check`** - Catch conflicts early 6. **Cache in CI** - Faster builds 7. **Review upgrades carefully** - Don't blindly `--upgrade` -
publishing.md 5.1 KB
# Publishing Python Packages Publish packages to PyPI with modern tooling. ## pyproject.toml for Publishing ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-package" version = "0.1.0" description = "My awesome package" readme = "README.md" license = {file = "LICENSE"} authors = [ {name = "Your Name", email = "you@example.com"}, ] keywords = ["keyword1", "keyword2"] classifiers = [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] requires-python = ">=3.10" dependencies = [ "requests>=2.28", "pydantic>=2.0", ] # Dev tooling → dependency-groups (PEP 735); not shipped with the package. [dependency-groups] dev = [ "pytest>=8.0", "pytest-cov>=5.0", "ruff>=0.4", "mypy>=1.10", ] [project.urls] Homepage = "https://github.com/username/my-package" Documentation = "https://my-package.readthedocs.io" Repository = "https://github.com/username/my-package" Changelog = "https://github.com/username/my-package/blob/main/CHANGELOG.md" [project.scripts] my-command = "my_package.cli:main" [project.entry-points."my_package.plugins"] plugin1 = "my_package.plugins:Plugin1" ``` ## Build and Upload ```bash # Build sdist + wheel — uv has a native builder, no separate `build` install uv build # Check build artifacts ls dist/ # my_package-0.1.0-py3-none-any.whl # my_package-0.1.0.tar.gz # Verify + upload with twine via uvx (ephemeral, nothing installed globally) uvx twine check dist/* # Upload to TestPyPI first uvx twine upload --repository testpypi dist/* # Test installation from TestPyPI into a throwaway env uv pip install --index-url https://test.pypi.org/simple/ my-package # Upload to PyPI (production) uvx twine upload dist/* ``` ## Version Management ### Option 1: Manual version ```toml [project] version = "0.1.0" ``` ### Option 2: Dynamic from __init__.py ```toml [project] dynamic = ["version"] [tool.hatch.version] path = "src/my_package/__init__.py" ``` ```python # src/my_package/__init__.py __version__ = "0.1.0" ``` ### Option 3: Git tags with hatch-vcs ```toml [project] dynamic = ["version"] [tool.hatch.version] source = "vcs" [build-system] requires = ["hatchling", "hatch-vcs"] build-backend = "hatchling.build" ``` ```bash # Create version tag git tag -a v0.1.0 -m "Release 0.1.0" git push origin v0.1.0 ``` ## Semantic Versioning ``` MAJOR.MINOR.PATCH Examples: 0.1.0 - Initial development 0.2.0 - New features (minor) 0.2.1 - Bug fixes (patch) 1.0.0 - First stable release 1.1.0 - New features, backwards compatible 2.0.0 - Breaking changes ``` ## Changelog (CHANGELOG.md) ```markdown # Changelog All notable changes to this project will be documented in this file. ## [Unreleased] ### Added - New feature X ### Changed - Updated dependency Y ### Fixed - Bug in Z ## [0.1.0] - 2024-01-15 ### Added - Initial release - Core functionality [Unreleased]: https://github.com/user/repo/compare/v0.1.0...HEAD [0.1.0]: https://github.com/user/repo/releases/tag/v0.1.0 ``` ## GitHub Actions CI/CD ```yaml # .github/workflows/publish.yml name: Publish to PyPI on: release: types: [published] jobs: publish: runs-on: ubuntu-latest permissions: id-token: write # For trusted publishing steps: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v5 - name: Build package run: uv build - name: Publish to PyPI uses: pypa/gh-action-pypi-publish@release/v1 # Uses trusted publishing - no token needed ``` ## PyPI Configuration ### ~/.pypirc (for twine) ```ini [pypi] username = __token__ password = pypi-xxxx... [testpypi] repository = https://test.pypi.org/legacy/ username = __token__ password = pypi-xxxx... ``` ### Trusted Publishing (Recommended) 1. Go to PyPI → Your project → Publishing 2. Add new trusted publisher 3. Set GitHub repo and workflow file 4. No API token needed in CI ## Source Distribution Layout ``` my-package/ ├── pyproject.toml ├── README.md ├── LICENSE ├── CHANGELOG.md ├── src/ │ └── my_package/ │ ├── __init__.py │ └── core.py └── tests/ └── test_core.py ``` ## Quick Reference | Command | Purpose | |---------|---------| | `uv build` | Build wheel and sdist (native, no `build` install) | | `uvx twine check dist/*` | Verify package | | `uvx twine upload dist/*` | Upload to PyPI | | `uvx twine upload --repository testpypi dist/*` | Upload to TestPyPI | | Version | When | |---------|------| | 0.x.x | Initial development | | x.0.0 | Breaking changes | | x.x.0 | New features | | x.x.x | Bug fixes | ## Checklist Before Publishing ```markdown - [ ] Version updated in pyproject.toml - [ ] CHANGELOG.md updated - [ ] README.md current - [ ] All tests passing - [ ] Type checks passing - [ ] Build succeeds locally - [ ] TestPyPI upload works - [ ] Installation from TestPyPI works ``` -
pyproject-patterns.md 6.1 KB
# pyproject.toml Patterns Comprehensive patterns for Python project configuration. ## Minimal Project ```toml [project] name = "my-project" version = "0.1.0" requires-python = ">=3.11" dependencies = [ "httpx>=0.25", "pydantic>=2.0", ] ``` ## Standard Library Project ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-package" version = "0.1.0" description = "A short description of the project" readme = "README.md" license = "MIT" requires-python = ">=3.11" authors = [ { name = "Your Name", email = "you@example.com" } ] keywords = ["keyword1", "keyword2"] classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] dependencies = [ "httpx>=0.25", "pydantic>=2.0", "rich>=13.0", ] # Dev tooling → dependency-groups (PEP 735). `uv add --dev <pkg>` writes here; # `uv sync` installs it by default. Not shipped with the published package. [dependency-groups] dev = [ "pytest>=8.0", "pytest-asyncio>=0.23", "pytest-cov>=5.0", "ruff>=0.4", "mypy>=1.10", ] # Opt-in extras users install explicitly: `uv add "my-package[docs]"` [project.optional-dependencies] docs = [ "mkdocs>=1.5", "mkdocs-material>=9.0", ] [project.scripts] my-cli = "my_package.cli:main" [project.urls] Homepage = "https://github.com/username/my-package" Documentation = "https://my-package.readthedocs.io" Repository = "https://github.com/username/my-package" Issues = "https://github.com/username/my-package/issues" ``` ## CLI Application ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-cli" version = "0.1.0" requires-python = ">=3.11" dependencies = [ "typer>=0.9", "rich>=13.0", ] [project.scripts] mycli = "my_cli.main:app" [dependency-groups] dev = ["pytest", "ruff"] ``` ## FastAPI Application ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [project] name = "my-api" version = "0.1.0" requires-python = ">=3.11" dependencies = [ "fastapi>=0.100", "uvicorn[standard]>=0.23", "pydantic>=2.0", "sqlalchemy>=2.0", "alembic>=1.12", "python-dotenv>=1.0", ] [dependency-groups] dev = [ "pytest>=8.0", "pytest-asyncio>=0.23", "httpx>=0.25", # for testing "ruff>=0.4", "mypy>=1.10", ] ``` ## Tool Configurations ### Ruff (Linting + Formatting) ```toml [tool.ruff] line-length = 100 target-version = "py311" exclude = [ ".git", ".venv", "__pycache__", "dist", "build", ] [tool.ruff.lint] select = [ "E", # pycodestyle errors "W", # pycodestyle warnings "F", # pyflakes "I", # isort "UP", # pyupgrade "B", # flake8-bugbear "C4", # flake8-comprehensions "DTZ", # flake8-datetimez "T10", # flake8-debugger "FA", # flake8-future-annotations "ISC", # flake8-implicit-str-concat "PIE", # flake8-pie "PT", # flake8-pytest-style "Q", # flake8-quotes "RSE", # flake8-raise "RET", # flake8-return "SIM", # flake8-simplify "TID", # flake8-tidy-imports "TCH", # flake8-type-checking "ARG", # flake8-unused-arguments "PTH", # flake8-use-pathlib "RUF", # Ruff-specific rules ] ignore = [ "E501", # line too long (handled by formatter) "B008", # do not perform function calls in argument defaults ] [tool.ruff.lint.per-file-ignores] "tests/**" = ["S101"] # Allow assert in tests [tool.ruff.lint.isort] known-first-party = ["my_package"] ``` ### pytest ```toml [tool.pytest.ini_options] testpaths = ["tests"] python_files = ["test_*.py"] python_functions = ["test_*"] addopts = [ "-ra", "-q", "--strict-markers", "--strict-config", ] markers = [ "slow: marks tests as slow", "integration: marks tests as integration tests", ] asyncio_mode = "auto" filterwarnings = [ "error", "ignore::DeprecationWarning", ] ``` ### mypy ```toml [tool.mypy] python_version = "3.11" strict = true warn_return_any = true warn_unused_ignores = true disallow_untyped_defs = true disallow_incomplete_defs = true check_untyped_defs = true disallow_untyped_decorators = true no_implicit_optional = true warn_redundant_casts = true warn_unreachable = true [[tool.mypy.overrides]] module = "tests.*" disallow_untyped_defs = false [[tool.mypy.overrides]] module = ["httpx.*", "pydantic.*"] ignore_missing_imports = true ``` ### Coverage ```toml [tool.coverage.run] source = ["my_package"] branch = true omit = [ "*/__pycache__/*", "*/tests/*", ] [tool.coverage.report] exclude_lines = [ "pragma: no cover", "def __repr__", "raise NotImplementedError", "if TYPE_CHECKING:", "if __name__ == .__main__.:", ] fail_under = 80 show_missing = true ``` ## Build Systems ### Hatchling (Recommended) ```toml [build-system] requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] packages = ["src/my_package"] [tool.hatch.version] path = "src/my_package/__init__.py" ``` ### Setuptools ```toml [build-system] requires = ["setuptools>=61.0", "wheel"] build-backend = "setuptools.build_meta" [tool.setuptools.packages.find] where = ["src"] ``` ### Poetry (pyproject.toml native) ```toml [tool.poetry] name = "my-package" version = "0.1.0" description = "" authors = ["Your Name <you@example.com>"] readme = "README.md" [tool.poetry.dependencies] python = "^3.10" httpx = "^0.25" [tool.poetry.group.dev.dependencies] pytest = "^7.0" ruff = "^0.1" [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" ``` ## Version Management ### Static Version ```toml [project] version = "0.1.0" ``` ### Dynamic Version (from file) ```toml [project] dynamic = ["version"] [tool.hatch.version] path = "src/my_package/__init__.py" # Reads: __version__ = "0.1.0" ``` ### Dynamic Version (from VCS) ```toml [project] dynamic = ["version"] [tool.hatch.version] source = "vcs" [tool.hatch.build.hooks.vcs] version-file = "src/my_package/_version.py" ```
-
-
scripts
-
.gitkeep 0 B · in bundle
-
-
SKILL.md 5.2 KB
--- name: python-env description: "Fast Python environment management with uv (10-100x faster than pip). Triggers on: uv, venv, pip, pyproject, python environment, install package, dependencies." license: MIT compatibility: "Requires uv CLI tool. Install: curl -LsSf https://astral.sh/uv/install.sh | sh" allowed-tools: "Bash" metadata: author: claude-mods --- # Python Environment Fast Python environment management with uv. Prefer the uv **project** workflow (`uv add` / `uv sync` / `uv run`) over the `uv pip` compatibility layer — it manages `pyproject.toml` + a lockfile for you and is reproducible. ## Quick Commands | Task | Command | |------|---------| | Start a project | `uv init <name>` (app) · `uv init --package <name>` (installable, `src/` layout) | | Add dependency | `uv add httpx` | | Add dev dependency | `uv add --dev pytest ruff` | | Remove dependency | `uv remove httpx` | | Sync env from lockfile | `uv sync` | | Run in project env | `uv run pytest` | | Update lockfile | `uv lock` | | Install a CLI tool | `uv tool install ruff` · one-shot: `uvx ruff` | | Install a Python | `uv python install 3.12` | ## Start a Project ```bash # Application (flat layout, no package build) uv init myapp # Installable package (src/ layout — separate tests/ that import by name) uv init --package wordtools # → src/wordtools/__init__.py, pyproject.toml with build-system ``` `uv init` creates `pyproject.toml`, pins a Python version, and prepares the project for `uv add` / `uv sync`. The `--package` (src) layout is preferred for anything with a test suite or that you intend to ship. ## Manage Dependencies ```bash # Add runtime deps (writes to [project.dependencies] + updates the lockfile) uv add "httpx>=0.25" pydantic # Add dev-only deps (writes to the dev dependency-group) uv add --dev pytest ruff mypy # Add with extras uv add "fastapi[standard]" # Remove uv remove httpx # Install everything from pyproject + uv.lock into .venv (reproducible) uv sync # Refresh the lockfile (e.g. after manual pyproject edits) uv lock ``` `uv` creates and manages `.venv` automatically — you rarely activate it; just prefix commands with `uv run`. ## Run Code ```bash uv run python script.py # run a script in the project env uv run pytest # run a tool from the dev group uv run -- ruff check . # `--` ends uv flag parsing ``` Never call bare `python` / `pytest` / `ruff` in a uv project — they may resolve to a different interpreter. Always `uv run`. ## CLI Tools (global, not project deps) ```bash uv tool install ruff # persistent, isolated, on PATH uv tool upgrade ruff uvx ruff check . # ephemeral one-shot run, nothing installed ``` Use `uv tool` / `uvx` for developer CLIs (ruff, pre-commit, httpie). Use `uv add` only for things your code imports. ## Python Versions ```bash uv python install 3.12 # download a managed interpreter uv python list # show available + installed uv init --python 3.12 app # pin a project to a version ``` Check python.org for the current stable (3.14 as of 2026-07; recent releases add opt-in free-threading and a JIT). 3.11+ is a sensible floor for new projects (TaskGroup, `Self`, faster interpreter). ## Minimal pyproject.toml ```toml [project] name = "my-project" version = "0.1.0" requires-python = ">=3.11" dependencies = [ "httpx>=0.25", "pydantic>=2.0", ] # Dev deps live here; `uv add --dev <pkg>` manages this group. [dependency-groups] dev = [ "pytest>=8.0", "ruff>=0.4", "mypy>=1.10", ] ``` ## Compatibility Layer (`uv pip`) — last resort `uv pip` mirrors pip's interface for environments uv doesn't manage (a hand-made venv, a legacy `requirements.txt`, CI that isn't uv-native). It does **not** update `pyproject.toml` or the lockfile — prefer `uv add` / `uv sync` whenever you control the project. ```bash uv venv # bare venv (no project) uv pip install -r requirements.txt # legacy requirements file uv pip install -e . # editable install into an unmanaged venv uv pip compile requirements.in -o requirements.txt # pin a requirements.txt ``` ## Troubleshooting | Issue | Solution | |-------|----------| | "No Python found" | `uv python install 3.12` | | Pin project Python | `uv init --python 3.12` or edit `requires-python` | | Lock/resolve conflict | `uv lock --resolution=lowest-direct` to probe, then loosen bounds | | Stale env after pull | `uv sync` | | Cache issues | `uv cache clean` | ## When to Use - **Always** use uv over pip — 10-100x faster - `uv add` / `uv remove` / `uv sync` for project dependencies (not `uv pip install`) - `uv run` to execute anything inside the project env - `uv tool install` / `uvx` for standalone developer CLIs - `uv pip` only for environments uv doesn't manage ## Additional Resources For detailed patterns, load: - `./references/pyproject-patterns.md` - Full pyproject.toml examples, tool configs - `./references/dependency-management.md` - Lock files, workspaces, private packages - `./references/publishing.md` - PyPI publishing, versioning, CI/CD --- ## See Also This is a **foundation skill** with no prerequisites. **Build on this skill:** - `python-typing-ops` - Type hints for projects - `python-pytest-ops` - Testing infrastructure - `python-fastapi-ops` - Web API development
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.