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

4.0 KiB

name, description
name description
python-style-preferences 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.
  1. 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(...).
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:
    ...
  1. 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.
  1. 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.
# 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]
  1. 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.

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:
    ...
  1. 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.