Files
skill-python-style-preferences/SKILL.md
T
2026-03-13 14:54:25 +08:00

112 lines
4.0 KiB
Markdown

---
name: python-style-preferences
description: Apply the user's preferred Python engineering style for new modules, refactors, reviews, and project scaffolding. Use when working on Python CLIs, async services, libraries, typed data pipelines, or tensor-heavy code that should standardize on uv, anyio, click, full type annotations, basedpyright, jaxtyping, and beartype.
---
# Python Style Preferences
## Overview
Follow these conventions whenever the task is primarily Python:
- Use `uv` for dependency management, virtualenv creation, locking, and command execution.
- Prefer `anyio` over raw `asyncio` APIs.
- Build CLIs with `click`.
- Keep type annotations comprehensive enough for `basedpyright` to be useful by default.
## Working Style
1. Start with typed domain shapes.
- Prefer `TypedDict` for reusable mapping-shaped payloads.
- Prefer `@dataclass(slots=True)` for reusable owned records and value objects.
- Avoid reusable bare `dict[str, object]` structures; keep ad hoc dicts local and short-lived.
2. Keep entrypoints thin.
- Put parsing and CLI wiring in `click` commands.
- Put business logic in typed functions and classes.
- For async CLIs, use a synchronous `click` entrypoint that calls `anyio.run(...)`.
```python
from pathlib import Path
import anyio
import click
@click.command()
@click.argument("config_path", type=click.Path(path_type=Path))
def main(config_path: Path) -> None:
anyio.run(run, config_path)
async def run(config_path: Path) -> None:
...
```
3. Use `anyio` primitives consistently.
- Prefer `anyio.create_task_group()`, `anyio.fail_after()`, streams, and cancellation scopes.
- Do not mix `asyncio.create_task`, `asyncio.gather`, or manual event-loop management into `anyio` code unless an external integration forces it.
- When an `asyncio` boundary is unavoidable, isolate it and leave a short note.
4. Treat typing as enforcement, not decoration.
- Annotate public functions, methods, return values, and reusable internal helpers.
- Run `basedpyright` as the default type-checking pass and keep new code clean.
- Allow `cast(...)` only at trusted boundaries where runtime guarantees exist but inference cannot express them. Leave a short reason comment immediately above it.
- Allow `# type: ignore[...]` only when it is narrow and justified. Leave a short reason comment immediately above it.
```python
# basedpyright cannot infer the validated plugin registry value type here.
runner = cast(Runner, registry[name])
# The vendor stub is wrong for this overload; runtime input is validated above.
value = vendor_api.load(path) # type: ignore[call-overload]
```
5. Use `jaxtyping` for arrays and tensors.
Short summary:
- Use `DType[ArrayType, "shape names"]`, for example `Float[np.ndarray, "batch channels"]`.
- Reuse axis names to express shared dimensions across arguments and returns.
- Use `...` for arbitrary extra axes and fixed integers for exact sizes.
- Prefer reusable aliases for common tensor shapes.
- Prefer concrete array types after normalization; use `ArrayLike` only at loose input boundaries.
See `references/jaxtyping-summary.md` for the fuller cheat sheet.
```python
import numpy as np
from beartype import beartype
from jaxtyping import Float, jaxtyped
Batch = Float[np.ndarray, "batch channels"]
@jaxtyped(typechecker=beartype)
def normalize(x: Batch) -> Batch:
...
```
6. Use runtime type checking where it pays for itself.
- Prefer `beartype` together with `@jaxtyped(typechecker=beartype)` on stable boundaries, data adapters, numerical helpers, and test-targeted functions.
- Avoid decorating the hottest inner loops unless the cost is clearly acceptable.
- Avoid `from __future__ import annotations` or stringized annotations when runtime checking must inspect annotations directly.
## Verification
Use this order unless the project already has a stricter local workflow:
1. `uv sync --dev`
2. `uv run basedpyright`
3. `uv run pytest`
4. `uv run python -m <package_or_module>` or a CLI smoke test when relevant
## Reference Files
- Read `references/jaxtyping-summary.md` when writing or reviewing array/tensor annotations.