4611 lines
108 KiB
Markdown
4611 lines
108 KiB
Markdown
---
|
|
title: "Tool and Library Registry"
|
|
version: "1.1.0"
|
|
date: "2025-11-17"
|
|
purpose: "Comprehensive registry of tools, libraries, and frameworks for opinionated Python development with template variable system for pyproject.toml"
|
|
sources:
|
|
- "skill-metadata/pattern-extraction.md (Section 3)"
|
|
- "skill-metadata/taxonomy.md (Section 8)"
|
|
- "skill-metadata/discovery/* (13 discovery reports)"
|
|
python_versions: ["3.11", "3.12", "3.13", "3.14"]
|
|
---
|
|
|
|
# Tool and Library Registry
|
|
|
|
Comprehensive catalog of development tools, testing frameworks, CLI libraries, data processing utilities, and MCP tools for modern Python 3.11+ development.
|
|
|
|
**Coverage**: 50+ tools across 10 categories **Sources**: Pattern extraction analysis, taxonomy organization, 13 agent discovery reports **User Requirements**: datasette, arrow, fabric, shiv, httpx, prefect, boltons, blinker, paho-mqtt, robotframework, copier, pytest, prospector, pre-commit, mypy, bandit, ruff, uv, hatchling
|
|
|
|
---
|
|
|
|
## 1. Tool Categories Overview
|
|
|
|
### Category Matrix
|
|
|
|
| Category | Tool Count | Mandatory Tools | Optional Tools | Use Cases |
|
|
| --- | --- | --- | --- | --- |
|
|
| Development Tools | 8 | uv, ruff, mypy, pyright | prospector, bandit | Package management, linting, type checking |
|
|
| Testing Tools | 9 | pytest, pytest-mock, pytest-cov | hypothesis, mutmut, robotframework | Unit tests, BDD, mutation testing |
|
|
| CLI Frameworks | 4 | typer, argparse | textual, click | Human-facing CLIs, portable scripts, TUIs |
|
|
| Data Libraries | 5 | - | datasette, arrow, httpx, requests | Data exploration, time handling, HTTP clients |
|
|
| Workflow Tools | 4 | - | prefect, fabric, copier, invoke | Orchestration, automation, templating |
|
|
| IoT/Messaging | 2 | - | paho-mqtt, blinker | MQTT messaging, signals/events |
|
|
| Build Tools | 4 | uv | hatchling, shiv, pip-tools | Package building, executable creation |
|
|
| Quality Tools | 4 | pre-commit, ruff | prospector, bandit | Code quality gates, security scanning |
|
|
| Utility Libraries | 3 | - | boltons, pydantic, structlog | General utilities, validation, logging |
|
|
| MCP Tools | 8 | - | context7, ref, exa, github | Documentation lookup, code search, reasoning |
|
|
|
|
---
|
|
|
|
## 2. Development Tools
|
|
|
|
### 2.1 uv (Package Manager & Script Executor)
|
|
|
|
```yaml
|
|
tool_name: uv
|
|
category: development
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "curl -LsSf https://astral.sh/uv/install.sh | sh"
|
|
purpose: "Modern Python package manager and PEP 723 script executor"
|
|
mandatory: true
|
|
scenarios:
|
|
- All Python development
|
|
- PEP 723 script execution
|
|
- Package installation
|
|
- Virtual environment management
|
|
alternatives:
|
|
- pip + pip-tools + virtualenv (legacy, NOT recommended)
|
|
- poetry (different approach, heavier)
|
|
- pdm (alternative modern tool)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for PEP 723 scripts (shebang requirement)
|
|
- Primary package manager for all projects
|
|
- Replaces pip, pip-tools, virtualenv, pipx
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Install packages
|
|
uv add requests pydantic
|
|
|
|
# Add development dependencies
|
|
uv add --dev pytest mypy ruff
|
|
|
|
# Run PEP 723 script
|
|
uv run --script script.py
|
|
|
|
# Create virtual environment
|
|
uv venv
|
|
|
|
# Sync dependencies from pyproject.toml
|
|
uv sync
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Works with pyproject.toml for dependency management
|
|
- Executes PEP 723 scripts via shebang
|
|
- Compatible with pre-commit hooks
|
|
- Faster than pip for all operations
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# pyproject.toml - Minimal dependency declaration example
|
|
# NOTE: Replace ALL {{template_variables}} with actual values before creating file
|
|
[project]
|
|
name = "{{project_name_from_directory_or_git_remote}}"
|
|
version = "{{version_from_git_tag_or_default_0_1_0}}"
|
|
dependencies = [
|
|
"typer>=0.19.2",
|
|
"pydantic>=2.0.0",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=8.0.0",
|
|
"mypy>=1.11.0",
|
|
"ruff>=0.6.0",
|
|
]
|
|
|
|
[tool.hatchling.build.targets.wheel]
|
|
packages = ["packages/{{package_name_from_project_name}}"]
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- PEP 723 (inline script metadata)
|
|
- PEP 621 (project metadata)
|
|
- Pattern: All Python agents require uv
|
|
|
|
**Source**: pattern-extraction.md Section 3.1, all discovery reports
|
|
|
|
---
|
|
|
|
### 2.2 ruff (Linting & Formatting)
|
|
|
|
```yaml
|
|
tool_name: ruff
|
|
category: development
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev ruff"
|
|
purpose: "Extremely fast Python linter and formatter replacing flake8, black, isort"
|
|
mandatory: true
|
|
scenarios:
|
|
- All Python code validation
|
|
- Pre-commit hooks
|
|
- CI/CD pipelines
|
|
- Linting error investigation
|
|
alternatives:
|
|
- flake8 + black + isort (legacy, slower)
|
|
- pylint (comprehensive but slower)
|
|
- prospector (multi-tool wrapper)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all Python code before delivery
|
|
- Layer 2 of validation pipeline
|
|
- Pre-commit hook integration
|
|
- CI/CD quality gates
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Check code
|
|
uv run ruff check .
|
|
|
|
# Fix auto-fixable issues
|
|
uv run ruff check --fix .
|
|
|
|
# Format code
|
|
uv run ruff format .
|
|
|
|
# Get rule documentation
|
|
ruff rule ANN201
|
|
|
|
# Check specific files (rare - usually run on .)
|
|
uv run ruff check path/to/file.py
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Pre-commit: Automatic linting on git commits
|
|
- Linting-root-cause-resolver: Uses `ruff rule {CODE}` for investigation
|
|
- Mypy/Pyright: Complementary type checking
|
|
- pytest: Can check test code
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# pyproject.toml
|
|
[tool.ruff]
|
|
target-version = "py311"
|
|
line-length = 100
|
|
|
|
[tool.ruff.lint]
|
|
select = [
|
|
"E", # pycodestyle errors
|
|
"W", # pycodestyle warnings
|
|
"F", # pyflakes
|
|
"I", # isort
|
|
"N", # pep8-naming
|
|
"UP", # pyupgrade
|
|
"ANN", # flake8-annotations
|
|
"ASYNC", # flake8-async
|
|
"S", # flake8-bandit
|
|
"B", # flake8-bugbear
|
|
"A", # flake8-builtins
|
|
"C4", # flake8-comprehensions
|
|
"DTZ", # flake8-datetimez
|
|
"T10", # flake8-debugger
|
|
"EM", # flake8-errmsg
|
|
"ISC", # flake8-implicit-str-concat
|
|
"ICN", # flake8-import-conventions
|
|
"G", # flake8-logging-format
|
|
"PIE", # flake8-pie
|
|
"T20", # flake8-print
|
|
"PYI", # flake8-pyi
|
|
"PT", # flake8-pytest-style
|
|
"Q", # flake8-quotes
|
|
"RSE", # flake8-raise
|
|
"RET", # flake8-return
|
|
"SLF", # flake8-self
|
|
"SIM", # flake8-simplify
|
|
"TID", # flake8-tidy-imports
|
|
"TCH", # flake8-type-checking
|
|
"ARG", # flake8-unused-arguments
|
|
"PTH", # flake8-use-pathlib
|
|
"ERA", # eradicate
|
|
"PD", # pandas-vet
|
|
"PGH", # pygrep-hooks
|
|
"PL", # pylint
|
|
"TRY", # tryceratops
|
|
"NPY", # numpy-specific rules
|
|
"RUF", # ruff-specific rules
|
|
]
|
|
|
|
ignore = [
|
|
"ANN101", # Missing type annotation for self
|
|
"ANN102", # Missing type annotation for cls
|
|
]
|
|
|
|
[tool.ruff.lint.per-file-ignores]
|
|
"tests/**/*.py" = [
|
|
"S101", # Allow assert in tests
|
|
"ANN201", # No return type required for test functions
|
|
]
|
|
```
|
|
|
|
**Common Patterns**:
|
|
|
|
```python
|
|
# REQUIRED: No legacy typing imports
|
|
# ruff will flag: from typing import List, Dict, Optional
|
|
|
|
# REQUIRED: Use native generics
|
|
def process(items: list[str]) -> dict[str, int]: # ✓
|
|
pass
|
|
|
|
# FORBIDDEN: Legacy typing
|
|
from typing import List, Dict
|
|
def process(items: List[str]) -> Dict[str, int]: # ✗
|
|
pass
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- NEVER suppress with # noqa comments
|
|
- Use linting-root-cause-resolver for root cause fixes
|
|
- ANN\* rules enforce type annotations
|
|
- PYI\* rules for stub files
|
|
|
|
**Source**: pattern-extraction.md Section 3.1, linting-root-cause-resolver-analysis.md
|
|
|
|
---
|
|
|
|
### 2.3 mypy (Static Type Checker)
|
|
|
|
```yaml
|
|
tool_name: mypy
|
|
category: development
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev mypy"
|
|
purpose: "Static type checker for Python with strict mode enforcement"
|
|
mandatory: true
|
|
scenarios:
|
|
- All Python code type validation
|
|
- Layer 3 of validation pipeline
|
|
- CI/CD type safety gates
|
|
- Pre-commit hooks
|
|
alternatives:
|
|
- pyright (Microsoft, also recommended)
|
|
- pyre (Facebook, less common)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all Python code
|
|
- Layer 3 of validation pipeline (after ruff)
|
|
- Use `--strict` mode exclusively
|
|
- Run before pyright for additional checks
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Check with strict mode
|
|
uv run mypy --strict .
|
|
|
|
# Generate HTML report
|
|
uv run mypy --html-report mypy-report .
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Ruff: Complementary linting
|
|
- Pyright: Run both for comprehensive checking
|
|
- pytest: Type-check test code
|
|
- Pre-commit: Automatic type checking
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# pyproject.toml
|
|
[tool.mypy]
|
|
python_version = "3.11"
|
|
strict = true
|
|
warn_return_any = true
|
|
warn_unused_configs = true
|
|
disallow_untyped_defs = true
|
|
disallow_any_unimported = true
|
|
no_implicit_optional = true
|
|
warn_redundant_casts = true
|
|
warn_unused_ignores = true
|
|
warn_no_return = true
|
|
check_untyped_defs = true
|
|
|
|
[[tool.mypy.overrides]]
|
|
module = "tests.*"
|
|
disallow_untyped_defs = false # Allow untyped test functions
|
|
```
|
|
|
|
**Common Patterns**:
|
|
|
|
```python
|
|
# REQUIRED: Complete type annotations
|
|
def authenticate_user(username: str, password: str) -> AuthResult:
|
|
"""Authenticate user credentials."""
|
|
pass
|
|
|
|
# REQUIRED: Generator fixtures with full typing
|
|
from typing import Generator
|
|
from pytest import fixture
|
|
|
|
@fixture
|
|
def database_connection() -> Generator[Connection, None, None]:
|
|
"""Provide database connection."""
|
|
conn = connect_to_db()
|
|
yield conn
|
|
conn.close()
|
|
|
|
# REQUIRED: Modern union syntax
|
|
def get_user(user_id: int) -> User | None: # ✓
|
|
pass
|
|
|
|
# FORBIDDEN: Legacy Optional
|
|
from typing import Optional
|
|
def get_user(user_id: int) -> Optional[User]: # ✗
|
|
pass
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Python 3.11+ native generics required
|
|
- Strict mode is MANDATORY
|
|
- All functions must have return type annotations
|
|
- Pattern: Run mypy before pyright
|
|
|
|
**Source**: pattern-extraction.md Section 1.2, taxonomy.md Section 6.1
|
|
|
|
---
|
|
|
|
### 2.4 pyright (Static Type Checker)
|
|
|
|
```yaml
|
|
tool_name: pyright
|
|
category: development
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pyright"
|
|
purpose: "Microsoft's static type checker with strict mode"
|
|
mandatory: true
|
|
scenarios:
|
|
- All Python code type validation
|
|
- Layer 3 of validation pipeline (with mypy)
|
|
- VS Code integration
|
|
- CI/CD type safety gates
|
|
alternatives:
|
|
- mypy (also recommended, run both)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all Python code
|
|
- Run after mypy for comprehensive coverage
|
|
- Use strict mode exclusively
|
|
- Complements mypy with different checks
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Check with strict mode (prefer basedpyright for CI native reports)
|
|
uv run basedpyright .
|
|
|
|
# Or standard pyright
|
|
uv run pyright .
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- VS Code: Built-in Pylance extension uses pyright
|
|
- basedpyright: Fork with native CI output formats (GitLab, GitHub)
|
|
- Mypy: Run both for best coverage
|
|
- Ruff: Complementary linting
|
|
- Pre-commit: Automatic type checking
|
|
|
|
**Configuration**:
|
|
|
|
```json
|
|
// pyrightconfig.json
|
|
{
|
|
"pythonVersion": "3.11",
|
|
"typeCheckingMode": "strict",
|
|
"reportMissingTypeStubs": true,
|
|
"reportImportCycles": true,
|
|
"reportUnusedImport": true,
|
|
"reportUnusedClass": true,
|
|
"reportUnusedFunction": true,
|
|
"reportUnusedVariable": true,
|
|
"reportDuplicateImport": true,
|
|
"reportPrivateUsage": true,
|
|
"reportConstantRedefinition": true,
|
|
"reportIncompatibleMethodOverride": true,
|
|
"reportIncompatibleVariableOverride": true,
|
|
"reportInconsistentConstructor": true,
|
|
"reportMissingParameterType": true,
|
|
"reportMissingTypeArgument": true,
|
|
"reportUnnecessaryCast": true,
|
|
"reportUnnecessaryComparison": true,
|
|
"reportUnnecessaryContains": true,
|
|
"reportUnnecessaryIsInstance": true
|
|
}
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Use strict mode only
|
|
- Complements mypy checks
|
|
- Pattern: mypy then pyright in validation pipeline
|
|
|
|
**Source**: pattern-extraction.md Section 1.2, taxonomy.md Section 6.4
|
|
|
|
---
|
|
|
|
### 2.5 pre-commit (Git Hooks)
|
|
|
|
```yaml
|
|
tool_name: pre-commit
|
|
category: development
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pre-commit"
|
|
purpose: "Git hook framework for running quality checks before commits"
|
|
mandatory: true
|
|
scenarios:
|
|
- All Python projects
|
|
- Layer 6 integration validation
|
|
- CI/CD pre-flight checks
|
|
- Team quality enforcement
|
|
alternatives:
|
|
- Manual script execution (NOT recommended)
|
|
- Custom git hooks (harder to maintain)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all Python projects
|
|
- Layer 6 of validation pipeline
|
|
- Install hooks: `pre-commit install`
|
|
- Run before commits: `pre-commit run --files <files>`
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Install hooks
|
|
uv run pre-commit install
|
|
|
|
# Run on all files
|
|
uv run pre-commit run --all-files
|
|
|
|
# Run on specific files (rare)
|
|
uv run pre-commit run --files path/to/file.py
|
|
|
|
# Update hook versions
|
|
uv run pre-commit autoupdate
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Ruff: Automatic linting and formatting
|
|
- Mypy: Type checking before commit
|
|
- Pyright: Additional type checks
|
|
- pytest: Run tests before commit
|
|
|
|
**Configuration**:
|
|
|
|
```yaml
|
|
# .pre-commit-config.yaml
|
|
repos:
|
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
rev: v0.6.0
|
|
hooks:
|
|
- id: ruff
|
|
args: [--fix]
|
|
- id: ruff-format
|
|
|
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
rev: v1.11.0
|
|
hooks:
|
|
- id: mypy
|
|
args: [--strict]
|
|
additional_dependencies:
|
|
- types-requests
|
|
- pydantic
|
|
|
|
- repo: local
|
|
hooks:
|
|
- id: basedpyright
|
|
name: basedpyright
|
|
entry: uv run basedpyright
|
|
language: system
|
|
types: [python]
|
|
pass_filenames: false
|
|
|
|
- id: pytest-check
|
|
name: pytest
|
|
entry: uv run pytest
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
```
|
|
|
|
**Common Patterns**:
|
|
|
|
```bash
|
|
# Standard workflow
|
|
git add file.py
|
|
uv run pre-commit run --files file.py # Run checks
|
|
git commit -m "Add feature" # Auto-runs hooks
|
|
|
|
# Fix issues - use pre-commit for consistency
|
|
uv run pre-commit run --all-files
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- MUST pass all hooks before commit
|
|
- NEVER skip hooks without justification
|
|
- Pattern: Automated quality enforcement
|
|
|
|
**Source**: pattern-extraction.md Section 3.5, taxonomy.md Section 6.4
|
|
|
|
---
|
|
|
|
### 2.6 prospector (Multi-Tool Linter)
|
|
|
|
```yaml
|
|
tool_name: prospector
|
|
category: development
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev prospector[with_everything]"
|
|
purpose: "Multi-tool wrapper combining pylint, pep8, pyflakes, mccabe, and more"
|
|
mandatory: false
|
|
scenarios:
|
|
- Comprehensive code analysis
|
|
- Legacy codebase auditing
|
|
- Security scanning
|
|
- Complexity analysis
|
|
alternatives:
|
|
- ruff + mypy + bandit (recommended modern stack)
|
|
- Individual tools separately
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Optional for comprehensive analysis
|
|
- Legacy code evaluation
|
|
- NOT recommended as primary linter (use ruff)
|
|
- Useful for one-off deep analysis
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Run all checks
|
|
prospector
|
|
|
|
# With specific tools
|
|
prospector --with-tool bandit --with-tool mccabe
|
|
|
|
# Output to file
|
|
prospector --output-format json > report.json
|
|
|
|
# Strictness levels
|
|
prospector --strictness high
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Combines: pylint, pep8, pyflakes, mccabe, dodgy, pep257, vulture
|
|
- Can run bandit for security
|
|
- Ruff replaces most prospector functionality
|
|
|
|
**Configuration**:
|
|
|
|
```yaml
|
|
# .prospector.yaml
|
|
strictness: high
|
|
test-warnings: true
|
|
doc-warnings: true
|
|
|
|
pylint:
|
|
run: true
|
|
disable:
|
|
- too-few-public-methods
|
|
|
|
pep8:
|
|
run: true
|
|
max-line-length: 100
|
|
|
|
mccabe:
|
|
run: true
|
|
max-complexity: 10
|
|
|
|
bandit:
|
|
run: true
|
|
```
|
|
|
|
**Comparison with ruff**:
|
|
|
|
- Ruff: Faster, modern, single tool
|
|
- Prospector: Comprehensive, slower, multiple tools
|
|
- Recommendation: Use ruff + mypy + bandit instead
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 2.7 bandit (Security Scanner)
|
|
|
|
```yaml
|
|
tool_name: bandit
|
|
category: development
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev bandit"
|
|
purpose: "Security-focused static analysis tool for Python"
|
|
mandatory: false
|
|
scenarios:
|
|
- Security-critical code
|
|
- Compliance requirements (HIPAA, PCI-DSS, GDPR)
|
|
- Pre-production security audits
|
|
- CI/CD security gates
|
|
alternatives:
|
|
- ruff (has some security rules via flake8-bandit)
|
|
- semgrep (broader security scanning)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for security-critical code
|
|
- Recommended for all production code
|
|
- CI/CD security scanning
|
|
- Compliance requirement validation
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Scan directory
|
|
bandit -r packages/
|
|
|
|
# Skip specific tests
|
|
bandit -r packages/ -s B101,B601
|
|
|
|
# Output formats
|
|
bandit -r packages/ -f json -o report.json
|
|
bandit -r packages/ -f html -o report.html
|
|
|
|
# Severity levels
|
|
bandit -r packages/ -ll # Low confidence + Low severity
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Ruff: Some overlap with flake8-bandit rules
|
|
- Pre-commit: Security scanning before commit
|
|
- CI/CD: Fail pipeline on high-severity issues
|
|
|
|
**Configuration**:
|
|
|
|
```yaml
|
|
# .bandit
|
|
tests:
|
|
- B201 # flask_debug_true
|
|
- B301 # pickle
|
|
- B302 # marshal
|
|
- B303 # md5
|
|
- B304 # ciphers
|
|
- B305 # cipher_modes
|
|
- B306 # mktemp_q
|
|
- B307 # eval
|
|
- B308 # mark_safe
|
|
- B309 # httpsconnection
|
|
- B310 # urllib_urlopen
|
|
- B311 # random
|
|
- B312 # telnetlib
|
|
- B313 # xml_bad_cElementTree
|
|
- B314 # xml_bad_ElementTree
|
|
- B315 # xml_bad_expatreader
|
|
- B316 # xml_bad_expatbuilder
|
|
- B317 # xml_bad_sax
|
|
- B318 # xml_bad_minidom
|
|
- B319 # xml_bad_pulldom
|
|
- B320 # xml_bad_etree
|
|
- B321 # ftplib
|
|
- B323 # unverified_context
|
|
- B324 # hashlib_new_insecure_functions
|
|
- B325 # tempnam
|
|
- B401 # import_telnetlib
|
|
- B402 # import_ftplib
|
|
- B403 # import_pickle
|
|
- B404 # import_subprocess
|
|
- B405 # import_xml_etree
|
|
- B406 # import_xml_sax
|
|
- B407 # import_xml_expat
|
|
- B408 # import_xml_minidom
|
|
- B409 # import_xml_pulldom
|
|
- B410 # import_lxml
|
|
- B411 # import_xmlrpclib
|
|
- B412 # import_httpoxy
|
|
- B501 # request_with_no_cert_validation
|
|
- B502 # ssl_with_bad_version
|
|
- B503 # ssl_with_bad_defaults
|
|
- B504 # ssl_with_no_version
|
|
- B505 # weak_cryptographic_key
|
|
- B506 # yaml_load
|
|
- B507 # ssh_no_host_key_verification
|
|
- B601 # paramiko_calls
|
|
- B602 # shell_true
|
|
- B603 # subprocess_without_shell_equals_true
|
|
- B604 # any_other_function_with_shell_equals_true
|
|
- B605 # start_process_with_a_shell
|
|
- B606 # start_process_with_no_shell
|
|
- B607 # start_process_with_partial_path
|
|
- B608 # hardcoded_sql_expressions
|
|
- B609 # wildcard_injection
|
|
|
|
exclude_dirs:
|
|
- /tests/
|
|
- /venv/
|
|
```
|
|
|
|
**Common Patterns**:
|
|
|
|
```python
|
|
# AVOID: Hardcoded passwords
|
|
password = "secret123" # B105
|
|
|
|
# PREFER: Environment variables
|
|
import os
|
|
password = os.getenv("DB_PASSWORD")
|
|
|
|
# AVOID: Shell injection
|
|
subprocess.run(f"ls {user_input}", shell=True) # B602
|
|
|
|
# PREFER: Parameterized commands
|
|
subprocess.run(["ls", user_input], shell=False)
|
|
|
|
# AVOID: Insecure random
|
|
import random
|
|
token = random.randint(0, 1000000) # B311
|
|
|
|
# PREFER: Cryptographically secure random
|
|
import secrets
|
|
token = secrets.token_hex(16)
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- MANDATORY for payment processing
|
|
- MANDATORY for authentication code
|
|
- MANDATORY for data validation
|
|
- Pattern: Security-first development
|
|
|
|
**Source**: User requirements list, pattern-extraction.md Section 4
|
|
|
|
---
|
|
|
|
## 3. Testing Tools
|
|
|
|
### 3.1 pytest (Test Framework)
|
|
|
|
```yaml
|
|
tool_name: pytest
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pytest"
|
|
purpose: "Modern Python testing framework with fixtures and plugins"
|
|
mandatory: true
|
|
scenarios:
|
|
- All Python testing
|
|
- Unit tests
|
|
- Integration tests
|
|
- E2E tests
|
|
- API testing
|
|
alternatives:
|
|
- unittest (stdlib, NOT recommended)
|
|
- nose2 (deprecated)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all Python testing
|
|
- NEVER use unittest
|
|
- Layer 4 of validation pipeline
|
|
- Minimum 80% code coverage required
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Run all tests (coverage via pyproject.toml config)
|
|
uv run pytest
|
|
|
|
# Verbose output
|
|
uv run pytest -v
|
|
|
|
# Run specific test file
|
|
uv run pytest tests/test_auth.py
|
|
|
|
# Run specific test function
|
|
uv run pytest tests/test_auth.py::test_login
|
|
|
|
# Run tests matching pattern
|
|
uv run pytest -k "auth"
|
|
|
|
# Show print statements
|
|
uv run pytest -s
|
|
|
|
# Stop on first failure
|
|
uv run pytest -x
|
|
|
|
# Show local variables on failure
|
|
uv run pytest -l
|
|
|
|
# Run last failed tests
|
|
uv run pytest --lf
|
|
|
|
# Run failed tests first
|
|
uv run pytest --ff
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- pytest-cov: Coverage reporting
|
|
- pytest-mock: Mocking (MANDATORY)
|
|
- pytest-asyncio: Async test support
|
|
- pytest-bdd: BDD/Gherkin tests
|
|
- hypothesis: Property-based testing
|
|
- mutmut: Mutation testing
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# pyproject.toml
|
|
[tool.pytest.ini_options]
|
|
testpaths = ["tests"]
|
|
python_files = ["test_*.py"]
|
|
python_classes = ["Test*"]
|
|
python_functions = ["test_*"]
|
|
addopts = [
|
|
"-v",
|
|
"--strict-markers",
|
|
"--strict-config",
|
|
"--cov=packages",
|
|
"--cov-report=term-missing",
|
|
"--cov-report=html",
|
|
"--cov-fail-under=80",
|
|
]
|
|
markers = [
|
|
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
|
|
"integration: marks tests as integration tests",
|
|
"unit: marks tests as unit tests",
|
|
]
|
|
```
|
|
|
|
**Common Patterns**:
|
|
|
|
```python
|
|
# REQUIRED: AAA pattern (Arrange-Act-Assert)
|
|
def test_user_authentication() -> None:
|
|
"""Test user authentication with valid credentials.
|
|
|
|
Tests: Authentication system
|
|
How: Create user, attempt login, verify token
|
|
Why: Core security validation
|
|
"""
|
|
# Arrange
|
|
user = create_test_user("test@example.com", "Pass123!")
|
|
|
|
# Act
|
|
response = authenticate(user.email, "Pass123!")
|
|
|
|
# Assert
|
|
assert response.success
|
|
assert response.token is not None
|
|
assert response.expires_at > datetime.now()
|
|
|
|
# REQUIRED: Type annotations
|
|
def test_data_processing(tmp_path: Path) -> None:
|
|
"""Test data processing with temporary files."""
|
|
pass
|
|
|
|
# REQUIRED: Comprehensive docstrings
|
|
def test_edge_case_handling() -> None:
|
|
"""Test handling of empty input data.
|
|
|
|
Tests: Data validation module
|
|
How: Pass empty list, verify graceful handling
|
|
Why: Prevent runtime errors on edge cases
|
|
"""
|
|
result = process_data([])
|
|
assert result.success is False
|
|
assert "empty" in result.error.lower()
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- MANDATORY 80% coverage minimum
|
|
- AAA pattern required
|
|
- Type hints on all test functions
|
|
- Comprehensive docstrings
|
|
- Pattern: pytest-architect creates tests
|
|
|
|
**Source**: pattern-extraction.md Section 1.3, pytest-architect-analysis.md
|
|
|
|
---
|
|
|
|
### 3.2 pytest-mock (Mocking Framework)
|
|
|
|
```yaml
|
|
tool_name: pytest-mock
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pytest-mock"
|
|
purpose: "Thin wrapper around unittest.mock providing pytest fixtures"
|
|
mandatory: true
|
|
scenarios:
|
|
- All mocking in tests
|
|
- External service mocking
|
|
- Database mocking
|
|
- API client mocking
|
|
alternatives:
|
|
- unittest.mock (FORBIDDEN - never use directly)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all mocking
|
|
- NEVER use unittest.mock directly
|
|
- Use `mocker: MockerFixture` parameter
|
|
- Replaces @patch decorators
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
from pytest_mock import MockerFixture
|
|
|
|
def test_external_api(mocker: MockerFixture) -> None:
|
|
"""Test external API integration with mock."""
|
|
# Mock external service
|
|
mock_response = mocker.Mock()
|
|
mock_response.status_code = 200
|
|
mock_response.json.return_value = {"status": "ok"}
|
|
|
|
mock_get = mocker.patch("requests.get", return_value=mock_response)
|
|
|
|
# Test code that uses requests.get
|
|
result = fetch_data("https://api.example.com")
|
|
|
|
# Verify
|
|
assert result["status"] == "ok"
|
|
mock_get.assert_called_once_with("https://api.example.com")
|
|
|
|
def test_database_operations(mocker: MockerFixture) -> None:
|
|
"""Test database operations with mocked connection."""
|
|
# Mock database connection
|
|
mock_conn = mocker.Mock()
|
|
mock_cursor = mocker.Mock()
|
|
mock_conn.cursor.return_value = mock_cursor
|
|
mock_cursor.fetchall.return_value = [("user1",), ("user2",)]
|
|
|
|
mocker.patch("psycopg2.connect", return_value=mock_conn)
|
|
|
|
# Test
|
|
users = get_all_users()
|
|
|
|
# Verify
|
|
assert users == ["user1", "user2"]
|
|
mock_conn.cursor.assert_called_once()
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- pytest: Provides MockerFixture
|
|
- Type checkers: Full type hint support
|
|
- Fixtures: Can be used in fixture composition
|
|
|
|
**Common Patterns**:
|
|
|
|
```python
|
|
# REQUIRED: Use mocker parameter
|
|
def test_with_mock(mocker: MockerFixture) -> None: # ✓
|
|
mock = mocker.patch("module.function")
|
|
|
|
# FORBIDDEN: Direct unittest.mock import
|
|
from unittest.mock import patch # ✗
|
|
@patch("module.function")
|
|
def test_with_patch(mock):
|
|
pass
|
|
|
|
# REQUIRED: mocker.Mock() not Mock()
|
|
def test_mock_object(mocker: MockerFixture) -> None:
|
|
mock_obj = mocker.Mock() # ✓
|
|
mock_obj.method.return_value = 42
|
|
|
|
# REQUIRED: mocker.spy() for partial mocking
|
|
def test_spy_on_method(mocker: MockerFixture) -> None:
|
|
obj = MyClass()
|
|
spy = mocker.spy(obj, "method")
|
|
obj.method("arg")
|
|
spy.assert_called_once_with("arg")
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- NEVER import from unittest.mock
|
|
- ALWAYS use mocker parameter
|
|
- Type hint as MockerFixture
|
|
- Pattern: pytest-architect enforces this
|
|
|
|
**Source**: pattern-extraction.md Section 2.2, pytest-architect-analysis.md
|
|
|
|
---
|
|
|
|
### 3.3 pytest-cov (Coverage Reporting)
|
|
|
|
```yaml
|
|
tool_name: pytest-cov
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pytest-cov"
|
|
purpose: "Coverage.py plugin for pytest with comprehensive reporting"
|
|
mandatory: true
|
|
scenarios:
|
|
- All Python testing
|
|
- Coverage measurement
|
|
- CI/CD quality gates
|
|
- Coverage-driven development
|
|
alternatives:
|
|
- coverage.py (pytest-cov wraps this)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all Python projects
|
|
- Minimum 80% coverage required
|
|
- Critical code: 95%+ coverage required
|
|
- Layer 4 validation with pytest
|
|
|
|
**Basic Usage**:
|
|
|
|
Coverage is configured in `pyproject.toml` - no CLI flags needed:
|
|
|
|
```bash
|
|
# Run tests with coverage (config-driven)
|
|
uv run pytest
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- pytest: Native plugin integration
|
|
- CI/CD: Generate reports for pipeline
|
|
- Coverage.py: Underlying engine
|
|
- Mutation testing: Complements mutmut
|
|
|
|
**Configuration** (MANDATORY - coverage in config, not CLI):
|
|
|
|
```toml
|
|
# pyproject.toml
|
|
[tool.pytest.ini_options]
|
|
addopts = [
|
|
"--cov=packages",
|
|
"--cov-report=term-missing",
|
|
"--cov-report=html:htmlcov",
|
|
"--cov-fail-under=80",
|
|
]
|
|
|
|
[tool.coverage.run]
|
|
source = ["packages"]
|
|
omit = [
|
|
"*/tests/*",
|
|
"*/test_*.py",
|
|
"*/__init__.py",
|
|
]
|
|
branch = true
|
|
|
|
[tool.coverage.report]
|
|
fail_under = 80
|
|
show_missing = true
|
|
skip_covered = false
|
|
exclude_lines = [
|
|
"pragma: no cover",
|
|
"def __repr__",
|
|
"raise AssertionError",
|
|
"raise NotImplementedError",
|
|
"if __name__ == .__main__.:",
|
|
"if TYPE_CHECKING:",
|
|
"@abstractmethod",
|
|
"@overload",
|
|
]
|
|
|
|
[tool.coverage.html]
|
|
directory = "htmlcov"
|
|
```
|
|
|
|
**Coverage Standards**:
|
|
|
|
```python
|
|
# General code: 80% minimum
|
|
# Critical code: 95%+ required
|
|
|
|
# Coverage excludes
|
|
def __repr__(self) -> str: # pragma: no cover
|
|
"""String representation."""
|
|
return f"User({self.name})"
|
|
|
|
# Type checking blocks
|
|
if TYPE_CHECKING: # pragma: no cover
|
|
from .models import User
|
|
|
|
# Abstract methods
|
|
@abstractmethod
|
|
def process(self) -> None: # pragma: no cover
|
|
"""Process data."""
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- MANDATORY 80% general code
|
|
- MANDATORY 95%+ critical code
|
|
- Pattern: Testing pyramid distribution
|
|
- Source: Coverage gates in validation pipeline
|
|
|
|
**Source**: pattern-extraction.md Section 1.3, taxonomy.md Section 6.2
|
|
|
|
---
|
|
|
|
### 3.4 hypothesis (Property-Based Testing)
|
|
|
|
```yaml
|
|
tool_name: hypothesis
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev hypothesis"
|
|
purpose: "Property-based testing framework for generating test cases"
|
|
mandatory: false
|
|
scenarios:
|
|
- Data validation testing
|
|
- Algorithm correctness
|
|
- Edge case discovery
|
|
- Fuzzing inputs
|
|
alternatives:
|
|
- Manual parametrization (less comprehensive)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- RECOMMENDED for all projects
|
|
- ESPECIALLY emphasized in pytest-architect
|
|
- Data validation and sanitization
|
|
- Complex algorithm testing
|
|
- Discovering edge cases
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
from hypothesis import given, strategies as st
|
|
|
|
@given(st.integers())
|
|
def test_absolute_value_always_positive(n: int) -> None:
|
|
"""Test that absolute value is always positive."""
|
|
assert abs(n) >= 0
|
|
|
|
@given(st.lists(st.integers()))
|
|
def test_reverse_twice_is_identity(lst: list[int]) -> None:
|
|
"""Test that reversing twice returns original list."""
|
|
assert list(reversed(list(reversed(lst)))) == lst
|
|
|
|
@given(st.text(min_size=1, max_size=100))
|
|
def test_email_validation(email_input: str) -> None:
|
|
"""Test email validation with various inputs."""
|
|
result = validate_email(email_input)
|
|
# Property: valid emails have @ symbol
|
|
if result.is_valid:
|
|
assert "@" in email_input
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- pytest: Native integration
|
|
- pytest-cov: Coverage of generated cases
|
|
- Type hints: Strategy inference
|
|
|
|
**Advanced Patterns**:
|
|
|
|
```python
|
|
from hypothesis import given, strategies as st, assume
|
|
from datetime import date, timedelta
|
|
|
|
# Custom strategies
|
|
email_strategy = st.builds(
|
|
lambda name, domain: f"{name}@{domain}",
|
|
name=st.text(min_size=1, max_size=20, alphabet=st.characters(whitelist_categories=("Ll", "Nd"))),
|
|
domain=st.sampled_from(["example.com", "test.org", "demo.net"])
|
|
)
|
|
|
|
@given(email_strategy)
|
|
def test_email_domain_validation(email: str) -> None:
|
|
"""Test email domain validation."""
|
|
result = validate_email_domain(email)
|
|
assert result.domain in ["example.com", "test.org", "demo.net"]
|
|
|
|
# Composite strategies
|
|
@st.composite
|
|
def date_range(draw):
|
|
"""Generate valid date range."""
|
|
start = draw(st.dates())
|
|
days = draw(st.integers(min_value=1, max_value=365))
|
|
end = start + timedelta(days=days)
|
|
return (start, end)
|
|
|
|
@given(date_range())
|
|
def test_date_range_processing(dates: tuple[date, date]) -> None:
|
|
"""Test date range processing."""
|
|
start, end = dates
|
|
assert start <= end
|
|
```
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# pyproject.toml
|
|
[tool.pytest.ini_options]
|
|
markers = [
|
|
"hypothesis: property-based tests using hypothesis",
|
|
]
|
|
|
|
# Add hypothesis profile
|
|
[tool.hypothesis]
|
|
max_examples = 100
|
|
derandomize = true
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Emphasized in pytest-architect
|
|
- Recommended for data validation
|
|
- Pattern: Property-based testing
|
|
|
|
**Source**: pytest-architect-analysis.md Section 4.1
|
|
|
|
---
|
|
|
|
### 3.5 mutmut (Mutation Testing)
|
|
|
|
```yaml
|
|
tool_name: mutmut
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev mutmut"
|
|
purpose: "Mutation testing tool to verify test suite quality"
|
|
mandatory: false
|
|
scenarios:
|
|
- Critical business logic
|
|
- Payment processing
|
|
- Authentication/authorization
|
|
- Security-critical code
|
|
- Compliance code (HIPAA, PCI-DSS, GDPR)
|
|
alternatives:
|
|
- cosmic-ray (alternative mutation tester)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for critical code:
|
|
- Payment processing
|
|
- Authentication/authorization
|
|
- Security-critical code
|
|
- Data validation and sanitization
|
|
- Regulatory compliance code
|
|
- Complex algorithms
|
|
- Core libraries
|
|
- Target: 100% mutation score (kill all mutants)
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Run mutation testing
|
|
mutmut run
|
|
|
|
# Show results
|
|
mutmut results
|
|
|
|
# Show specific mutant
|
|
mutmut show 1
|
|
|
|
# Apply specific mutant (for debugging)
|
|
mutmut apply 1
|
|
|
|
# Run tests after applying mutant
|
|
pytest
|
|
|
|
# Revert mutant
|
|
mutmut apply --revert
|
|
|
|
# Run on specific paths
|
|
mutmut run --paths-to-mutate=packages/auth/
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- pytest: Uses pytest to run tests
|
|
- Coverage: Complements code coverage
|
|
- CI/CD: Critical code quality gate
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# setup.cfg or pyproject.toml
|
|
[mutmut]
|
|
paths_to_mutate = packages/
|
|
backup = false
|
|
runner = pytest
|
|
tests_dir = tests/
|
|
```
|
|
|
|
**Common Patterns**:
|
|
|
|
```python
|
|
# Example: Payment processing (MANDATORY mutation testing)
|
|
def calculate_total(items: list[Item], tax_rate: float) -> Decimal:
|
|
"""Calculate order total with tax.
|
|
|
|
CRITICAL: Payment processing - mutation tested.
|
|
"""
|
|
subtotal = sum(item.price * item.quantity for item in items)
|
|
tax = subtotal * Decimal(str(tax_rate))
|
|
total = subtotal + tax
|
|
return total.quantize(Decimal("0.01"))
|
|
|
|
# Tests MUST kill all mutants:
|
|
# - Operator changes (+ to -, * to /)
|
|
# - Number changes (tax_rate to 0, to 1)
|
|
# - Decimal precision changes
|
|
# - Boundary conditions
|
|
|
|
def test_calculate_total_normal() -> None:
|
|
"""Test normal calculation."""
|
|
items = [Item(price=Decimal("10.00"), quantity=2)]
|
|
total = calculate_total(items, 0.08)
|
|
assert total == Decimal("21.60") # 20.00 + 1.60 tax
|
|
|
|
def test_calculate_total_zero_tax() -> None:
|
|
"""Test with zero tax rate."""
|
|
items = [Item(price=Decimal("10.00"), quantity=1)]
|
|
total = calculate_total(items, 0.0)
|
|
assert total == Decimal("10.00")
|
|
|
|
def test_calculate_total_precision() -> None:
|
|
"""Test decimal precision handling."""
|
|
items = [Item(price=Decimal("10.99"), quantity=1)]
|
|
total = calculate_total(items, 0.08)
|
|
assert total == Decimal("11.87") # Rounds correctly
|
|
```
|
|
|
|
**Mutation Score Interpretation**:
|
|
|
|
- 100%: All mutants killed (perfect)
|
|
- 90-99%: Excellent test coverage
|
|
- 80-89%: Good, some gaps
|
|
- <80%: Insufficient testing for critical code
|
|
|
|
**Related Standards**:
|
|
|
|
- MANDATORY for critical code
|
|
- Target: 100% mutation score
|
|
- Pattern: Complements code coverage
|
|
|
|
**Source**: pattern-extraction.md Section 2.7, pytest-architect-analysis.md
|
|
|
|
---
|
|
|
|
### 3.6 robotframework (Acceptance Testing)
|
|
|
|
```yaml
|
|
tool_name: robotframework
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev robotframework"
|
|
purpose: "Keyword-driven acceptance testing framework"
|
|
mandatory: false
|
|
scenarios:
|
|
- BDD acceptance tests
|
|
- E2E testing
|
|
- Non-technical stakeholder tests
|
|
- Keyword-driven testing
|
|
alternatives:
|
|
- pytest-bdd (Python-native BDD)
|
|
- behave (Gherkin-based BDD)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Optional for acceptance testing
|
|
- E2E test scenarios
|
|
- Non-technical stakeholder involvement
|
|
- Keyword-driven test approach
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Run tests
|
|
robot tests/
|
|
|
|
# Run specific test file
|
|
robot tests/login.robot
|
|
|
|
# Run with tags
|
|
robot --include smoke tests/
|
|
|
|
# Generate reports
|
|
robot --outputdir reports tests/
|
|
```
|
|
|
|
**Example Test**:
|
|
|
|
```robotframework
|
|
*** Settings ***
|
|
Library SeleniumLibrary
|
|
|
|
*** Variables ***
|
|
${URL} https://example.com
|
|
${BROWSER} Chrome
|
|
|
|
*** Test Cases ***
|
|
User Can Login With Valid Credentials
|
|
[Documentation] Test successful login flow
|
|
[Tags] smoke login
|
|
Open Browser ${URL} ${BROWSER}
|
|
Input Text id:username testuser
|
|
Input Text id:password TestPass123!
|
|
Click Button id:login
|
|
Page Should Contain Welcome, testuser
|
|
[Teardown] Close Browser
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- pytest: Can run alongside pytest
|
|
- Selenium: Web automation
|
|
- CI/CD: Generate XML reports
|
|
|
|
**Related Standards**:
|
|
|
|
- Alternative to pytest-bdd
|
|
- Pattern: Acceptance testing layer
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 3.7 pytest-asyncio (Async Testing)
|
|
|
|
```yaml
|
|
tool_name: pytest-asyncio
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pytest-asyncio"
|
|
purpose: "Pytest support for testing async code"
|
|
mandatory: false
|
|
scenarios:
|
|
- FastAPI testing
|
|
- Async function testing
|
|
- Concurrent operation testing
|
|
- AsyncIO-based applications
|
|
alternatives:
|
|
- pytest-trio (Trio async framework)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Required for async/await code testing
|
|
- FastAPI endpoint testing
|
|
- Async database operations
|
|
- Concurrent task testing
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
from app import app
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_async_endpoint() -> None:
|
|
"""Test async API endpoint."""
|
|
async with AsyncClient(app=app, base_url="http://test") as client:
|
|
response = await client.get("/users/1")
|
|
assert response.status_code == 200
|
|
assert response.json()["id"] == 1
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_concurrent_operations() -> None:
|
|
"""Test concurrent async operations."""
|
|
import asyncio
|
|
|
|
async def fetch_user(user_id: int) -> dict:
|
|
# Simulate async operation
|
|
await asyncio.sleep(0.1)
|
|
return {"id": user_id}
|
|
|
|
# Test concurrent execution
|
|
results = await asyncio.gather(
|
|
fetch_user(1),
|
|
fetch_user(2),
|
|
fetch_user(3),
|
|
)
|
|
|
|
assert len(results) == 3
|
|
assert results[0]["id"] == 1
|
|
```
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# pyproject.toml
|
|
[tool.pytest.ini_options]
|
|
asyncio_mode = "auto"
|
|
markers = [
|
|
"asyncio: mark test as async",
|
|
]
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Use @pytest.mark.asyncio decorator
|
|
- Type hint async functions
|
|
- Pattern: FastAPI testing
|
|
|
|
**Source**: pytest-architect-analysis.md Section 4.3
|
|
|
|
---
|
|
|
|
### 3.8 pytest-bdd (BDD Testing)
|
|
|
|
```yaml
|
|
tool_name: pytest-bdd
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pytest-bdd"
|
|
purpose: "BDD plugin for pytest using Gherkin syntax"
|
|
mandatory: false
|
|
scenarios:
|
|
- Requirements traceability
|
|
- Stakeholder-readable tests
|
|
- Acceptance criteria validation
|
|
- BDD development
|
|
alternatives:
|
|
- robotframework (keyword-driven)
|
|
- behave (standalone BDD)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Optional for BDD approach
|
|
- Requirements traceability needed
|
|
- Non-technical stakeholder involvement
|
|
- Gherkin feature files
|
|
|
|
**Basic Usage**:
|
|
|
|
```gherkin
|
|
# features/auth.feature
|
|
Feature: User Authentication
|
|
As a user
|
|
I want to log in with my credentials
|
|
So that I can access my account
|
|
|
|
Scenario: Successful login
|
|
Given I am on the login page
|
|
When I enter username "testuser"
|
|
And I enter password "TestPass123!"
|
|
And I click the login button
|
|
Then I should see "Welcome, testuser"
|
|
And I should be on the dashboard page
|
|
```
|
|
|
|
```python
|
|
# tests/test_auth.py
|
|
from pytest_bdd import scenarios, given, when, then, parsers
|
|
|
|
scenarios("features/auth.feature")
|
|
|
|
@given("I am on the login page")
|
|
def login_page(browser):
|
|
"""Navigate to login page."""
|
|
browser.get("https://example.com/login")
|
|
|
|
@when(parsers.parse('I enter username "{username}"'))
|
|
def enter_username(browser, username: str) -> None:
|
|
"""Enter username."""
|
|
browser.find_element_by_id("username").send_keys(username)
|
|
|
|
@when(parsers.parse('I enter password "{password}"'))
|
|
def enter_password(browser, password: str) -> None:
|
|
"""Enter password."""
|
|
browser.find_element_by_id("password").send_keys(password)
|
|
|
|
@when("I click the login button")
|
|
def click_login(browser) -> None:
|
|
"""Click login button."""
|
|
browser.find_element_by_id("login").click()
|
|
|
|
@then(parsers.parse('I should see "{text}"'))
|
|
def should_see_text(browser, text: str) -> None:
|
|
"""Verify text is visible."""
|
|
assert text in browser.page_source
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Alternative to robotframework
|
|
- Pattern: BDD acceptance testing
|
|
|
|
**Source**: pytest-architect-analysis.md Section 4.1
|
|
|
|
---
|
|
|
|
### 3.9 pytest-benchmark (Performance Testing)
|
|
|
|
```yaml
|
|
tool_name: pytest-benchmark
|
|
category: testing
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add --dev pytest-benchmark"
|
|
purpose: "Performance regression testing for pytest"
|
|
mandatory: false
|
|
scenarios:
|
|
- Performance regression detection
|
|
- Algorithm optimization
|
|
- Benchmarking code changes
|
|
- CI/CD performance gates
|
|
alternatives:
|
|
- timeit (manual benchmarking)
|
|
- cProfile (profiling, not benchmarking)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Optional for performance-critical code
|
|
- Regression testing after optimization
|
|
- CI/CD performance monitoring
|
|
- Algorithm comparison
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
def test_list_comprehension_performance(benchmark):
|
|
"""Benchmark list comprehension vs map."""
|
|
data = range(1000)
|
|
|
|
result = benchmark(lambda: [x * 2 for x in data])
|
|
|
|
assert len(result) == 1000
|
|
|
|
def test_algorithm_comparison(benchmark):
|
|
"""Compare sorting algorithms."""
|
|
import random
|
|
data = [random.randint(0, 1000) for _ in range(1000)]
|
|
|
|
result = benchmark(sorted, data)
|
|
|
|
assert result == sorted(data)
|
|
|
|
# Run benchmarks
|
|
# pytest --benchmark-only
|
|
# pytest --benchmark-compare
|
|
```
|
|
|
|
**Configuration**:
|
|
|
|
```toml
|
|
# pyproject.toml
|
|
[tool.pytest.ini_options]
|
|
markers = [
|
|
"benchmark: performance benchmarks",
|
|
]
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- ALWAYS profile before optimizing
|
|
- Pattern: Performance regression testing
|
|
|
|
**Source**: pytest-architect-analysis.md Section 3.5
|
|
|
|
---
|
|
|
|
## 4. CLI Frameworks
|
|
|
|
### 4.1 Typer (Human-Facing CLI)
|
|
|
|
```yaml
|
|
tool_name: typer
|
|
category: cli
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "typer>=0.19.2" # In PEP 723 dependencies
|
|
purpose: "Type-based CLI framework with Rich integration"
|
|
mandatory: true
|
|
scenarios:
|
|
- Human-facing command-line tools
|
|
- Interactive CLI applications
|
|
- CLI with formatted output
|
|
- Developer tools
|
|
alternatives:
|
|
- argparse (stdlib, less features)
|
|
- click (typer builds on click)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for human-facing CLIs
|
|
- Scripts with external dependencies
|
|
- Rich terminal output needed
|
|
- Type-driven CLI design
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
#!/usr/bin/env -S uv --quiet run --active --script
|
|
# /// script
|
|
# requires-python = ">=3.11"
|
|
# dependencies = [
|
|
# "typer>=0.19.2", # Includes Rich - do NOT add Rich separately
|
|
# ]
|
|
# ///
|
|
|
|
"""Modern CLI tool with type hints."""
|
|
|
|
from pathlib import Path
|
|
from typing import Annotated
|
|
|
|
import typer
|
|
from rich.console import Console
|
|
|
|
app = typer.Typer(rich_markup_mode="rich")
|
|
console = Console()
|
|
|
|
@app.command()
|
|
def process(
|
|
input_file: Annotated[Path, typer.Argument(help="Input file to process")],
|
|
output: Annotated[Path, typer.Option("--output", "-o", help="Output directory")] = Path("."),
|
|
verbose: Annotated[bool, typer.Option("--verbose", "-v", help="Verbose output")] = False,
|
|
) -> None:
|
|
"""Process files with [bold green]style[/bold green]."""
|
|
if verbose:
|
|
console.print(f"[cyan]Processing[/cyan] {input_file}")
|
|
|
|
# Processing logic
|
|
console.print("[green]:white_check_mark:[/green] Done!")
|
|
|
|
if __name__ == "__main__":
|
|
app()
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Rich: Bundled automatically (NEVER add separately)
|
|
- PEP 723: Standard shebang pattern
|
|
- Testing: Use CliRunner from typer.testing
|
|
|
|
**Advanced Patterns**:
|
|
|
|
```python
|
|
from typing import Annotated
|
|
from enum import Enum
|
|
|
|
import typer
|
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
|
|
# Enum for choices
|
|
class OutputFormat(str, Enum):
|
|
JSON = "json"
|
|
YAML = "yaml"
|
|
CSV = "csv"
|
|
|
|
@app.command()
|
|
def export(
|
|
format: Annotated[OutputFormat, typer.Option(help="Output format")] = OutputFormat.JSON,
|
|
) -> None:
|
|
"""Export data in specified format."""
|
|
console.print(f"Exporting as {format.value}")
|
|
|
|
# Progress bars
|
|
@app.command()
|
|
def download() -> None:
|
|
"""Download files with progress."""
|
|
with Progress(
|
|
SpinnerColumn(),
|
|
TextColumn("[progress.description]{task.description}"),
|
|
console=console,
|
|
) as progress:
|
|
task = progress.add_task("Downloading...", total=None)
|
|
# Download logic
|
|
progress.update(task, completed=True)
|
|
```
|
|
|
|
**Common Mistakes**:
|
|
|
|
```python
|
|
# WRONG: Adding Rich separately
|
|
# /// script
|
|
# dependencies = [
|
|
# "typer>=0.19.2",
|
|
# "rich>=13.0.0", # ✗ WRONG - Rich is included with Typer
|
|
# ]
|
|
# ///
|
|
|
|
# CORRECT: Typer only
|
|
# /// script
|
|
# dependencies = [
|
|
# "typer>=0.19.2", # ✓ Rich is bundled
|
|
# ]
|
|
# ///
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- NEVER add Rich separately
|
|
- MUST use Annotated for parameters
|
|
- MUST include rich help text
|
|
- Pattern: PEP 723 CLI template
|
|
|
|
**Source**: pattern-extraction.md Section 3.3, python-cli-architect-analysis.md
|
|
|
|
---
|
|
|
|
### 4.2 Rich (Terminal Formatting)
|
|
|
|
```yaml
|
|
tool_name: rich
|
|
category: cli
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "Bundled with Typer >=0.19.2"
|
|
purpose: "Beautiful terminal formatting and output"
|
|
mandatory: false # Bundled with Typer
|
|
scenarios:
|
|
- Formatted CLI output
|
|
- Progress bars
|
|
- Tables
|
|
- Syntax highlighting
|
|
alternatives:
|
|
- colorama (basic colors only)
|
|
- termcolor (basic colors only)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Automatically available with Typer
|
|
- NEVER add as separate dependency when using Typer
|
|
- Direct use when NOT using Typer
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
from rich import box
|
|
from rich.console import Console
|
|
from rich.table import Table
|
|
from rich.measure import Measurement
|
|
|
|
console = Console()
|
|
|
|
# Print with markup
|
|
console.print("[bold green]Success![/bold green]")
|
|
console.print(":white_check_mark: Task completed")
|
|
|
|
# Tables
|
|
table = Table(
|
|
title=":sparkles: Results",
|
|
box=box.MINIMAL_DOUBLE_HEAD,
|
|
title_style="bold blue"
|
|
)
|
|
table.add_column("Name", style="cyan", no_wrap=True)
|
|
table.add_column("Status", style="magenta")
|
|
table.add_row("Task 1", "✓ Complete")
|
|
|
|
# CRITICAL: Measure and set table width
|
|
def _get_table_width(table: Table) -> int:
|
|
"""Get natural width of table using temporary wide console."""
|
|
temp_console = Console(width=9999)
|
|
measurement = Measurement.get(temp_console, temp_console.options, table)
|
|
return int(measurement.maximum)
|
|
|
|
table.width = _get_table_width(table)
|
|
|
|
# Print with specific parameters to prevent wrapping
|
|
console.print(
|
|
table,
|
|
crop=False,
|
|
overflow="ignore",
|
|
no_wrap=True,
|
|
soft_wrap=True
|
|
)
|
|
```
|
|
|
|
**Rich Components**:
|
|
|
|
```python
|
|
from rich.console import Console
|
|
from rich.table import Table
|
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
from rich.panel import Panel
|
|
from rich.syntax import Syntax
|
|
from rich.tree import Tree
|
|
from rich.measure import Measurement
|
|
from rich import box
|
|
|
|
# Progress bars
|
|
with Progress(
|
|
SpinnerColumn(),
|
|
TextColumn("[progress.description]{task.description}"),
|
|
) as progress:
|
|
task = progress.add_task("Processing...", total=100)
|
|
for i in range(100):
|
|
progress.update(task, advance=1)
|
|
|
|
# Panels
|
|
console.print(Panel("Important message", title="Warning", border_style="yellow"))
|
|
|
|
# Syntax highlighting
|
|
code = '''
|
|
def hello():
|
|
print("Hello, world!")
|
|
'''
|
|
syntax = Syntax(code, "python", theme="monokai")
|
|
console.print(syntax)
|
|
|
|
# Trees
|
|
tree = Tree("Root")
|
|
tree.add("Branch 1")
|
|
tree.add("Branch 2").add("Leaf")
|
|
console.print(tree)
|
|
```
|
|
|
|
**Integration with Other Tools**:
|
|
|
|
- Typer: Automatic integration
|
|
- Testing: Capture with StringIO
|
|
- NO_COLOR: Respect environment variable
|
|
|
|
**Table Best Practices**:
|
|
|
|
- MUST use box.MINIMAL_DOUBLE_HEAD
|
|
- MUST measure table width
|
|
- MUST set table.width to prevent wrapping
|
|
- MUST use specific print parameters
|
|
|
|
**Related Standards**:
|
|
|
|
- NEVER add separately when using Typer
|
|
- MANDATORY table width measurement
|
|
- Pattern: Rich table display
|
|
|
|
**Source**: pattern-extraction.md Section 5.1, python-cli-architect-analysis.md
|
|
|
|
---
|
|
|
|
### 4.3 argparse (Portable CLI)
|
|
|
|
```yaml
|
|
tool_name: argparse
|
|
category: cli
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "Stdlib - no installation needed"
|
|
purpose: "Standard library argument parsing for portable scripts"
|
|
mandatory: false
|
|
scenarios:
|
|
- Stdlib-only scripts
|
|
- Maximum portability
|
|
- No external dependencies
|
|
- Automation/CI scripts
|
|
alternatives:
|
|
- typer (more features, external dependency)
|
|
- click (more features, external dependency)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Scripts with NO external dependencies
|
|
- Maximum portability required
|
|
- Automation/CI environments
|
|
- Shebang: `#!/usr/bin/env python3`
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
#!/usr/bin/env python3
|
|
"""Portable script with argparse."""
|
|
|
|
import argparse
|
|
from pathlib import Path
|
|
|
|
def main() -> None:
|
|
"""Main entry point."""
|
|
parser = argparse.ArgumentParser(
|
|
description="Process files",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
)
|
|
|
|
parser.add_argument(
|
|
"input",
|
|
type=Path,
|
|
help="Input file to process"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-o", "--output",
|
|
type=Path,
|
|
default=Path("."),
|
|
help="Output directory (default: current directory)"
|
|
)
|
|
|
|
parser.add_argument(
|
|
"-v", "--verbose",
|
|
action="store_true",
|
|
help="Verbose output"
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.verbose:
|
|
print(f"Processing {args.input}")
|
|
|
|
# Processing logic
|
|
print("Done!")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
```
|
|
|
|
**Advanced Patterns**:
|
|
|
|
```python
|
|
# Subcommands
|
|
import argparse
|
|
|
|
parser = argparse.ArgumentParser()
|
|
subparsers = parser.add_subparsers(dest="command", required=True)
|
|
|
|
# Add subcommand
|
|
process_parser = subparsers.add_parser("process", help="Process files")
|
|
process_parser.add_argument("input", type=Path)
|
|
|
|
list_parser = subparsers.add_parser("list", help="List files")
|
|
list_parser.add_argument("--pattern", help="File pattern")
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.command == "process":
|
|
process_files(args.input)
|
|
elif args.command == "list":
|
|
list_files(args.pattern)
|
|
|
|
# Mutual exclusivity
|
|
group = parser.add_mutually_exclusive_group()
|
|
group.add_argument("--json", action="store_true")
|
|
group.add_argument("--yaml", action="store_true")
|
|
|
|
# Argument groups
|
|
input_group = parser.add_argument_group("Input Options")
|
|
input_group.add_argument("--file", type=Path)
|
|
input_group.add_argument("--stdin", action="store_true")
|
|
|
|
output_group = parser.add_argument_group("Output Options")
|
|
output_group.add_argument("--output", type=Path)
|
|
output_group.add_argument("--format", choices=["json", "yaml", "csv"])
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Stdlib only - no dependencies
|
|
- Shebang: `#!/usr/bin/env python3`
|
|
- Pattern: Portable script template
|
|
|
|
**Source**: pattern-extraction.md Section 2.1, taxonomy.md Section 4
|
|
|
|
---
|
|
|
|
### 4.4 Textual (Terminal UI)
|
|
|
|
```yaml
|
|
tool_name: textual
|
|
category: cli
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add textual"
|
|
purpose: "Rich interactive terminal user interfaces"
|
|
mandatory: false
|
|
scenarios:
|
|
- Full terminal UI applications
|
|
- Interactive dashboards
|
|
- Complex navigation
|
|
- Real-time monitoring
|
|
alternatives:
|
|
- curses (stdlib, lower level)
|
|
- urwid (older TUI library)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Full interactive TUI needed
|
|
- Complex layouts and navigation
|
|
- Real-time updates
|
|
- Dashboard applications
|
|
|
|
**Status**: Framework support needed (see taxonomy.md Section 5.2)
|
|
|
|
**Example** (conceptual):
|
|
|
|
```python
|
|
from textual.app import App
|
|
from textual.widgets import Header, Footer, Button
|
|
|
|
class MyApp(App):
|
|
"""Textual application."""
|
|
|
|
def compose(self):
|
|
"""Compose UI."""
|
|
yield Header()
|
|
yield Button("Click me")
|
|
yield Footer()
|
|
|
|
def on_button_pressed(self) -> None:
|
|
"""Handle button press."""
|
|
self.exit()
|
|
|
|
if __name__ == "__main__":
|
|
app = MyApp()
|
|
app.run()
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Framework extension needed
|
|
- Pattern: TUI development
|
|
|
|
**Source**: taxonomy.md Section 5, user requirements list
|
|
|
|
---
|
|
|
|
## 5. Data Libraries
|
|
|
|
### 5.1 datasette (Data Exploration)
|
|
|
|
```yaml
|
|
tool_name: datasette
|
|
category: data
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add datasette"
|
|
purpose: "Instant JSON API and web UI for SQLite databases"
|
|
mandatory: false
|
|
scenarios:
|
|
- Database exploration
|
|
- Quick data APIs
|
|
- Data visualization
|
|
- SQLite database serving
|
|
alternatives:
|
|
- direct SQLite access
|
|
- custom Flask/FastAPI apps
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Rapid database exploration
|
|
- Prototyping data APIs
|
|
- Sharing SQLite databases
|
|
- Data journalism
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Serve database
|
|
datasette mydb.db
|
|
|
|
# Serve with metadata
|
|
datasette mydb.db --metadata metadata.json
|
|
|
|
# Publish to cloud
|
|
datasette publish cloudrun mydb.db --service=my-data
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Data exploration tools
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 5.2 arrow (Date/Time Handling)
|
|
|
|
```yaml
|
|
tool_name: arrow
|
|
category: data
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add arrow"
|
|
purpose: "Better dates and times for Python"
|
|
mandatory: false
|
|
scenarios:
|
|
- Human-friendly date parsing
|
|
- Timezone handling
|
|
- Date arithmetic
|
|
- Date formatting
|
|
alternatives:
|
|
- datetime (stdlib, more verbose)
|
|
- pendulum (similar features)
|
|
- dateutil (lower level)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- User-friendly date handling
|
|
- Timezone conversions
|
|
- Date range generation
|
|
- Human-readable formatting
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
import arrow
|
|
|
|
# Current time
|
|
now = arrow.now()
|
|
utc = arrow.utcnow()
|
|
|
|
# Parse dates
|
|
date = arrow.get("2023-05-11")
|
|
parsed = arrow.get("2023-05-11 12:30:00", "YYYY-MM-DD HH:mm:ss")
|
|
|
|
# Timezone handling
|
|
local = arrow.now("US/Pacific")
|
|
converted = utc.to("Europe/London")
|
|
|
|
# Humanization
|
|
now = arrow.now()
|
|
hour_ago = now.shift(hours=-1)
|
|
print(hour_ago.humanize()) # "an hour ago"
|
|
|
|
# Date arithmetic
|
|
future = now.shift(days=7, hours=2)
|
|
past = now.shift(months=-1)
|
|
|
|
# Formatting
|
|
formatted = now.format("YYYY-MM-DD HH:mm:ss")
|
|
iso = now.isoformat()
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Time-aware scripts
|
|
|
|
**Source**: User requirements list, python-portable-script-analysis.md
|
|
|
|
---
|
|
|
|
### 5.3 httpx (Async HTTP Client)
|
|
|
|
```yaml
|
|
tool_name: httpx
|
|
category: data
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add httpx"
|
|
purpose: "Modern async HTTP client with HTTP/2 support"
|
|
mandatory: false
|
|
scenarios:
|
|
- Async API clients
|
|
- HTTP/2 support
|
|
- Modern async applications
|
|
- FastAPI testing
|
|
alternatives:
|
|
- requests (sync only, more common)
|
|
- aiohttp (async, lower level)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Async HTTP requests needed
|
|
- HTTP/2 support required
|
|
- FastAPI async testing
|
|
- Modern async applications
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
import httpx
|
|
|
|
# Sync usage (like requests)
|
|
response = httpx.get("https://api.example.com/users")
|
|
data = response.json()
|
|
|
|
# Async usage
|
|
import asyncio
|
|
|
|
async def fetch_users():
|
|
async with httpx.AsyncClient() as client:
|
|
response = await client.get("https://api.example.com/users")
|
|
return response.json()
|
|
|
|
users = asyncio.run(fetch_users())
|
|
|
|
# Testing FastAPI
|
|
from httpx import AsyncClient
|
|
from app import app
|
|
|
|
async def test_endpoint():
|
|
async with AsyncClient(app=app, base_url="http://test") as client:
|
|
response = await client.get("/users")
|
|
assert response.status_code == 200
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Async HTTP client
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 5.4 requests (HTTP Client)
|
|
|
|
```yaml
|
|
tool_name: requests
|
|
category: data
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add requests"
|
|
purpose: "HTTP library for humans"
|
|
mandatory: false
|
|
scenarios:
|
|
- Synchronous HTTP requests
|
|
- API clients
|
|
- Web scraping
|
|
- Simple HTTP operations
|
|
alternatives:
|
|
- httpx (async support, modern)
|
|
- urllib (stdlib, lower level)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Synchronous HTTP requests
|
|
- Simple API clients
|
|
- Most common HTTP library
|
|
- Well-documented patterns
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
import requests
|
|
|
|
# GET request
|
|
response = requests.get("https://api.example.com/users")
|
|
users = response.json()
|
|
|
|
# POST request
|
|
data = {"name": "Alice", "email": "alice@example.com"}
|
|
response = requests.post("https://api.example.com/users", json=data)
|
|
|
|
# Headers and authentication
|
|
headers = {"Authorization": "Bearer token123"}
|
|
response = requests.get("https://api.example.com/protected", headers=headers)
|
|
|
|
# Error handling
|
|
try:
|
|
response = requests.get("https://api.example.com/users")
|
|
response.raise_for_status() # Raise for 4xx/5xx
|
|
data = response.json()
|
|
except requests.HTTPError as e:
|
|
print(f"HTTP error: {e}")
|
|
except requests.RequestException as e:
|
|
print(f"Request failed: {e}")
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Pattern: Common in examples
|
|
- Alternative: httpx for async
|
|
|
|
**Source**: Common Python library
|
|
|
|
---
|
|
|
|
### 5.5 pydantic (Data Validation)
|
|
|
|
```yaml
|
|
tool_name: pydantic
|
|
category: data
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add pydantic"
|
|
purpose: "Data validation using Python type annotations"
|
|
mandatory: false
|
|
scenarios:
|
|
- API request/response validation
|
|
- Configuration management
|
|
- Data serialization
|
|
- Type-safe data models
|
|
alternatives:
|
|
- dataclasses (stdlib, no validation)
|
|
- marshmallow (schema-based validation)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- API data validation
|
|
- Configuration management
|
|
- Type-safe data models
|
|
- JSON schema generation
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
from pydantic import BaseModel, Field, validator
|
|
from datetime import datetime
|
|
|
|
class User(BaseModel):
|
|
"""User model with validation."""
|
|
id: int
|
|
name: str = Field(..., min_length=1, max_length=100)
|
|
email: str
|
|
created_at: datetime = Field(default_factory=datetime.now)
|
|
is_active: bool = True
|
|
|
|
@validator("email")
|
|
def validate_email(cls, v: str) -> str:
|
|
"""Validate email format."""
|
|
if "@" not in v:
|
|
raise ValueError("Invalid email address")
|
|
return v.lower()
|
|
|
|
# Usage
|
|
user = User(id=1, name="Alice", email="alice@example.com")
|
|
print(user.json())
|
|
print(user.dict())
|
|
|
|
# Validation errors
|
|
try:
|
|
invalid_user = User(id=1, name="", email="invalid")
|
|
except ValueError as e:
|
|
print(f"Validation error: {e}")
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Pattern: FastAPI integration
|
|
- Pattern: DTO models
|
|
|
|
**Source**: Common in modern Python
|
|
|
|
---
|
|
|
|
## 6. Workflow Tools
|
|
|
|
### 6.1 prefect (Workflow Orchestration)
|
|
|
|
```yaml
|
|
tool_name: prefect
|
|
category: workflow
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add prefect"
|
|
purpose: "Modern workflow orchestration platform"
|
|
mandatory: false
|
|
scenarios:
|
|
- Data pipeline orchestration
|
|
- Task scheduling
|
|
- Distributed workflows
|
|
- Workflow monitoring
|
|
alternatives:
|
|
- airflow (older, more complex)
|
|
- dagster (data pipeline focused)
|
|
- celery (task queue, lower level)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Complex workflow orchestration
|
|
- Data pipeline management
|
|
- Scheduled task execution
|
|
- Distributed computing
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
from prefect import flow, task
|
|
|
|
@task
|
|
def extract_data(source: str) -> list:
|
|
"""Extract data from source."""
|
|
# Extraction logic
|
|
return data
|
|
|
|
@task
|
|
def transform_data(data: list) -> list:
|
|
"""Transform extracted data."""
|
|
# Transformation logic
|
|
return transformed
|
|
|
|
@task
|
|
def load_data(data: list, destination: str) -> None:
|
|
"""Load data to destination."""
|
|
# Loading logic
|
|
pass
|
|
|
|
@flow
|
|
def etl_pipeline(source: str, destination: str) -> None:
|
|
"""ETL pipeline flow."""
|
|
raw_data = extract_data(source)
|
|
clean_data = transform_data(raw_data)
|
|
load_data(clean_data, destination)
|
|
|
|
# Run flow
|
|
if __name__ == "__main__":
|
|
etl_pipeline("source.csv", "database")
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Workflow orchestration
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 6.2 fabric (Remote Execution)
|
|
|
|
```yaml
|
|
tool_name: fabric
|
|
category: workflow
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add fabric"
|
|
purpose: "High-level SSH command execution and deployment"
|
|
mandatory: false
|
|
scenarios:
|
|
- Remote server management
|
|
- Deployment automation
|
|
- DevOps scripting
|
|
- SSH task execution
|
|
alternatives:
|
|
- paramiko (lower level SSH)
|
|
- ansible (YAML-based automation)
|
|
- invoke (local task execution)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Remote server automation
|
|
- Deployment scripts
|
|
- DevOps workflows
|
|
- SSH-based operations
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
from fabric import Connection, task
|
|
|
|
@task
|
|
def deploy(c):
|
|
"""Deploy application to server."""
|
|
# Connect to remote server
|
|
with Connection("user@server.com") as conn:
|
|
# Update code
|
|
conn.run("cd /app && git pull")
|
|
|
|
# Install dependencies
|
|
conn.run("cd /app && uv sync")
|
|
|
|
# Restart service
|
|
conn.sudo("systemctl restart myapp")
|
|
|
|
# Multiple servers
|
|
from fabric import SerialGroup
|
|
|
|
def deploy_cluster():
|
|
"""Deploy to cluster."""
|
|
servers = SerialGroup("server1.com", "server2.com", "server3.com")
|
|
servers.run("cd /app && git pull")
|
|
servers.sudo("systemctl restart myapp")
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: DevOps automation
|
|
|
|
**Source**: User requirements list, python-portable-script-analysis.md
|
|
|
|
---
|
|
|
|
### 6.3 copier (Project Templating)
|
|
|
|
```yaml
|
|
tool_name: copier
|
|
category: workflow
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add copier"
|
|
purpose: "Project and file template rendering with updates"
|
|
mandatory: false
|
|
scenarios:
|
|
- Project scaffolding
|
|
- Template-based code generation
|
|
- Consistent project structure
|
|
- Template updates
|
|
alternatives:
|
|
- cookiecutter (similar, no updates)
|
|
- jinja2-cli (basic templating)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Project scaffolding
|
|
- Consistent project structure
|
|
- Template maintenance
|
|
- Multi-project standardization
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Create project from template
|
|
copier copy https://github.com/org/template myproject
|
|
|
|
# Update existing project
|
|
cd myproject
|
|
copier update
|
|
|
|
# Copy with answers
|
|
copier copy --data project_name=MyApp template/ myapp/
|
|
```
|
|
|
|
**Template Example**:
|
|
|
|
```yaml
|
|
# copier.yml
|
|
_subdirectory: template
|
|
|
|
_questions:
|
|
- name: project_name
|
|
type: str
|
|
help: Project name
|
|
|
|
- name: author
|
|
type: str
|
|
help: Author name
|
|
|
|
- name: python_version
|
|
type: str
|
|
default: "3.11"
|
|
help: Python version
|
|
|
|
_templates_suffix: .jinja
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Project templates
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 6.4 invoke (Task Execution)
|
|
|
|
```yaml
|
|
tool_name: invoke
|
|
category: workflow
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add invoke"
|
|
purpose: "Python task execution tool and library"
|
|
mandatory: false
|
|
scenarios:
|
|
- Build automation
|
|
- Development tasks
|
|
- Task orchestration
|
|
- Local workflows
|
|
alternatives:
|
|
- make (Makefile-based)
|
|
- nox (test automation)
|
|
- tox (test environments)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Local task automation
|
|
- Development workflows
|
|
- Build scripts
|
|
- Task organization
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
# tasks.py
|
|
from invoke import task
|
|
|
|
@task
|
|
def clean(c):
|
|
"""Clean build artifacts."""
|
|
c.run("rm -rf build dist *.egg-info")
|
|
|
|
@task
|
|
def test(c):
|
|
"""Run tests."""
|
|
c.run("pytest")
|
|
|
|
@task
|
|
def lint(c):
|
|
"""Run linters."""
|
|
c.run("ruff check .")
|
|
c.run("mypy .")
|
|
|
|
@task(pre=[clean, test, lint])
|
|
def build(c):
|
|
"""Build package."""
|
|
c.run("uv build")
|
|
|
|
# Run: invoke build
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Alternative to make
|
|
- Pattern: Task automation
|
|
|
|
**Source**: Common Python tool
|
|
|
|
---
|
|
|
|
## 7. IoT/Messaging
|
|
|
|
### 7.1 paho-mqtt (MQTT Client)
|
|
|
|
```yaml
|
|
tool_name: paho-mqtt
|
|
category: iot
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add paho-mqtt"
|
|
purpose: "MQTT protocol client library"
|
|
mandatory: false
|
|
scenarios:
|
|
- IoT device communication
|
|
- Message broker integration
|
|
- Publish-subscribe messaging
|
|
- Real-time data streams
|
|
alternatives:
|
|
- gmqtt (async MQTT)
|
|
- aiomqtt (async wrapper)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- IoT device integration
|
|
- MQTT messaging
|
|
- Pub/sub patterns
|
|
- Real-time communication
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
import paho.mqtt.client as mqtt
|
|
|
|
def on_connect(client, userdata, flags, rc):
|
|
"""Callback for connection."""
|
|
print(f"Connected with result code {rc}")
|
|
client.subscribe("sensors/temperature")
|
|
|
|
def on_message(client, userdata, msg):
|
|
"""Callback for messages."""
|
|
print(f"{msg.topic}: {msg.payload.decode()}")
|
|
|
|
# Create client
|
|
client = mqtt.Client()
|
|
client.on_connect = on_connect
|
|
client.on_message = on_message
|
|
|
|
# Connect and loop
|
|
client.connect("mqtt.example.com", 1883, 60)
|
|
client.loop_forever()
|
|
|
|
# Publishing
|
|
def publish_temperature(temp: float) -> None:
|
|
"""Publish temperature reading."""
|
|
client = mqtt.Client()
|
|
client.connect("mqtt.example.com", 1883, 60)
|
|
client.publish("sensors/temperature", str(temp))
|
|
client.disconnect()
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: IoT integration
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 7.2 blinker (Signals/Events)
|
|
|
|
```yaml
|
|
tool_name: blinker
|
|
category: messaging
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add blinker"
|
|
purpose: "Fast Python in-process signal/event system"
|
|
mandatory: false
|
|
scenarios:
|
|
- Event-driven architecture
|
|
- Decoupled components
|
|
- Plugin systems
|
|
- Observer pattern
|
|
alternatives:
|
|
- PyPubSub (publish-subscribe)
|
|
- custom event handlers
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Event-driven design
|
|
- Decoupling components
|
|
- Plugin architecture
|
|
- Observer pattern implementation
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
from blinker import signal
|
|
|
|
# Define signals
|
|
user_logged_in = signal("user-logged-in")
|
|
data_processed = signal("data-processed")
|
|
|
|
# Connect handlers
|
|
@user_logged_in.connect
|
|
def on_user_login(sender, user_id):
|
|
"""Handle user login event."""
|
|
print(f"User {user_id} logged in")
|
|
|
|
@data_processed.connect
|
|
def on_data_processed(sender, record_count):
|
|
"""Handle data processing completion."""
|
|
print(f"Processed {record_count} records")
|
|
|
|
# Emit signals
|
|
user_logged_in.send("auth-system", user_id=123)
|
|
data_processed.send("processor", record_count=1000)
|
|
|
|
# Named receivers
|
|
def log_user_activity(sender, user_id):
|
|
"""Log user activity."""
|
|
pass
|
|
|
|
user_logged_in.connect(log_user_activity, sender="auth-system")
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Event-driven systems
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
## 8. Build Tools
|
|
|
|
### 8.1 hatchling (Build Backend)
|
|
|
|
```yaml
|
|
tool_name: hatchling
|
|
category: build
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add hatchling"
|
|
purpose: "Modern Python build backend for packages"
|
|
mandatory: false
|
|
scenarios:
|
|
- Package building
|
|
- PEP 517/PEP 660 compliance
|
|
- Modern packaging
|
|
- PyPI publishing
|
|
alternatives:
|
|
- setuptools (legacy)
|
|
- poetry (different approach)
|
|
- flit (simpler, limited)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Building Python packages
|
|
- Modern build backend
|
|
- PEP 517 compliance
|
|
- PyPI publishing
|
|
|
|
**Basic Usage**:
|
|
|
|
```toml
|
|
# pyproject.toml - Complete project metadata example
|
|
# NOTE: Replace ALL {{template_variables}} with actual values before creating file
|
|
# See "Pyproject.toml Template Variable Reference" section for sourcing methods
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[project]
|
|
name = "{{project_name_from_directory_or_git_remote}}"
|
|
version = "{{version_from_git_tag_or_default_0_1_0}}"
|
|
description = "{{project_description_from_user_or_readme}}"
|
|
readme = "README.md"
|
|
requires-python = ">=3.11"
|
|
license = {text = "{{license_type_from_user_or_default_MIT}}"}
|
|
authors = [
|
|
{name = "{{author_name_from_git_config_user_name}}", email = "{{author_email_from_git_config_user_email}}"},
|
|
]
|
|
keywords = [{{project_keywords_from_user}}]
|
|
classifiers = [
|
|
"Development Status :: {{dev_status_from_user}}",
|
|
"Intended Audience :: {{audience_from_user}}",
|
|
"Programming Language :: Python :: 3.11",
|
|
"Programming Language :: Python :: 3.12",
|
|
"Programming Language :: Python :: 3.13",
|
|
]
|
|
dependencies = [
|
|
"typer>=0.19.2",
|
|
"pydantic>=2.0.0",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=8.0.0",
|
|
"mypy>=1.11.0",
|
|
"ruff>=0.6.0",
|
|
]
|
|
|
|
[project.scripts]
|
|
{{cli_command_name_from_user}} = "{{package_name_from_project_name}}.cli:main"
|
|
|
|
[project.urls]
|
|
Homepage = "{{repository_homepage_url_from_git_remote}}"
|
|
Repository = "{{repository_url_from_git_remote_get_url}}"
|
|
Issues = "{{repository_issues_url_from_git_remote}}"
|
|
Documentation = "{{documentation_url_from_user_or_readme}}"
|
|
|
|
[tool.hatchling.build.targets.wheel]
|
|
packages = ["packages/{{package_name_from_project_name}}"]
|
|
```
|
|
|
|
```bash
|
|
# Build package
|
|
uv build
|
|
|
|
# Outputs:
|
|
# dist/mypackage-1.0.0-py3-none-any.whl
|
|
# dist/mypackage-1.0.0.tar.gz
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Modern packaging
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 8.2 shiv (Executable Builder)
|
|
|
|
```yaml
|
|
tool_name: shiv
|
|
category: build
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add shiv"
|
|
purpose: "Command-line utility for building Python zip apps"
|
|
mandatory: false
|
|
scenarios:
|
|
- Single-file executables
|
|
- Portable Python apps
|
|
- Easy distribution
|
|
- Self-contained scripts
|
|
alternatives:
|
|
- pex (similar concept)
|
|
- pyinstaller (binary executables)
|
|
- nuitka (Python to C compiler)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Create portable executables
|
|
- Single-file distribution
|
|
- No installation deployment
|
|
- Python zip applications
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Create executable
|
|
shiv -c mycli -o mycli.pyz mypackage
|
|
|
|
# Create with dependencies
|
|
shiv -c mycli -o mycli.pyz --python '/usr/bin/env python3' mypackage requests pydantic
|
|
|
|
# Run executable
|
|
./mycli.pyz --help
|
|
|
|
# With specific Python
|
|
python3.11 mycli.pyz --help
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- User requirement
|
|
- Pattern: Portable executables
|
|
|
|
**Source**: User requirements list
|
|
|
|
---
|
|
|
|
### 8.3 pip-tools (Dependency Management)
|
|
|
|
```yaml
|
|
tool_name: pip-tools
|
|
category: build
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "uv add pip-tools"
|
|
purpose: "Pin and manage Python dependencies"
|
|
mandatory: false
|
|
scenarios:
|
|
- Dependency pinning
|
|
- Reproducible builds
|
|
- Dependency resolution
|
|
- Requirements management
|
|
alternatives:
|
|
- uv (modern, faster, recommended)
|
|
- poetry (different approach)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Legacy projects
|
|
- Dependency locking
|
|
- NOT recommended (use uv instead)
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Compile requirements
|
|
pip-compile requirements.in -o requirements.txt
|
|
|
|
# Sync environment
|
|
pip-sync requirements.txt
|
|
|
|
# Upgrade dependencies
|
|
pip-compile --upgrade requirements.in
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Legacy tool
|
|
- Replaced by uv
|
|
- Pattern: Use uv instead
|
|
|
|
**Source**: Mentioned as legacy alternative
|
|
|
|
---
|
|
|
|
## 9. Quality Tools
|
|
|
|
### 9.1 validate_pep723.py (PEP 723 Validator)
|
|
|
|
```yaml
|
|
tool_name: validate_pep723.py
|
|
category: quality
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "~/.claude/tools/validate_pep723.py"
|
|
purpose: "Validate PEP 723 script metadata compliance"
|
|
mandatory: true
|
|
scenarios:
|
|
- PEP 723 script validation
|
|
- Layer 5 validation pipeline
|
|
- Pre-delivery checks
|
|
- Dependency verification
|
|
alternatives:
|
|
- Manual verification (error-prone)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- MANDATORY for all PEP 723 scripts
|
|
- Layer 5 of validation pipeline
|
|
- Before script delivery
|
|
- Dependency auditing
|
|
|
|
**Basic Usage**:
|
|
|
|
```bash
|
|
# Validate script
|
|
~/.claude/tools/validate_pep723.py check script.py
|
|
|
|
# Expected output
|
|
✅ Shebang correct: #!/usr/bin/env -S uv --quiet run --active --script
|
|
✅ Metadata block found
|
|
✅ requires-python present: >=3.11
|
|
✅ All imports have dependencies
|
|
✅ Rich not listed separately (bundled with Typer)
|
|
```
|
|
|
|
**Checks Performed**:
|
|
|
|
1. Shebang correctness
|
|
2. Metadata block presence
|
|
3. requires-python declaration
|
|
4. All imports in dependencies
|
|
5. Rich not separately listed with Typer
|
|
6. Dependency version format
|
|
|
|
**Related Standards**:
|
|
|
|
- MANDATORY validation step
|
|
- Layer 5 of validation pipeline
|
|
- Pattern: PEP 723 compliance
|
|
|
|
**Source**: pattern-extraction.md Section 3.5, all CLI agents
|
|
|
|
---
|
|
|
|
## 10. MCP Tools
|
|
|
|
### 10.1 Context7 (Library Documentation)
|
|
|
|
```yaml
|
|
tool_name: mcp__context7__get-library-docs
|
|
category: mcp
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "MCP server integration"
|
|
purpose: "Fetch up-to-date library documentation"
|
|
mandatory: false
|
|
scenarios:
|
|
- Library documentation lookup
|
|
- API reference research
|
|
- Best practices discovery
|
|
- Framework usage patterns
|
|
alternatives:
|
|
- WebSearch (less specific)
|
|
- Manual documentation reading
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Researching library APIs
|
|
- Finding best practices
|
|
- Understanding frameworks
|
|
- Linting rule investigation
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
# Tool call
|
|
context7_docs = mcp__context7__get-library-docs(
|
|
context7CompatibleLibraryID="/astral-sh/ruff",
|
|
topic="ANN201 rule",
|
|
tokens=5000
|
|
)
|
|
|
|
# Use case: Linting investigation
|
|
# Step 1: Resolve library ID
|
|
library_id = mcp__context7__resolve-library-id(libraryName="ruff")
|
|
|
|
# Step 2: Get specific documentation
|
|
docs = mcp__context7__get-library-docs(
|
|
context7CompatibleLibraryID=library_id,
|
|
topic="type annotation rules"
|
|
)
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Used by linting-root-cause-resolver
|
|
- Used by subagent-refactorer
|
|
- Pattern: Authoritative research
|
|
|
|
**Source**: pattern-extraction.md Section 3.4, linting-resolver-analysis.md
|
|
|
|
---
|
|
|
|
### 10.2 Ref (Documentation Search)
|
|
|
|
```yaml
|
|
tool_name: mcp__Ref__ref_search_documentation
|
|
category: mcp
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "MCP server integration"
|
|
purpose: "Search official documentation"
|
|
mandatory: false
|
|
scenarios:
|
|
- Official docs lookup
|
|
- API reference search
|
|
- Framework documentation
|
|
- Standard library docs
|
|
alternatives:
|
|
- WebSearch (broader)
|
|
- Context7 (library-specific)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Official documentation search
|
|
- Python stdlib references
|
|
- Framework official docs
|
|
- API specifications
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
# Search Python docs
|
|
python_docs = mcp__Ref__ref_search_documentation(
|
|
query="asyncio gather Python 3.11"
|
|
)
|
|
|
|
# Search framework docs
|
|
fastapi_docs = mcp__Ref__ref_search_documentation(
|
|
query="FastAPI dependency injection"
|
|
)
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Used by linting-root-cause-resolver
|
|
- Used by subagent-refactorer
|
|
- Pattern: Official documentation
|
|
|
|
**Source**: pattern-extraction.md Section 3.4
|
|
|
|
---
|
|
|
|
### 10.3 Exa (Code Context)
|
|
|
|
```yaml
|
|
tool_name: mcp__exa__get_code_context_exa
|
|
category: mcp
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "MCP server integration"
|
|
purpose: "Get code context for libraries, SDKs, and APIs"
|
|
mandatory: false
|
|
scenarios:
|
|
- Library usage examples
|
|
- SDK integration patterns
|
|
- API client code
|
|
- Real-world usage
|
|
alternatives:
|
|
- GitHub search (less curated)
|
|
- Stack Overflow (less reliable)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Finding library usage examples
|
|
- Understanding SDK integration
|
|
- Discovering code patterns
|
|
- Real-world implementations
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
# Get code context
|
|
code_examples = mcp__exa__get_code_context_exa(
|
|
query="pytest-mock fixture usage examples"
|
|
)
|
|
|
|
# Library integration
|
|
integration = mcp__exa__get_code_context_exa(
|
|
query="FastAPI with SQLAlchemy async"
|
|
)
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Used by linting-root-cause-resolver
|
|
- Used by subagent-refactorer
|
|
- Pattern: Code example research
|
|
|
|
**Source**: pattern-extraction.md Section 3.4
|
|
|
|
---
|
|
|
|
### 10.4 GitHub (Code Search)
|
|
|
|
```yaml
|
|
tool_name: mcp__github__search_code
|
|
category: mcp
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "MCP server integration"
|
|
purpose: "Search GitHub code repositories"
|
|
mandatory: false
|
|
scenarios:
|
|
- Finding real-world examples
|
|
- Pattern discovery
|
|
- Library usage in wild
|
|
- Error resolution
|
|
alternatives:
|
|
- Direct GitHub web search
|
|
- Exa code context
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Real-world code examples
|
|
- Common error solutions
|
|
- Library usage patterns
|
|
- Best practices discovery
|
|
|
|
**Basic Usage**:
|
|
|
|
```python
|
|
# Search for pattern
|
|
examples = mcp__github__search_code(
|
|
query="pytest-mock mocker.patch language:python"
|
|
)
|
|
|
|
# Find error solutions
|
|
solutions = mcp__github__search_code(
|
|
query="ruff ANN201 fix examples"
|
|
)
|
|
```
|
|
|
|
**Related Standards**:
|
|
|
|
- Used by linting-root-cause-resolver
|
|
- Used by subagent-refactorer
|
|
- Pattern: GitHub examples
|
|
|
|
**Source**: pattern-extraction.md Section 3.4
|
|
|
|
---
|
|
|
|
### 10.5 Sequential Thinking
|
|
|
|
```yaml
|
|
tool_name: mcp__sequential_thinking__sequentialthinking
|
|
category: mcp
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "MCP server integration"
|
|
purpose: "Chain-of-thought reasoning for complex problems"
|
|
mandatory: false
|
|
scenarios:
|
|
- Complex problem decomposition
|
|
- Multi-step reasoning
|
|
- Dependency analysis
|
|
- Architecture decisions
|
|
alternatives:
|
|
- Direct analysis (less structured)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Complex problem solving
|
|
- Architecture decisions
|
|
- Dependency analysis
|
|
- Multi-step workflows
|
|
|
|
**Related Standards**:
|
|
|
|
- Used for complex analysis
|
|
- Pattern: Structured reasoning
|
|
|
|
**Source**: pattern-extraction.md Section 3.4
|
|
|
|
---
|
|
|
|
### 10.6 WebSearch
|
|
|
|
```yaml
|
|
tool_name: WebSearch
|
|
category: mcp
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "Built-in tool"
|
|
purpose: "General web search"
|
|
mandatory: false
|
|
scenarios:
|
|
- Broad research
|
|
- Technology comparison
|
|
- Current trends
|
|
- General information
|
|
alternatives:
|
|
- Specific MCP tools (more targeted)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Broad research needs
|
|
- Technology comparisons
|
|
- Current trends
|
|
- General information
|
|
|
|
**Related Standards**:
|
|
|
|
- Used by spec-analyst
|
|
- Pattern: General research
|
|
|
|
**Source**: pattern-extraction.md Section 3.4
|
|
|
|
---
|
|
|
|
### 10.7 WebFetch
|
|
|
|
```yaml
|
|
tool_name: WebFetch
|
|
category: mcp
|
|
python_versions: [3.11, 3.12, 3.13, 3.14]
|
|
installation: "Built-in tool"
|
|
purpose: "Fetch specific web content"
|
|
mandatory: false
|
|
scenarios:
|
|
- Retrieve specific pages
|
|
- Documentation fetching
|
|
- Blog post reading
|
|
- Article analysis
|
|
alternatives:
|
|
- Direct URL access
|
|
- Ref search (for docs)
|
|
```
|
|
|
|
**When to Use**:
|
|
|
|
- Specific URL content needed
|
|
- Documentation retrieval
|
|
- Blog/article analysis
|
|
- Targeted content fetch
|
|
|
|
**Related Standards**:
|
|
|
|
- Used by spec-analyst
|
|
- Pattern: Content retrieval
|
|
|
|
**Source**: pattern-extraction.md Section 3.4
|
|
|
|
---
|
|
|
|
## 11. Tool Comparison Tables
|
|
|
|
### 11.1 Linter Comparison
|
|
|
|
| Feature | ruff | prospector | bandit | pylint |
|
|
| ------------------ | -------------- | ---------------------- | ----------------- | --------- |
|
|
| **Speed** | Extremely fast | Slow | Medium | Slow |
|
|
| **Rules** | 800+ | Combined | Security-focused | 200+ |
|
|
| **Auto-fix** | Yes | Some | No | Some |
|
|
| **Type checking** | No | Via mypy | No | Basic |
|
|
| **Security** | Via plugins | Via bandit | Primary | Basic |
|
|
| **Configuration** | pyproject.toml | .prospector.yaml | .bandit | .pylintrc |
|
|
| **Python 3.11+** | Yes | Yes | Yes | Yes |
|
|
| **Recommendation** | **PRIMARY** | Optional deep analysis | Security scanning | Legacy |
|
|
|
|
**Verdict**: Use **ruff** as primary linter, add **bandit** for security, skip prospector and pylint.
|
|
|
|
---
|
|
|
|
### 11.2 Type Checker Comparison
|
|
|
|
| Feature | mypy | pyright |
|
|
| ------------------- | -------------- | ------------------- |
|
|
| **Speed** | Medium | Fast |
|
|
| **Strict mode** | Yes | Yes |
|
|
| **IDE integration** | Good | Excellent (VS Code) |
|
|
| **Error messages** | Good | Excellent |
|
|
| **Python 3.11+** | Yes | Yes |
|
|
| **Plugin system** | Yes | Limited |
|
|
| **Configuration** | pyproject.toml | pyrightconfig.json |
|
|
| **Recommendation** | **PRIMARY** | **COMPLEMENTARY** |
|
|
|
|
**Verdict**: Run **both** mypy and pyright for comprehensive type checking.
|
|
|
|
---
|
|
|
|
### 11.3 Testing Framework Comparison
|
|
|
|
| Feature | pytest | unittest | robotframework |
|
|
| ------------------- | --------------- | -------------- | ------------------ |
|
|
| **Style** | Modern fixtures | Class-based | Keyword-driven |
|
|
| **Mocking** | pytest-mock | unittest.mock | Built-in |
|
|
| **Fixtures** | Yes (powerful) | setUp/tearDown | Suite setup |
|
|
| **Parametrization** | Yes (native) | Manual | Via templates |
|
|
| **Plugins** | 800+ | Few | 100+ |
|
|
| **BDD support** | pytest-bdd | No | Native |
|
|
| **Coverage** | pytest-cov | coverage.py | Built-in |
|
|
| **Python 3.11+** | Yes | Yes | Yes |
|
|
| **Recommendation** | **MANDATORY** | FORBIDDEN | Optional (BDD/E2E) |
|
|
|
|
**Verdict**: Use **pytest** exclusively. NEVER use unittest. Consider robotframework for BDD/E2E.
|
|
|
|
---
|
|
|
|
### 11.4 CLI Framework Comparison
|
|
|
|
| Feature | Typer | argparse | Click | Textual |
|
|
| ------------------ | ---------------- | ------------ | --------------- | ------------ |
|
|
| **Stdlib** | No | Yes | No | No |
|
|
| **Type hints** | Native | Manual | Decorators | N/A |
|
|
| **Rich output** | Bundled | Manual | No | Native |
|
|
| **Subcommands** | Yes | Manual | Yes | N/A |
|
|
| **Auto help** | Yes | Yes | Yes | N/A |
|
|
| **Validation** | Type-based | Manual | Limited | N/A |
|
|
| **Use case** | Human CLI | Portable | Alternative | Full TUI |
|
|
| **Python 3.11+** | Yes | Yes | Yes | Yes |
|
|
| **Recommendation** | **Human-facing** | **Portable** | Not recommended | **TUI apps** |
|
|
|
|
**Verdict**: Use **Typer** for human-facing CLIs, **argparse** for portable scripts, **Textual** for TUIs.
|
|
|
|
---
|
|
|
|
### 11.5 Package Builder Comparison
|
|
|
|
| Feature | hatchling | setuptools | poetry | flit |
|
|
| ------------------ | --------------- | ------------ | -------------- | --------------- |
|
|
| **PEP 517** | Yes | Yes | Yes | Yes |
|
|
| **Speed** | Fast | Medium | Slow | Fast |
|
|
| **Complexity** | Low | Medium | High | Low |
|
|
| **Lock files** | No | No | Yes | No |
|
|
| **Plugins** | Yes | Many | Yes | Limited |
|
|
| **Configuration** | pyproject.toml | setup.py/cfg | pyproject.toml | pyproject.toml |
|
|
| **Python 3.11+** | Yes | Yes | Yes | Yes |
|
|
| **Recommendation** | **RECOMMENDED** | Legacy | Alternative | Simple packages |
|
|
|
|
**Verdict**: Use **hatchling** for modern packages, avoid setuptools for new projects.
|
|
|
|
---
|
|
|
|
## 12. Tool Dependency Graph
|
|
|
|
```mermaid
|
|
graph TD
|
|
uv[uv] --> pytest[pytest]
|
|
uv --> ruff[ruff]
|
|
uv --> mypy[mypy]
|
|
uv --> pyright[pyright]
|
|
|
|
pytest --> pytest-mock[pytest-mock]
|
|
pytest --> pytest-cov[pytest-cov]
|
|
pytest --> pytest-asyncio[pytest-asyncio]
|
|
pytest --> pytest-bdd[pytest-bdd]
|
|
pytest --> hypothesis[hypothesis]
|
|
|
|
pytest-cov --> mutmut[mutmut]
|
|
|
|
typer --> rich[Rich - bundled]
|
|
|
|
pre-commit --> ruff
|
|
pre-commit --> mypy
|
|
pre-commit --> pyright
|
|
pre-commit --> pytest
|
|
|
|
hatchling --> uv
|
|
|
|
validate_pep723 --> uv
|
|
|
|
style uv fill:#90EE90
|
|
style pytest fill:#87CEEB
|
|
style ruff fill:#FFD700
|
|
style typer fill:#DDA0DD
|
|
style pre-commit fill:#F0E68C
|
|
```
|
|
|
|
---
|
|
|
|
## 13. Installation Profiles
|
|
|
|
### 13.1 CLI Human-Facing Profile
|
|
|
|
```bash
|
|
#!/usr/bin/env -S uv --quiet run --active --script
|
|
# /// script
|
|
# requires-python = ">=3.11"
|
|
# dependencies = [
|
|
# "typer>=0.19.2", # Rich bundled - do NOT add separately
|
|
# ]
|
|
# ///
|
|
|
|
# Development dependencies
|
|
uv add --dev pytest pytest-mock pytest-cov mypy ruff pyright pre-commit
|
|
```
|
|
|
|
**Use Case**: Interactive CLI tools for humans with Rich output
|
|
|
|
---
|
|
|
|
### 13.2 CLI Portable Profile
|
|
|
|
```python
|
|
#!/usr/bin/env python3
|
|
# No dependencies - stdlib only
|
|
|
|
# Development dependencies
|
|
uv add --dev pytest mypy ruff pyright
|
|
```
|
|
|
|
**Use Case**: Maximum portability, no external dependencies
|
|
|
|
---
|
|
|
|
### 13.3 Testing Profile
|
|
|
|
```bash
|
|
# Core testing
|
|
uv add --dev pytest pytest-mock pytest-cov
|
|
|
|
# Extended testing
|
|
uv add --dev pytest-asyncio pytest-bdd pytest-benchmark hypothesis mutmut
|
|
|
|
# Quality tools
|
|
uv add --dev mypy ruff pyright pre-commit
|
|
```
|
|
|
|
**Use Case**: Comprehensive testing setup
|
|
|
|
---
|
|
|
|
### 13.4 Data Science Profile
|
|
|
|
```bash
|
|
# Data libraries
|
|
uv add datasette arrow httpx pydantic
|
|
|
|
# Development
|
|
uv add --dev pytest mypy ruff
|
|
```
|
|
|
|
**Use Case**: Data exploration and processing
|
|
|
|
---
|
|
|
|
### 13.5 Full Development Profile
|
|
|
|
```bash
|
|
# Core development
|
|
uv add typer pydantic requests
|
|
|
|
# Testing
|
|
uv add --dev pytest pytest-mock pytest-cov hypothesis mutmut
|
|
|
|
# Quality
|
|
uv add --dev ruff mypy pyright pre-commit bandit
|
|
|
|
# Optional
|
|
uv add --dev pytest-asyncio pytest-bdd robotframework
|
|
```
|
|
|
|
**Use Case**: Complete development environment
|
|
|
|
---
|
|
|
|
## 14. Tool Integration Patterns
|
|
|
|
### 14.1 Validation Pipeline Integration
|
|
|
|
```bash
|
|
# Preferred: Use pre-commit (runs all layers in correct order)
|
|
uv run pre-commit run --all-files
|
|
|
|
# Or individual layers:
|
|
|
|
# Layer 1: Format first
|
|
uv run ruff format .
|
|
|
|
# Layer 2: Linting
|
|
uv run ruff check .
|
|
|
|
# Layer 3: Type Checking (use project-detected checker)
|
|
uv run basedpyright . # or mypy based on project config
|
|
|
|
# Layer 4: Testing (coverage via pyproject.toml config)
|
|
uv run pytest
|
|
|
|
# Layer 5: PEP 723 (scripts only)
|
|
/shebangpython script.py
|
|
```
|
|
|
|
**Pattern**: Sequential validation gates
|
|
|
|
**Source**: pattern-extraction.md Section 8.1, taxonomy.md Section 6.4
|
|
|
|
---
|
|
|
|
### 14.2 Testing Stack Integration
|
|
|
|
```bash
|
|
# Standard test run (coverage via config)
|
|
uv run pytest
|
|
|
|
# Specific test directory
|
|
uv run pytest tests/unit/
|
|
uv run pytest tests/integration/ -v
|
|
|
|
# Async tests
|
|
uv run pytest tests/test_async.py --asyncio-mode=auto
|
|
|
|
# BDD tests
|
|
uv run pytest --gherkin-terminal-reporter features/
|
|
|
|
# Mutation testing (critical code)
|
|
uv run mutmut run
|
|
|
|
# Performance benchmarks
|
|
uv run pytest --benchmark-only tests/benchmarks/
|
|
```
|
|
|
|
**Pattern**: pytest + plugins ecosystem
|
|
|
|
**Source**: pattern-extraction.md Section 3.2
|
|
|
|
---
|
|
|
|
### 14.3 Pre-commit Hook Integration
|
|
|
|
```yaml
|
|
# .pre-commit-config.yaml
|
|
repos:
|
|
# Formatting and linting
|
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
rev: v0.6.0
|
|
hooks:
|
|
- id: ruff
|
|
args: [--fix]
|
|
- id: ruff-format
|
|
|
|
# Type checking
|
|
- repo: https://github.com/pre-commit/mirrors-mypy
|
|
rev: v1.11.0
|
|
hooks:
|
|
- id: mypy
|
|
args: [--strict]
|
|
|
|
# Security scanning
|
|
- repo: https://github.com/PyCQA/bandit
|
|
rev: 1.7.9
|
|
hooks:
|
|
- id: bandit
|
|
args: [-c, pyproject.toml]
|
|
|
|
# Local hooks
|
|
- repo: local
|
|
hooks:
|
|
- id: basedpyright
|
|
name: basedpyright
|
|
entry: uv run basedpyright
|
|
language: system
|
|
types: [python]
|
|
pass_filenames: false
|
|
|
|
- id: pytest
|
|
name: pytest
|
|
entry: uv run pytest
|
|
language: system
|
|
pass_filenames: false
|
|
always_run: true
|
|
|
|
- id: validate-pep723
|
|
name: validate PEP 723
|
|
entry: ~/.claude/tools/validate_pep723.py check
|
|
language: system
|
|
files: '^.*\.py$'
|
|
```
|
|
|
|
**Pattern**: ruff + mypy + bandit + pyright + pytest + validate_pep723
|
|
|
|
**Source**: pattern-extraction.md Section 3.5
|
|
|
|
---
|
|
|
|
### 14.4 uv + hatchling Packaging
|
|
|
|
```toml
|
|
# pyproject.toml - Minimal packaging configuration example
|
|
# NOTE: Replace ALL {{template_variables}} with actual values before creating file
|
|
[build-system]
|
|
requires = ["hatchling"]
|
|
build-backend = "hatchling.build"
|
|
|
|
[project]
|
|
name = "{{project_name_from_directory_or_git_remote}}"
|
|
version = "{{version_from_git_tag_or_default_0_1_0}}"
|
|
description = "{{project_description_from_user_or_readme}}"
|
|
authors = [
|
|
{name = "{{author_name_from_git_config_user_name}}", email = "{{author_email_from_git_config_user_email}}"},
|
|
]
|
|
dependencies = [
|
|
"typer>=0.19.2",
|
|
"pydantic>=2.0.0",
|
|
]
|
|
|
|
[project.optional-dependencies]
|
|
dev = [
|
|
"pytest>=8.0.0",
|
|
"pytest-mock>=3.14.0",
|
|
"pytest-cov>=5.0.0",
|
|
"mypy>=1.11.0",
|
|
"ruff>=0.6.0",
|
|
"pre-commit>=3.8.0",
|
|
]
|
|
|
|
[project.scripts]
|
|
{{cli_command_name_from_user}} = "{{package_name_from_project_name}}.cli:main"
|
|
|
|
[tool.hatchling.build.targets.wheel]
|
|
packages = ["packages/{{package_name_from_project_name}}"]
|
|
```
|
|
|
|
```bash
|
|
# Workflow
|
|
uv sync # Install dependencies
|
|
uv run pytest # Run tests
|
|
uv run ruff check . # Lint
|
|
uv run mypy . # Type check
|
|
uv build # Build package
|
|
uv publish # Publish to PyPI
|
|
```
|
|
|
|
**Pattern**: uv + hatchling modern packaging
|
|
|
|
---
|
|
|
|
## 15. Version Requirements Matrix
|
|
|
|
### 15.1 Python Version Support
|
|
|
|
| Tool | 3.11 | 3.12 | 3.13 | 3.14 | Notes |
|
|
| -------- | ---- | ---- | ---- | ---- | ------------------ |
|
|
| uv | ✓ | ✓ | ✓ | ✓ | Universal |
|
|
| ruff | ✓ | ✓ | ✓ | ✓ | Universal |
|
|
| mypy | ✓ | ✓ | ✓ | ✓ | Universal |
|
|
| pyright | ✓ | ✓ | ✓ | ✓ | Universal |
|
|
| pytest | ✓ | ✓ | ✓ | ✓ | Universal |
|
|
| typer | ✓ | ✓ | ✓ | ✓ | Requires 0.19.2+ |
|
|
| rich | ✓ | ✓ | ✓ | ✓ | Bundled with Typer |
|
|
| pydantic | ✓ | ✓ | ✓ | ✓ | v2 recommended |
|
|
| httpx | ✓ | ✓ | ✓ | ✓ | Async support |
|
|
| prefect | ✓ | ✓ | ✓ | ✓ | Modern workflow |
|
|
|
|
**Baseline**: Python 3.11+ required for all tools
|
|
|
|
---
|
|
|
|
### 15.2 Minimum Tool Versions
|
|
|
|
| Tool | Minimum Version | Reason |
|
|
| -------- | --------------- | ------------------------------ |
|
|
| typer | 0.19.2 | Rich bundling, modern features |
|
|
| pydantic | 2.0.0 | V2 rewrite, performance |
|
|
| pytest | 8.0.0 | Modern fixtures |
|
|
| mypy | 1.11.0 | Python 3.11+ support |
|
|
| ruff | 0.6.0 | Comprehensive rules |
|
|
| requests | 2.31.0 | Security fixes |
|
|
| arrow | 1.3.0 | Modern API |
|
|
|
|
---
|
|
|
|
### 15.3 Known Compatibility Issues
|
|
|
|
**None identified** for Python 3.11+ environment with listed minimum versions.
|
|
|
|
**Legacy Python** (3.8-3.10):
|
|
|
|
- Cannot use native generics syntax
|
|
- Cannot use union operator (`|`)
|
|
- Requires typing module imports
|
|
- NOT supported by this skill
|
|
|
|
---
|
|
|
|
## 16. Common Patterns and Usage
|
|
|
|
### 16.1 PEP 723 Script Template
|
|
|
|
```python
|
|
#!/usr/bin/env -S uv --quiet run --active --script
|
|
# /// script
|
|
# requires-python = ">=3.11"
|
|
# dependencies = [
|
|
# "typer>=0.19.2", # Rich bundled
|
|
# "pydantic>=2.0.0",
|
|
# "httpx>=0.27.0",
|
|
# ]
|
|
# ///
|
|
|
|
"""Modern CLI tool with type hints and validation.
|
|
|
|
This script demonstrates:
|
|
- PEP 723 inline metadata
|
|
- Typer CLI framework
|
|
- Pydantic data validation
|
|
- httpx async HTTP client
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from typing import Annotated
|
|
|
|
import httpx
|
|
import typer
|
|
from pydantic import BaseModel, Field
|
|
from rich.console import Console
|
|
|
|
app = typer.Typer(rich_markup_mode="rich")
|
|
console = Console()
|
|
|
|
class Config(BaseModel):
|
|
"""Configuration model."""
|
|
api_url: str = Field(..., description="API base URL")
|
|
timeout: int = Field(default=30, ge=1, le=300)
|
|
|
|
@app.command()
|
|
def fetch(
|
|
url: Annotated[str, typer.Argument(help="URL to fetch")],
|
|
config_file: Annotated[Path, typer.Option("--config", "-c")] = Path("config.json"),
|
|
) -> None:
|
|
"""Fetch data from API with [bold green]validation[/bold green]."""
|
|
# Load and validate config
|
|
config = Config.model_validate_json(config_file.read_text())
|
|
|
|
# Fetch data
|
|
response = httpx.get(url, timeout=config.timeout)
|
|
response.raise_for_status()
|
|
|
|
console.print("[green]:white_check_mark:[/green] Success!")
|
|
|
|
if __name__ == "__main__":
|
|
app()
|
|
```
|
|
|
|
**Validation**:
|
|
|
|
```bash
|
|
~/.claude/tools/validate_pep723.py check script.py
|
|
```
|
|
|
|
---
|
|
|
|
### 16.2 pytest Test Suite Template
|
|
|
|
```python
|
|
"""Test suite for authentication module.
|
|
|
|
Tests: User authentication system
|
|
Coverage: 95%+ (critical business logic)
|
|
"""
|
|
|
|
from typing import Generator
|
|
|
|
import pytest
|
|
from pytest_mock import MockerFixture
|
|
|
|
from app.auth import authenticate_user, AuthResult
|
|
from app.models import User
|
|
|
|
@pytest.fixture
|
|
def mock_database(mocker: MockerFixture) -> MockerFixture:
|
|
"""Mock database connection.
|
|
|
|
Returns:
|
|
Configured mocker for database operations.
|
|
"""
|
|
mock_db = mocker.Mock()
|
|
mock_db.get_user.return_value = User(
|
|
id=1,
|
|
username="testuser",
|
|
email="test@example.com",
|
|
password_hash="$2b$12$...", # bcrypt hash
|
|
)
|
|
return mocker.patch("app.auth.db", mock_db)
|
|
|
|
@pytest.fixture
|
|
def sample_user() -> User:
|
|
"""Provide sample user for testing.
|
|
|
|
Returns:
|
|
User instance with test data.
|
|
"""
|
|
return User(
|
|
id=1,
|
|
username="testuser",
|
|
email="test@example.com",
|
|
)
|
|
|
|
def test_authenticate_valid_credentials(
|
|
mock_database: MockerFixture,
|
|
sample_user: User,
|
|
) -> None:
|
|
"""Test authentication with valid credentials.
|
|
|
|
Tests: User authentication flow
|
|
How: Mock database, provide valid password, verify token generation
|
|
Why: Ensure core security functionality works correctly
|
|
"""
|
|
# Arrange
|
|
username = "testuser"
|
|
password = "ValidPass123!"
|
|
|
|
# Act
|
|
result = authenticate_user(username, password)
|
|
|
|
# Assert
|
|
assert result.success is True
|
|
assert result.token is not None
|
|
assert result.user_id == sample_user.id
|
|
mock_database.get_user.assert_called_once_with(username)
|
|
|
|
def test_authenticate_invalid_password(mock_database: MockerFixture) -> None:
|
|
"""Test authentication with invalid password.
|
|
|
|
Tests: Authentication failure handling
|
|
How: Provide incorrect password, verify failure
|
|
Why: Ensure security - wrong password must fail
|
|
"""
|
|
# Arrange
|
|
username = "testuser"
|
|
password = "WrongPassword"
|
|
|
|
# Act
|
|
result = authenticate_user(username, password)
|
|
|
|
# Assert
|
|
assert result.success is False
|
|
assert result.token is None
|
|
assert "invalid credentials" in result.error.lower()
|
|
|
|
@pytest.mark.parametrize("invalid_input", [
|
|
"",
|
|
None,
|
|
" " * 10,
|
|
"a", # Too short
|
|
])
|
|
def test_authenticate_invalid_input(
|
|
invalid_input: str | None,
|
|
mock_database: MockerFixture,
|
|
) -> None:
|
|
"""Test authentication with invalid inputs.
|
|
|
|
Tests: Input validation
|
|
How: Parametrized test with various invalid inputs
|
|
Why: Prevent errors from malformed data
|
|
"""
|
|
# Act & Assert
|
|
with pytest.raises(ValueError, match="Invalid username"):
|
|
authenticate_user(invalid_input, "password") # type: ignore
|
|
```
|
|
|
|
**Coverage**:
|
|
|
|
Coverage thresholds configured in `pyproject.toml` (95%+ for critical code like auth).
|
|
|
|
---
|
|
|
|
## 17. Documentation
|
|
|
|
### 17.1 When to Use Each Tool
|
|
|
|
**Development Phase**:
|
|
|
|
1. **Project Setup**: uv, hatchling
|
|
2. **Code Writing**: typer/argparse, pydantic, httpx/requests
|
|
3. **Testing**: pytest, pytest-mock, pytest-cov, hypothesis
|
|
4. **Quality**: ruff, mypy, pyright, bandit
|
|
5. **Pre-commit**: pre-commit, validate_pep723.py
|
|
6. **Building**: uv build (hatchling backend)
|
|
7. **Publishing**: uv publish
|
|
|
|
**Tool Selection Decision Tree**:
|
|
|
|
```text
|
|
Need to...
|
|
├─ Manage packages? → uv
|
|
├─ Lint code? → ruff
|
|
├─ Type check? → mypy + pyright
|
|
├─ Test code? → pytest + pytest-mock + pytest-cov
|
|
├─ Build CLI?
|
|
│ ├─ Human-facing? → typer (Rich bundled)
|
|
│ └─ Portable? → argparse
|
|
├─ Validate data? → pydantic
|
|
├─ Make HTTP requests?
|
|
│ ├─ Async? → httpx
|
|
│ └─ Sync? → requests
|
|
├─ Orchestrate workflows? → prefect
|
|
├─ Automate deployments? → fabric
|
|
├─ Template projects? → copier
|
|
├─ Explore data? → datasette
|
|
└─ Handle dates? → arrow
|
|
```
|
|
|
|
---
|
|
|
|
### 17.2 Tool Documentation References
|
|
|
|
**Official Documentation**:
|
|
|
|
- uv: <https://github.com/astral-sh/uv>
|
|
- ruff: <https://docs.astral.sh/ruff/>
|
|
- mypy: <https://mypy.readthedocs.io/>
|
|
- pyright: <https://microsoft.github.io/pyright/>
|
|
- pytest: <https://docs.pytest.org/>
|
|
- typer: <https://typer.tiangolo.com/>
|
|
- rich: <https://rich.readthedocs.io/>
|
|
- pydantic: <https://docs.pydantic.dev/>
|
|
- httpx: <https://www.python-httpx.org/>
|
|
- prefect: <https://docs.prefect.io/>
|
|
|
|
**MCP Tool Access**:
|
|
|
|
```python
|
|
# Get latest documentation
|
|
docs = mcp__context7__get-library-docs(
|
|
context7CompatibleLibraryID="/astral-sh/ruff",
|
|
topic="configuration"
|
|
)
|
|
|
|
# Search official docs
|
|
ref = mcp__Ref__ref_search_documentation(
|
|
query="pytest fixtures best practices"
|
|
)
|
|
|
|
# Get code examples
|
|
examples = mcp__exa__get_code_context_exa(
|
|
query="typer CLI with Rich tables"
|
|
)
|
|
```
|
|
|
|
---
|
|
|
|
## 18. Pyproject.toml Template Variable Reference
|
|
|
|
CRITICAL: This section defines template variables used in pyproject.toml examples throughout this document. The model MUST replace ALL template variables with actual values before creating any pyproject.toml file.
|
|
|
|
### 18.1 Template Variable Format
|
|
|
|
Template variables use the format: `{{descriptive_name_indicating_source}}`
|
|
|
|
Each variable name indicates:
|
|
|
|
1. WHAT value is needed
|
|
2. WHERE to obtain it from
|
|
|
|
### 18.2 Project Metadata Variables
|
|
|
|
**Project Name**:
|
|
|
|
```text
|
|
Variable: {{project_name_from_directory_or_git_remote}}
|
|
Sources (in priority order):
|
|
1. git config --get remote.origin.url | sed 's/.*\///' | sed 's/\.git$//'
|
|
2. basename "$(pwd)"
|
|
3. User input
|
|
Validation: Must be valid Python package name (lowercase, underscores, no hyphens)
|
|
Example: my_awesome_package
|
|
```
|
|
|
|
**Project Version**:
|
|
|
|
```text
|
|
Variable: {{version_from_git_tag_or_default_0_1_0}}
|
|
Sources (in priority order):
|
|
1. git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//'
|
|
2. Default: "0.1.0"
|
|
3. User input
|
|
Validation: Must follow semantic versioning (X.Y.Z)
|
|
Example: 1.2.3
|
|
```
|
|
|
|
**Project Description**:
|
|
|
|
```text
|
|
Variable: {{project_description_from_user_or_readme}}
|
|
Sources (in priority order):
|
|
1. First line of README.md after title
|
|
2. User input (REQUIRED if README.md missing)
|
|
Validation: Single-line string, <200 characters
|
|
Example: A modern Python CLI tool for processing CSV files
|
|
```
|
|
|
|
### 18.3 Author Variables
|
|
|
|
**Author Name**:
|
|
|
|
```text
|
|
Variable: {{author_name_from_git_config_user_name}}
|
|
Source: git config --get user.name
|
|
Fallback: User input (REQUIRED if git config missing)
|
|
Validation: Non-empty string
|
|
Example: Jane Developer
|
|
```
|
|
|
|
**Author Email**:
|
|
|
|
```text
|
|
Variable: {{author_email_from_git_config_user_email}}
|
|
Source: git config --get user.email
|
|
Fallback: User input (REQUIRED if git config missing)
|
|
Validation: Valid email format
|
|
Example: jane@example.com
|
|
```
|
|
|
|
### 18.4 Repository Variables
|
|
|
|
**Repository Namespace** (DEPRECATED):
|
|
|
|
```text
|
|
Variable: {{repository_namespace_from_git_remote}}
|
|
Status: DEPRECATED - Use {{repository_homepage_url_from_git_remote}} instead
|
|
Source: git config --get remote.origin.url | sed 's/.*[:/]\([^/]*\)\/[^/]*$/\1/'
|
|
Example: myusername or myorg
|
|
Legacy Use: Was used for GitHub-specific URL construction
|
|
Reason: Hardcoded GitHub domain assumptions. New variables derive complete URLs from git remote.
|
|
```
|
|
|
|
**Project Name from Git Remote**:
|
|
|
|
```text
|
|
Variable: {{project_name_from_git_remote}}
|
|
Source: git config --get remote.origin.url | sed 's/.*\///' | sed 's/\.git$//'
|
|
Example: my-awesome-project
|
|
Used in: URLs (preserves hyphens, unlike package name)
|
|
Note: Still valid for project naming. For URL construction, use {{repository_homepage_url_from_git_remote}}.
|
|
```
|
|
|
|
**Repository URL**:
|
|
|
|
```text
|
|
Variable: {{repository_url_from_git_remote_get_url}}
|
|
Source: git config --get remote.origin.url
|
|
Validation: Must be valid git URL
|
|
Example: https://github.com/myusername/my-project.git
|
|
```
|
|
|
|
**Repository Homepage URL**:
|
|
|
|
```text
|
|
Variable: {{repository_homepage_url_from_git_remote}}
|
|
Source: Git remote URL converted to web/HTTPS format
|
|
Bash Command:
|
|
GIT_URL=$(git config --get remote.origin.url)
|
|
# Convert SSH to HTTPS and remove .git suffix
|
|
# Handles: git@gitlab.com:user/repo.git -> https://gitlab.com/user/repo
|
|
# Handles: https://github.com/user/repo.git -> https://github.com/user/repo
|
|
HOMEPAGE_URL=$(echo "$GIT_URL" | sed 's|^git@\([^:]*\):\(.*\)\.git$|https://\1/\2|' | sed 's|\.git$||')
|
|
echo "$HOMEPAGE_URL"
|
|
Example:
|
|
- Git remote: git@gitlab.com:myorg/myproject.git → https://gitlab.com/myorg/myproject
|
|
- Git remote: https://github.com/user/repo.git → https://github.com/user/repo
|
|
Used In: [project.urls] Homepage = "{{repository_homepage_url_from_git_remote}}"
|
|
Priority: Optional - only if project has a git remote configured
|
|
```
|
|
|
|
**Repository Issues URL**:
|
|
|
|
```text
|
|
Variable: {{repository_issues_url_from_git_remote}}
|
|
Source: Repository homepage URL + platform-specific issues path
|
|
Bash Command:
|
|
GIT_URL=$(git config --get remote.origin.url)
|
|
HOMEPAGE_URL=$(echo "$GIT_URL" | sed 's|^git@\([^:]*\):\(.*\)\.git$|https://\1/\2|' | sed 's|\.git$||')
|
|
# GitLab uses /-/issues, GitHub uses /issues
|
|
if echo "$HOMEPAGE_URL" | grep -q "gitlab"; then
|
|
ISSUES_URL="${HOMEPAGE_URL}/-/issues"
|
|
else
|
|
ISSUES_URL="${HOMEPAGE_URL}/issues"
|
|
fi
|
|
echo "$ISSUES_URL"
|
|
Example:
|
|
- GitLab: https://gitlab.com/myorg/myproject → https://gitlab.com/myorg/myproject/-/issues
|
|
- GitHub: https://github.com/user/repo → https://github.com/user/repo/issues
|
|
Used In: [project.urls] Issues = "{{repository_issues_url_from_git_remote}}"
|
|
Priority: Optional - only if project tracks issues in the repository
|
|
```
|
|
|
|
### 18.5 CLI and Package Variables
|
|
|
|
**CLI Command Name**:
|
|
|
|
```text
|
|
Variable: {{cli_command_name_from_user}}
|
|
Source: User input (REQUIRED for CLI projects)
|
|
Validation: Valid shell command name (lowercase, hyphens ok)
|
|
Example: my-cli or myapp
|
|
Used in: [project.scripts] entry point
|
|
```
|
|
|
|
**Package Name from Project Name**:
|
|
|
|
```text
|
|
Variable: {{package_name_from_project_name}}
|
|
Source: Derived from project_name (replace hyphens with underscores)
|
|
Bash Command:
|
|
PROJECT_NAME=$(git config --get remote.origin.url | sed 's/.*\///' | sed 's/\.git$//')
|
|
PACKAGE_NAME=$(echo "$PROJECT_NAME" | tr '-' '_')
|
|
echo "$PACKAGE_NAME"
|
|
Example:
|
|
- Project: mcp-config-tools → Package: mcp_config_tools
|
|
- Project: my_tool → Package: my_tool
|
|
Used in:
|
|
- [tool.hatchling.build.targets.wheel] packages = ["packages/{{package_name_from_project_name}}"]
|
|
- [project.scripts] command = "{{package_name_from_project_name}}.cli:main"
|
|
- Import paths in code
|
|
Priority: Mandatory - required for correct package structure
|
|
```
|
|
|
|
### 18.6 Optional Metadata Variables
|
|
|
|
**License Type**:
|
|
|
|
```text
|
|
Variable: {{license_type_from_user_or_default_MIT}}
|
|
Sources (in priority order):
|
|
1. Detected from LICENSE file
|
|
2. Default: "MIT"
|
|
3. User input
|
|
Common values: MIT, Apache-2.0, GPL-3.0, BSD-3-Clause
|
|
Example: MIT
|
|
```
|
|
|
|
**Project Keywords**:
|
|
|
|
```text
|
|
Variable: {{project_keywords_from_user}}
|
|
Source: User input (optional)
|
|
Format: Comma-separated quoted strings
|
|
Example: "cli", "csv", "data-processing", "automation"
|
|
```
|
|
|
|
**Development Status**:
|
|
|
|
```text
|
|
Variable: {{dev_status_from_user}}
|
|
Source: User input with default suggestions
|
|
Common values:
|
|
- 3 - Alpha
|
|
- 4 - Beta
|
|
- 5 - Production/Stable
|
|
Example: 4 - Beta
|
|
```
|
|
|
|
**Intended Audience**:
|
|
|
|
```text
|
|
Variable: {{audience_from_user}}
|
|
Source: User input with default suggestions
|
|
Common values: Developers, System Administrators, End Users/Desktop
|
|
Example: Developers
|
|
```
|
|
|
|
**Documentation URL**:
|
|
|
|
```text
|
|
Variable: {{documentation_url_from_user_or_readme}}
|
|
Sources (in priority order):
|
|
1. User input (if custom docs site)
|
|
2. Derive from repository homepage + #readme: {{repository_homepage_url_from_git_remote}}#readme
|
|
Example: https://my-project.readthedocs.io/ or https://gitlab.com/myorg/myproject#readme
|
|
```
|
|
|
|
### 18.7 Variable Gathering Procedure
|
|
|
|
PROCEDURE for agents creating pyproject.toml files:
|
|
|
|
1. Execute git commands to gather available values
|
|
2. Read README.md for description if present
|
|
3. Derive package names from project names
|
|
4. Prompt user for REQUIRED missing values:
|
|
- description (if README.md missing)
|
|
- cli_command_name (for CLI projects)
|
|
- author info (if git config missing)
|
|
5. Apply defaults for optional values
|
|
6. Validate all values meet format requirements
|
|
7. Replace ALL template variables in template
|
|
8. Write final pyproject.toml with NO template variable syntax remaining
|
|
|
|
### 18.8 Example Gathering Script
|
|
|
|
```bash
|
|
#!/usr/bin/env bash
|
|
# gather_project_metadata.sh - Collect values for pyproject.toml template variables
|
|
|
|
# Git-based values
|
|
PROJECT_NAME=$(git config --get remote.origin.url | sed 's/.*\///' | sed 's/\.git$//' | tr '-' '_')
|
|
VERSION=$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//' || echo "0.1.0")
|
|
REPO_NAMESPACE=$(git config --get remote.origin.url | sed 's/.*[:/]\([^/]*\)\/[^/]*$/\1/')
|
|
REPO_URL=$(git config --get remote.origin.url)
|
|
AUTHOR_NAME=$(git config --get user.name)
|
|
AUTHOR_EMAIL=$(git config --get user.email)
|
|
|
|
# Directory-based fallback
|
|
if [ -z "$PROJECT_NAME" ]; then
|
|
PROJECT_NAME=$(basename "$(pwd)" | tr '-' '_')
|
|
fi
|
|
|
|
# README-based description
|
|
if [ -f "README.md" ]; then
|
|
DESCRIPTION=$(grep -v "^#" README.md | grep -v "^$" | head -1 | sed 's/^[[:space:]]*//')
|
|
fi
|
|
|
|
# Output gathered values
|
|
echo "PROJECT_NAME=$PROJECT_NAME"
|
|
echo "VERSION=$VERSION"
|
|
echo "REPO_NAMESPACE=$REPO_NAMESPACE"
|
|
echo "REPO_URL=$REPO_URL"
|
|
echo "AUTHOR_NAME=$AUTHOR_NAME"
|
|
echo "AUTHOR_EMAIL=$AUTHOR_EMAIL"
|
|
echo "DESCRIPTION=$DESCRIPTION"
|
|
```
|
|
|
|
---
|
|
|
|
## 19. Mandatory Rules for Agent File Creation
|
|
|
|
CRITICAL RULES: The model MUST follow these rules when creating pyproject.toml files.
|
|
|
|
### 19.1 Template Variable Replacement Rule
|
|
|
|
RULE: The model MUST replace ALL template variables with actual values before creating pyproject.toml
|
|
|
|
TRIGGER: Agent task involves creating or writing a pyproject.toml file
|
|
|
|
PROCEDURE:
|
|
|
|
1. Identify all {{template_variable}} instances in template
|
|
2. Execute gathering procedure from section 18.7
|
|
3. Replace each {{template_variable}} with actual value
|
|
4. Verify NO {{template_variable}} syntax remains in output
|
|
5. Validate all required fields are present with non-placeholder values
|
|
|
|
CONSTRAINT: The model MUST NOT write pyproject.toml files containing {{template_variable}} syntax
|
|
|
|
### 19.2 Value Validation Rule
|
|
|
|
RULE: The model MUST validate all gathered values meet PEP 621 requirements
|
|
|
|
VALIDATION_CHECKS:
|
|
|
|
- name: Valid Python package name (lowercase, underscores only)
|
|
- version: Semantic versioning format (X.Y.Z)
|
|
- description: Non-empty string <200 characters
|
|
- authors: At least one author with name and email
|
|
- requires-python: Minimum Python version specified
|
|
- dependencies: Valid package specifiers
|
|
|
|
CONSTRAINT: The model MUST NOT proceed with invalid values
|
|
|
|
### 19.3 Git Config Availability Rule
|
|
|
|
RULE: The model MUST verify git configuration availability before using git-based variables
|
|
|
|
CONDITION: IF git config values are unavailable THEN model MUST prompt user for required values
|
|
|
|
PROCEDURE:
|
|
|
|
1. Test: git config --get user.name
|
|
2. IF empty THEN prompt user for author name
|
|
3. Test: git config --get user.email
|
|
4. IF empty THEN prompt user for author email
|
|
5. Continue with remaining variable gathering
|
|
|
|
### 19.4 Placeholder Detection Rule
|
|
|
|
RULE: The model MUST detect and reject placeholder values in final output
|
|
|
|
FORBIDDEN_PATTERNS:
|
|
|
|
- "mypackage"
|
|
- "Author Name"
|
|
- "<author@example.com>"
|
|
- "yourusername"
|
|
- "My Python package" (generic description)
|
|
- Any string containing "example" in email or URL fields
|
|
|
|
VERIFICATION:
|
|
|
|
```bash
|
|
# Before writing file, model must verify none of these patterns exist:
|
|
grep -E "(mypackage|Author Name|author@example\.com|yourusername)" pyproject.toml
|
|
# If match found: ABORT and gather actual values
|
|
```
|
|
|
|
### 19.5 User Prompt Rule for Missing Values
|
|
|
|
RULE: The model MUST prompt user for values that cannot be gathered automatically
|
|
|
|
REQUIRED_PROMPTS when source unavailable:
|
|
|
|
- Project description (if no README.md)
|
|
- CLI command name (for CLI projects)
|
|
- Author name/email (if git config empty)
|
|
- Keywords (optional but recommended)
|
|
- License type (if no LICENSE file and not using MIT default)
|
|
|
|
PROMPT_FORMAT:
|
|
|
|
```text
|
|
I need the following information to complete pyproject.toml:
|
|
|
|
1. Project description (brief one-line summary): ___
|
|
2. CLI command name (what users type to run it): ___
|
|
3. Author name: ___ [detected: $NAME, press Enter to use]
|
|
4. Author email: ___ [detected: $EMAIL, press Enter to use]
|
|
```
|
|
|
|
### 19.6 Final Verification Rule
|
|
|
|
RULE: The model MUST perform final verification before writing pyproject.toml
|
|
|
|
VERIFICATION_CHECKLIST:
|
|
|
|
- [ ] NO {{template_variable}} syntax present
|
|
- [ ] NO placeholder values (mypackage, Author Name, etc.)
|
|
- [ ] ALL required fields present: name, version, description, authors
|
|
- [ ] Author email matches valid email regex
|
|
- [ ] Package name is valid Python identifier (lowercase, underscores)
|
|
- [ ] Version follows semantic versioning
|
|
- [ ] Dependencies have version specifiers
|
|
|
|
CONSTRAINT: The model MUST NOT write file if ANY checklist item fails
|
|
|
|
### 19.7 Error Handling Rule
|
|
|
|
RULE: The model MUST report specific validation failures and remediation steps
|
|
|
|
IF validation fails THEN:
|
|
|
|
1. Report which check failed
|
|
2. Show actual vs expected value format
|
|
3. Provide exact command to gather correct value
|
|
4. Wait for user to provide correction
|
|
5. Re-validate before proceeding
|
|
|
|
EXAMPLE_ERROR_REPORT:
|
|
|
|
```text
|
|
❌ Validation failed: author_email
|
|
|
|
Current value: "author@example.com"
|
|
Problem: Placeholder value detected
|
|
Expected: Valid email address from git config or user input
|
|
|
|
To fix, run: git config --get user.email
|
|
Or provide your email address: ___
|
|
```
|
|
|
|
---
|
|
|
|
## Document Metadata
|
|
|
|
**Created**: 2025-10-21 **Version**: 1.1.0 **Tools Documented**: 50+ **Categories**: 10 **Sources**: pattern-extraction.md, taxonomy.md, 13 discovery reports **Python Versions**: 3.11-3.14 **Status**: Complete
|
|
|
|
**Recent Updates**:
|
|
|
|
- 2025-11-17 v1.1.0: Added template variable system for pyproject.toml examples (sections 18-19)
|
|
|
|
**Coverage Summary**:
|
|
|
|
- Development Tools: 7 (uv, ruff, mypy, pyright, pre-commit, prospector, bandit)
|
|
- Testing Tools: 9 (pytest, pytest-mock, pytest-cov, hypothesis, mutmut, robotframework, pytest-asyncio, pytest-bdd, pytest-benchmark)
|
|
- CLI Frameworks: 4 (typer, rich, argparse, textual)
|
|
- Data Libraries: 5 (datasette, arrow, httpx, requests, pydantic)
|
|
- Workflow Tools: 4 (prefect, fabric, copier, invoke)
|
|
- IoT/Messaging: 2 (paho-mqtt, blinker)
|
|
- Build Tools: 4 (uv, hatchling, shiv, pip-tools)
|
|
- Quality Tools: 1 (validate_pep723.py)
|
|
- MCP Tools: 7 (context7, ref, exa, github, sequential-thinking, websearch, webfetch)
|
|
- Utility Libraries: 0 (boltons mentioned in requirements but not yet documented)
|
|
|
|
**Next Steps**:
|
|
|
|
1. Add boltons utility library documentation
|
|
2. Expand Textual framework section
|
|
3. Add more advanced integration patterns
|
|
4. Create tool migration guides
|
|
5. Add troubleshooting sections
|
|
|
|
---
|
|
|
|
_This registry serves as the authoritative tool and library reference for the opinionated-python-development skill. All tool selections, versions, and integration patterns should align with this documentation._
|