From wf
Project coding conventions covering code quality, structure, typing, logging, and style. Always apply when writing, reviewing, or modifying Python code.
How this skill is triggered — by the user, by Claude, or both
Slash command
/wf:conventionsThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Project coding conventions for all Python code. Covers structure, style, quality, and logging. For detailed tool configurations see [tooling.md](./tooling.md). For file templates see [templates.md](./templates.md).
Project coding conventions for all Python code. Covers structure, style, quality, and logging. For detailed tool configurations see tooling.md. For file templates see templates.md.
Use src-layout with layered architecture:
${PROJECT_NAME}/
├── pyproject.toml
├── mkdocs.yml
├── docs/
│ ├── index.md
│ └── scripts/
│ └── gen_ref_pages.py
├── src/
│ └── ${PROJECT_NAME}/
│ ├── __init__.py
│ ├── _version.py # Auto-generated by hatch-vcs
│ ├── contracts/ # API schemas — single source of truth
│ ├── core/ # Infrastructure only (logger, config, exceptions)
│ ├── models/ # Shared domain models (Pydantic)
│ ├── services/ # Business logic (framework-agnostic)
│ └── interfaces/ # Entry points
│ ├── cli/ # CLI (Typer)
│ ├── rest/ # REST API (FastAPI)
│ └── rpc/ # JSON-RPC over WebSocket
└── tests/
├── conftest.py
└── ... # Mirror src/ structure
Target Python 3.13+:
[project]
requires-python = ">=3.13"
import os
from pathlib import Path
import httpx
from pydantic import BaseModel
from ${PROJECT_NAME}.core import logger
from ${PROJECT_NAME}.services.processor import process_data
from x import y for specific itemsAlways use type hints on all function signatures:
def process_file(
filepath: Path,
options: dict[str, Any] | None = None,
) -> ProcessResult:
...
list[str] # not List[str]
dict[str, int] # not Dict[str, int]
str | None # not Optional[str]
int | str # not Union[int, str]
Google-style for all public functions:
def fetch_data(url: str, timeout: int = 30) -> dict[str, Any]:
"""Fetch data from a URL and return parsed JSON.
Args:
url: The URL to fetch data from.
timeout: Request timeout in seconds. Defaults to 30.
Returns:
Parsed JSON response as a dictionary.
Raises:
httpx.HTTPError: If the request fails.
"""
...
file_count not fc, user_data not ud)ALL_CAPS at module level — extract magic numberssnake_case, imperative verbsMAX_RETRIES = 3
DEFAULT_TIMEOUT = 30
SUPPORTED_FORMATS = {"json", "yaml", "toml"}
Never use print() — always use logger.
from ${PROJECT_NAME}.core import logger
logger.debug(f"Processing item {i} of {total}")
logger.info(f"Processing {count} files")
logger.success(f"Completed: {result}")
logger.warning(f"Rate limit approaching")
logger.error(f"Failed to process: {error}")
logger.critical("System failure")
# Log exceptions with context
try:
process()
except Exception as e:
logger.error(f"Processing failed: {e}", exc_info=True)
raise
# Progress logging for long operations
for i, item in enumerate(items, 1):
process_item(item)
if i % 100 == 0:
logger.info(f"Progress: {i}/{total} items processed")
logger.success(f"Completed processing {total} items")
def test_function_logs_correctly(caplog):
with caplog.at_level("INFO"):
my_function()
assert "Expected message" in caplog.text
# Specific exceptions, not bare except
try:
result = process(data)
except FileNotFoundError:
logger.error(f"File not found: {filepath}")
raise
except ValueError as e:
logger.error(f"Invalid data: {e}")
raise
# Custom exceptions in core/exceptions.py
class ProcessingError(Exception):
"""Raised when processing fails."""
pass
# Validate early, fail fast
def process(data: str) -> Result:
if not data:
raise ValueError("data cannot be empty")
...
Use environment variables via pydantic-settings:
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
debug: bool = False
api_key: str
database_url: str
model_config = {"env_prefix": "${PROJECT_NAME}_"}
settings = Settings()
Before committing:
print()except)uv run ruff check . passesuv run pyright passes| Aspect | Convention |
|---|---|
| Python version | 3.13+ |
| Package manager | uv |
| Build system | Hatchling + hatch-vcs |
| Versioning | Git tags (vX.Y.Z) |
| Linter/Formatter | Ruff |
| Type checker | Pyright (strict) |
| Test framework | pytest |
| Documentation | Material for MkDocs |
| Docstring style | |
| Logging | loguru (never print()) |
| CLI | Typer |
| REST API | FastAPI |
| JSON-RPC / WebSocket | jsonrpc-websocket, websockets |
| Line length | 88 |
| Import style | Absolute, sorted |
${PROJECT_NAME}npx claudepluginhub mesca/claude-plugins --plugin wfConfigures ruff/mypy for Python linting/formatting, enforces PEP 8 naming/docstrings/type hints. Use for new projects, code reviews, or style standards.
Enforces Python standards with PEP 8 via Black (100-char lines), type hints on functions/classes, and Google docstrings. Use for writing/formatting Python code.
Provides tiered Python development guidance from simple scripts to production systems, covering PEP-8 style, Ruff linting, pytest testing, mypy typing, uv tooling, security, and packaging.