gali-leilei

write-python

1
0
# Install this skill:
npx skills add gali-leilei/agent-skills-md --skill "write-python"

Install specific skill from multi-skill repository

# Description

Write idiomatic and modern (3.14+) python code. Use when writing Python code, CLI tools, scripts, or services. Emphasizes stdlib, type hints, uv/ruff toolchain, and minimal dependencies.

# SKILL.md


name: write-python
description: Write idiomatic and modern (3.14+) python code. Use when writing Python code, CLI tools, scripts, or services. Emphasizes stdlib, type hints, uv/ruff toolchain, and minimal dependencies.
user-invocable: false
context: fork
agent: python-engineer
allowed-tools:
- Read
- Bash
- Grep
- Glob


Python Development (3.14+)

Core Philosophy

  1. Stdlib and Mature Libraries First
  2. Prefer Python stdlib solutions
  3. Have as few external dependencies as possible
  4. Prefer dataclasses over attrs, pathlib over os.path

  5. Type Hints Everywhere (No Any)

  6. Python 3.14 has lazy annotations by default
  7. Avoid Any — use concrete types or generics
  8. Use native type if possible, i.e. dict over Dict, list over List.
  9. Avoid old syntax such as Union, Optinal, Generic.

  10. Library Preference

  11. Prefer dataclasses over attrs and pydantic
  12. Prefer pathlib over os.path
  13. Prefer urlib3 over requests
  14. Prefer uv/ruff over pip/venv

  15. Explicit over Implicit

  16. Prefer dataclasses over def __init__(self, ...)
  17. Avoid setattr, getattr, importlib
  18. Avoid default value for keyword argument
  19. Prefer explicit loop over clever list comprehension
  20. Prefer explict in conditional statement, if len(arr) == 0 over if arr
  21. Only have function and class in library, avoid assginment expression
  22. Prefer TypedDict over dict if passing dictionary around

  23. Composition over Inheritance

  24. Prefer Protocol over ABC
  25. Avoid all design patterns inspired by Java, such as Mixin, Factory etc.
  26. Prefer stateless function over hidden dependencies

  27. Flat Control Flow

  28. Guard clauses with early returns
  29. Pattern matching to flatten conditionals
  30. Maximum 2 levels of nesting

  31. Explicit Error Handling

  32. Custom exception hierarchy for domain errors
  33. Raise early, handle at boundaries
  34. except ValueError | TypeError: (no parens)

Quick Patterns

Protocol-Based Dependency Injection

from typing import Protocol

# Protocol at consumer (like Go interfaces)
class UserStore(Protocol):
    uuid: str
    def get(self, id: str) -> User | None: ...
    def save(self, user: User) -> None: ...

class UserService:
    def __init__(self, store: UserStore):
        self.store = store  # accepts any matching impl

Flat Control Flow (No Nesting)

# GOOD: guard clauses, early returns
def process(user: User | None) -> Result:
    if user is None:
        raise ValueError("user required")
    if not user.email:
        raise ValueError("email required")
    if not is_valid_email(user.email):
        raise ValueError("invalid email")
    return do_work(user)  # happy path at end

# BAD: nested conditions
def process(user: User | None) -> Result:
    if user is not None:
        if user.email:
            if is_valid_email(user.email):
                return do_work(user)
    raise ValueError("invalid")

Pattern Matching

# Flatten complex conditionals with match
match event:
    case {"type": "click", "x": x, "y": y}:
        handle_click(x, y)
    case {"type": "key", "code": code}:
        handle_key(code)
    case _:
        raise ValueError(f"Unknown event: {event}")

Type Hints (No Any)

# GOOD: concrete types
def process_users(users: list[User], limit: int | None = None) -> list[Result]:
    ...

# GOOD: generics when needed
def first[T](items: list[T]) -> T | None:
    return items[0] if items else None

# BAD: unnecessary Any
def process(data: Any) -> Any:  # Don't do this
    ...

Error Handling

# except without parens (3.14)
except ValueError | TypeError:
    handle_error()

# Custom exceptions
class NotFoundError(AppError):
    def __init__(self, resource: str, id: str):
        self.resource = resource
        self.id = id
        super().__init__(f"{resource} not found: {id}")

Python 3.14 Features

  • Deferred annotations: No from __future__ import annotations
  • Template strings (t""): t"Hello {name}" returns Template
  • except without parens: except ValueError | TypeError:
  • concurrent.interpreters: True parallelism
  • compression.zstd: Zstandard in stdlib
  • Free-threaded build: No GIL (opt-in)

References

Tooling

uv sync                    # Install deps
ruff check --fix .         # Lint and autofix
ruff format .              # Format
pytest -v                  # Test
mypy .                     # Type check

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.