Opencode-config-backup python-engineer

Python Engineer Skill

install
source · Clone the upstream repo
git clone https://github.com/jieni777/opencode-config-backup
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jieni777/opencode-config-backup "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/python-engineer" ~/.claude/skills/jieni777-opencode-config-backup-python-engineer && rm -rf "$T"
manifest: skills/python-engineer/SKILL.md
source content

Python Engineer Skill

Comprehensive Python development guidance for modern, production-ready applications. Covers best practices, tooling, frameworks, and productivity patterns.

Metadata

  • Name: python-engineer
  • Description: Expert Python development with modern best practices, type hints, async/await, testing, packaging, and framework selection guidance
  • License: MIT

Design Philosophy

Purpose

To provide authoritative guidance for Python development that balances:

  • Code quality (PEP 8, type safety, testing)
  • Developer productivity (tooling, automation, modern patterns)
  • Performance (async, profiling, optimization)
  • Maintainability (clear structure, documentation, modularity)

Tone

  • Modern: Python 3.9+ features, contemporary tooling (uv, ruff, setuptools_scm)
  • Practical: Real-world patterns over theoretical purity
  • Opinionated: Clear defaults with justification for alternatives

Constraints

ALWAYS:

  • Use type hints for public APIs
  • Follow PEP 8 (enforced by black/ruff)
  • Write tests with pytest
  • Use
    uv
    for new projects (10-100x faster than pip)
  • Prefer
    src
    layout for packages
  • Use
    pyproject.toml
    (PEP 621 standard)

NEVER:

  • Suppress type errors with
    # type: ignore
    (fix the code)
  • Use mutable default arguments (use
    None
    and set default)
  • Ignore test coverage (aim for >80%)
  • Hardcode secrets (use environment variables/Pydantic Settings)
  • Mix
    print()
    with logging (use proper logging)

Differentiation

AspectThis SkillOthers
Python Version3.9+ (current best practices)Legacy 2.7/3.6 support
Dependency Managementuv (fast, modern)poetry/pip/venv (slower)
Lintingruff (Python-written, 10-100x faster)black+flake8 (separate tools)
Testingpytest with modern pluginsunittest/legacy approaches
PackagingPEP 621 pyproject.toml + setuptools_scmsetup.py/setup.cfg
Type Checkingmypy strict mode for librariesOptional/relaxed

Python Best Practices

Code Style & Formatting

Primary Tools:

  • ruff: Linting and formatting (replaces black, flake8, isort)
    • 10-100x faster than alternatives
    • Compatible with black 99% of the time
    • Write in Rust for performance
  • Configuration in
    pyproject.toml
    :
[tool.ruff]
line-length = 88
target-version = "py39"

[tool.ruff.lint]
select = ["E", "F", "I", "N", "W"]
ignore = ["E501"]  # Let black handle line length

[tool.ruff.format]
quote-style = "double"
indent-style = "space"

Pre-commit hooks (

.pre-commit-config.yaml
):

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.1.0
    hooks:
      - id: ruff
        args: [--fix]
      - id: ruff-format

Type Hints

Always use type hints for:

  • Function parameters and return values
  • Class attributes
  • Public API surfaces
  • Complex data structures
from typing import Optional, List, Dict, Any
from dataclasses import dataclass
from collections.abc import Sequence

# Preferred: Use dataclasses for structured data
@dataclass
class User:
    id: int
    name: str
    email: str
    roles: Sequence[str]

# Function with comprehensive type hints
async def fetch_users(
    *,
    limit: Optional[int] = None,
    filters: Dict[str, Any] | None = None,
) -> List[User]:
    """Fetch users from database.

    Args:
        limit: Maximum number of users to return
        filters: Key-value filters for query

    Returns:
        List of User objects
    """
    filters = filters or {}
    # Implementation
    return []

Mypy configuration (

pyproject.toml
):

[tool.mypy]
python_version = "3.9"
strict = true  # Libraries: strict mode
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = true

For applications, use

warn_return_any = true
without full strict mode.

Testing with pytest

Project structure:

myproject/
├── src/
│   └── myproject/
│       ├── __init__.py
│       ├── main.py
│       └── utils.py
├── tests/
│   ├── conftest.py
│   ├── test_main.py
│   └── test_utils.py

Example test (

tests/test_utils.py
):

import pytest
from myproject.utils import calculate_sum

def test_calculate_sum_basic():
    assert calculate_sum([1, 2, 3]) == 6

@pytest.mark.parametrize("input,expected", [
    ([], 0),
    ([1], 1),
    ([1, 2, 3], 6),
])
def test_calculate_sum_various(input, expected):
    assert calculate_sum(input) == expected

@pytest.mark.asyncio
async def test_async_function():
    result = await async_operation()
    assert result is not None

pytest configuration (

pyproject.toml
):

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
    "--strict-markers",
    "--strict-config",
    "--cov=src/myproject",
    "--cov-report=term-missing",
    "--cov-report=html",
]

Async/await Patterns

When to use async:

  • I/O-bound operations (HTTP requests, database queries)
  • Network operations (websockets, streams)
  • Concurrent tasks without CPU bottlenecks

Example patterns:

import asyncio
from typing import AsyncIterable

# Parallel async operations
async def fetch_multiple(urls: Sequence[str]) -> List[Response]:
    """Fetch multiple URLs concurrently."""
    async with httpx.AsyncClient() as client:
        tasks = [client.get(url) for url in urls]
        responses = await asyncio.gather(*tasks, return_exceptions=True)
        return responses

# Async context manager
class DatabaseConnection:
    async def __aenter__(self):
        self.conn = await asyncpg.connect(...)
        return self.conn

    async def __aexit__(self, exc_type, exc, tb):
        await self.conn.close()

# Async generator
async def stream_results(query: str) -> AsyncIterable[Dict]:
    """Stream database results row by row."""
    async with DatabaseConnection() as conn:
        async for row in conn.cursor(query):
            yield dict(row)

Avoid async for:

  • CPU-intensive operations (use multiprocessing)
  • Simple synchronous code that doesn't benefit from concurrency

Project Structure

Modern
src
Layout (Recommended for Packages)

myproject/
├── pyproject.toml          # PEP 621 configuration
├── README.md
├── LICENSE
├── .gitignore
├── .pre-commit-config.yaml
├── src/
│   └── myproject/
│       ├── __init__.py
│       ├── main.py
│       └── utils.py
├── tests/
│   ├── conftest.py
│   ├── __init__.py
│   └── test_main.py
├── docs/
│   └── index.md
└── .github/
    └── workflows/
        └── ci.yml

Why

src
layout:

  • Prevents import confusion during development
  • Ensures tests import from installed package, not source tree
  • Better packaging behavior with tools like
    setuptools_scm

pyproject.toml
(PEP 621 Standard)

Complete example:

[build-system]
requires = ["hatchling", "setuptools-scm"]
build-backend = "hatchling.build"

[project]
name = "myproject"
dynamic = ["version"]
description = "A modern Python project"
readme = "README.md"
requires-python = ">=3.9"
license = {text = "MIT"}
authors = [
    {name = "Author Name", email = "author@example.com"},
]

keywords = ["python", "example"]
classifiers = [
    "Development Status :: 4 - Beta",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: MIT License",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.9",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
]

dependencies = [
    "httpx>=0.25.0",
    "pydantic>=2.0.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0.0",
    "pytest-cov>=4.0.0",
    "pytest-asyncio>=0.21.0",
    "mypy>=1.0.0",
    "ruff>=0.1.0",
    "pre-commit>=3.0.0",
]
docs = [
    "mkdocs>=1.5.0",
    "mkdocs-material>=9.0.0",
]

[project.scripts]
myproject-cli = "myproject.main:cli"

[project.urls]
Homepage = "https://github.com/user/myproject"
Documentation = "https://myproject.readthedocs.io"
Repository = "https://github.com/user/myproject"
Issues = "https://github.com/user/myproject/issues"

[tool.setuptools_scm]
write_to = "src/myproject/_version.py"

[tool.ruff]
line-length = 88
target-version = "py39"

[tool.ruff.lint]
select = ["E", "F", "I", "N", "W"]
ignore = ["E501"]

[tool.mypy]
python_version = "3.9"
strict = true
warn_return_any = true
warn_unused_configs = true

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
    "--strict-markers",
    "--cov=src/myproject",
    "--cov-report=term-missing",
]

Dependency Management with
uv

Installation:

# Using pip (one-time)
pip install uv

# Or using the official installer
curl -LsSf https://astral.sh/uv/install.sh | sh

Commands:

# Create new project
uv init myproject

# Add dependencies
uv add httpx pydantic

# Add dev dependencies
uv add --dev pytest pytest-cov mypy ruff

# Run commands in virtual environment
uv run pytest
uv run myproject-cli

# Sync dependencies (create/update venv)
uv sync

# Update dependencies
uv lock --upgrade

Why

uv
:

  • Written in Rust (10-100x faster than pip)
  • Drop-in replacement for pip/pip-tools
  • Built-in dependency resolution (like poetry)
  • Works with existing
    requirements.txt

Framework Selection

Web Development

FrameworkUse CaseKey Features
FastAPIAPIs, microservicesAsync, auto docs, Pydantic validation, fast
DjangoFull-stack appsORM, admin, authentication, batteries included
FlaskSimple microservicesMinimal, flexible, easy to learn

Choose FastAPI when:

  • Building REST/GraphQL APIs
  • Need async I/O performance
  • Want automatic OpenAPI docs
  • Rapid development with type safety

Choose Django when:

  • Building full-stack web applications
  • Need built-in admin interface
  • Require robust authentication/permissions
  • Want ORM and database migrations out of the box

Choose Flask when:

  • Building simple microservices
  • Need maximum flexibility
  • Learning web frameworks

FastAPI best practices (

main.py
):

from fastapi import FastAPI, Depends, HTTPException, status
from pydantic import BaseModel, Field
from typing import List, Optional

app = FastAPI(
    title="My API",
    description="API documentation",
    version="1.0.0",
)

# Pydantic models for request/response
class UserCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=100)
    email: str = Field(..., regex=r"^[^@]+@[^@]+\.[^@]+$")

class User(BaseModel):
    id: int
    name: str
    email: str

# Dependency injection
async def get_db():
    """Database session dependency."""
    async with async_session() as session:
        yield session

# Routes with proper status codes
@app.post("/users", response_model=User, status_code=status.HTTP_201_CREATED)
async def create_user(
    user: UserCreate,
    db: AsyncSession = Depends(get_db),
) -> User:
    """Create a new user."""
    # Implementation
    return user

@app.get("/users/{user_id}", response_model=User)
async def get_user(
    user_id: int,
    db: AsyncSession = Depends(get_db),
) -> User:
    """Get user by ID."""
    user = await db.get(User, user_id)
    if not user:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="User not found",
        )
    return user

@app.get("/users", response_model=List[User])
async def list_users(
    skip: int = 0,
    limit: int = 100,
    db: AsyncSession = Depends(get_db),
) -> List[User]:
    """List users with pagination."""
    return await db.execute(select(User).offset(skip).limit(limit))

Database

SQLAlchemy 2.0 with async support:

from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import declarative_base, sessionmaker

# Async engine
DATABASE_URL = "postgresql+asyncpg://user:pass@localhost/db"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)

Base = declarative_base()

class User(Base):
    __tablename__ = "users"

    id = Column(Integer, primary_key=True)
    name = Column(String, nullable=False)
    email = Column(String, unique=True, nullable=False)

# Async CRUD operations
async def create_user(user_data: dict) -> User:
    async with async_session() as session:
        user = User(**user_data)
        session.add(user)
        await session.commit()
        await session.refresh(user)
        return user

async def get_user(user_id: int) -> Optional[User]:
    async with async_session() as session:
        return await session.get(User, user_id)

Alembic migrations:

# Initialize migrations
alembic init alembic

# Create migration
alembic revision --autogenerate -m "Add users table"

# Apply migrations
alembic upgrade head

Configuration Management

Pydantic Settings (

config.py
):

from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field

class Settings(BaseSettings):
    model_config = SettingsConfigDict(
        env_file=".env",
        env_file_encoding="utf-8",
        case_sensitive=False,
    )

    # Application settings
    app_name: str = "My App"
    debug: bool = False

    # Database
    database_url: str = Field(..., env="DATABASE_URL")

    # Security
    secret_key: str = Field(..., env="SECRET_KEY")
    jwt_algorithm: str = "HS256"

    # External services
    api_key: Optional[str] = None

settings = Settings()

Usage (

.env
file):

DATABASE_URL=postgresql+asyncpg://user:pass@localhost/db
SECRET_KEY=your-secret-key-here
DEBUG=false

Logging

Structured logging with structlog (

logging.py
):

import structlog
import logging

def configure_logging(debug: bool = False) -> None:
    """Configure structured logging."""
    level = logging.DEBUG if debug else logging.INFO

    # Standard library logging
    logging.basicConfig(
        format="%(message)s",
        level=level,
    )

    # Structlog configuration
    structlog.configure(
        processors=[
            structlog.contextvars.merge_contextvars,
            structlog.processors.add_log_level,
            structlog.processors.StackInfoRenderer(),
            structlog.dev.set_exc_info,
            structlog.processors.TimeStamper(fmt="iso"),
            structlog.processors.JSONRenderer() if not debug else structlog.dev.ConsoleRenderer(),
        ],
        wrapper_class=structlog.make_filtering_bound_logger(level),
        context_class=dict,
        logger_factory=structlog.PrintLoggerFactory(),
        cache_logger_on_first_use=True,
    )

# Usage
logger = structlog.get_logger(__name__)
logger.info("User created", user_id=123, email="user@example.com")

CLI Development

Typer for Modern CLIs

Example CLI (

cli.py
):

import typer
from typing import Optional

app = typer.Typer()

@app.command()
def hello(
    name: str = typer.Argument(..., help="Name to greet"),
    uppercase: bool = typer.Option(False, "--upper", "-u", help="Uppercase output"),
    count: int = typer.Option(1, "--count", "-c", help="Number of times to greet"),
) -> None:
    """Greet someone."""
    greeting = f"Hello, {name}!"
    if uppercase:
        greeting = greeting.upper()

    for _ in range(count):
        typer.echo(greeting)

if __name__ == "__main__":
    app()

Usage:

python cli.py World --upper --count 3
# Output: HELLO, WORLD!
#         HELLO, WORLD!
#         HELLO, WORLD!

Entry Points

Define in

pyproject.toml
:

[project.scripts]
myproject-cli = "myproject.cli:app"

After installation:

myproject-cli World --upper

Package Development & Distribution

Publishing to PyPI

Build with hatch/uv:

# Install build tools
uv pip install build twine

# Build package
uv run build

# Check distribution
twine check dist/*

# Upload to PyPI
twine upload dist/*

Versioning with

setuptools_scm
:

[build-system]
requires = ["hatchling", "setuptools_scm"]
build-backend = "hatchling.build"

[tool.setuptools_scm]
write_to = "src/myproject/_version.py"

Version automatically determined from:

  • Latest git tag (e.g.,
    v1.0.0
    )
  • Number of commits since tag
  • Commit hash for dev versions

CI/CD with GitHub Actions

Complete workflow (

.github/workflows/ci.yml
):

name: CI

on:
  push:
    branches: [main, develop]
  pull_request:
    branches: [main, develop]

jobs:
  test:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        python-version: ["3.9", "3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - name: Set up uv
        uses: astral-sh/setup-uv@v1
        with:
          version: "latest"

      - name: Set up Python ${{ matrix.python-version }}
        run: uv python install ${{ matrix.python-version }}

      - name: Install dependencies
        run: uv sync --dev

      - name: Run linters
        run: |
          uv run ruff check .
          uv run ruff format --check .

      - name: Run type checks
        run: uv run mypy src

      - name: Run tests
        run: uv run pytest --cov=src/myproject --cov-report=xml

      - name: Upload coverage to Codecov
        uses: codecov/codecov-action@v4

  build:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, macos-latest, windows-latest]
        python-version: ["3.9", "3.10", "3.11", "3.12"]

    steps:
      - uses: actions/checkout@v4

      - name: Build wheels
        uses: pypa/cibuildwheel@v2
        env:
          CIBW_BUILD: cp39-* cp310-* cp311-* cp312-*

      - uses: actions/upload-artifact@v4
        with:
          name: wheels
          path: wheelhouse/*.whl

Documentation

Docstring Conventions

Google style (recommended):

def calculate_discount(
    price: float,
    discount_rate: float,
    quantity: int = 1,
) -> float:
    """Calculate the discounted price for an item.

    Args:
        price: The original price of the item.
        discount_rate: The discount rate as a decimal (e.g., 0.2 for 20%).
        quantity: The number of items. Defaults to 1.

    Returns:
        The discounted total price.

    Raises:
        ValueError: If price is negative or discount_rate is not between 0 and 1.

    Examples:
        >>> calculate_discount(100.0, 0.2, 2)
        160.0
    """
    if price < 0:
        raise ValueError("Price must be non-negative")
    if not 0 <= discount_rate <= 1:
        raise ValueError("Discount rate must be between 0 and 1")

    return price * (1 - discount_rate) * quantity

MkDocs Documentation

Configuration (

mkdocs.yml
):

site_name: My Project
site_description: Modern Python project documentation
site_url: https://myproject.readthedocs.io

theme:
  name: material
  palette:
    - scheme: default
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-7
        name: Switch to dark mode
    - scheme: slate
      primary: indigo
      accent: indigo
      toggle:
        icon: material/brightness-4
        name: Switch to light mode

plugins:
  - search
  - mkdocstrings:
      handlers:
        python:
          options:
            show_source: true
            show_root_heading: true
            show_root_full_path: false

markdown_extensions:
  - pymdownx.highlight:
      anchor_linenums: true
  - pymdownx.superfences

nav:
  - Home: index.md
  - Installation: installation.md
  - Usage: usage.md
  - API Reference: api/

Anti-Patterns & Common Mistakes

Code Quality Anti-Patterns

❌ Bad: Mutable default arguments

def process_items(items: List = []):  # Mutates across calls!
    items.append("processed")
    return items

✅ Good: Use

None
as default

from typing import Optional, List

def process_items(items: Optional[List] = None) -> List:
    if items is None:
        items = []
    items.append("processed")
    return items

❌ Bad: Empty except blocks

try:
    risky_operation()
except:  # Swallows ALL errors including KeyboardInterrupt!
    pass

✅ Good: Specific exception handling

try:
    risky_operation()
except ValueError as e:
    logger.error("Invalid value", error=str(e))
    raise
except Exception as e:
    logger.exception("Unexpected error")
    raise

❌ Bad: Using

print()
for logging

def process_data(data):
    print(f"Processing: {data}")  # No timestamps, no levels, can't disable
    # ... process
    print(f"Done: {data}")

✅ Good: Proper logging

import logging

logger = logging.getLogger(__name__)

def process_data(data):
    logger.info("Processing data", data=data)
    # ... process
    logger.info("Processing complete", data=data)

❌ Bad: Suppressing type errors

def process(item: Any) -> str:  # Avoid Any!
    return item.do_something()  # mypy error: Item has no attribute

✅ Good: Fix type errors or use proper typing

from typing import Protocol

class Processable(Protocol):
    def do_something(self) -> str: ...

def process(item: Processable) -> str:
    return item.do_something()  # Type-safe!

Performance Anti-Patterns

❌ Bad: String concatenation in loops

def build_string(items: List[str]) -> str:
    result = ""
    for item in items:  # O(n²) - creates new string each iteration
        result += item
    return result

✅ Good: Use

join()

def build_string(items: List[str]) -> str:
    return "".join(items)  # O(n)

❌ Bad: Synchronous HTTP calls in async function

async def fetch_data(urls: List[str]) -> List[Dict]:
    results = []
    for url in urls:
        # Blocks the event loop!
        response = requests.get(url)
        results.append(response.json())
    return results

✅ Good: Async HTTP client

import httpx

async def fetch_data(urls: List[str]) -> List[Dict]:
    async with httpx.AsyncClient() as client:
        tasks = [client.get(url) for url in urls]
        responses = await asyncio.gather(*tasks)
        return [r.json() for r in responses]

Security Anti-Patterns

❌ Bad: Hardcoded secrets

API_KEY = "sk-1234567890abcdef"  # Never commit secrets!

def fetch_data():
    requests.get("https://api.example.com/data", params={"key": API_KEY})

✅ Good: Environment variables + Pydantic Settings

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    api_key: str  # Loaded from API_KEY env var

    class Config:
        env_file = ".env"

settings = Settings()

def fetch_data():
    requests.get(
        "https://api.example.com/data",
        params={"key": settings.api_key},
    )

❌ Bad: SQL injection with f-strings

def get_user(username: str):
    cursor.execute(f"SELECT * FROM users WHERE name = '{username}'")  # Injection!

✅ Good: Parameterized queries

def get_user(username: str):
    cursor.execute("SELECT * FROM users WHERE name = %s", (username,))

Reference Resources

Official Documentation

Modern Tooling

Best Practices

Example Projects


Quick Start Example

Project Setup

# 1. Initialize project with uv
uv init myproject
cd myproject

# 2. Add dependencies
uv add httpx pydantic pydantic-settings

# 3. Add dev dependencies
uv add --dev pytest pytest-cov pytest-asyncio mypy ruff pre-commit

# 4. Create project structure
mkdir -p src/myproject tests

# 5. Set up pre-commit hooks
uv run pre-commit install

Main Application (
src/myproject/main.py
)

from fastapi import FastAPI
from pydantic import BaseModel
import structlog

from config import settings

app = FastAPI(title="My API", version="1.0.0")
logger = structlog.get_logger(__name__)

class Item(BaseModel):
    name: str
    price: float

@app.get("/")
async def root() -> dict:
    """Root endpoint."""
    logger.info("Root endpoint called")
    return {"message": "Hello World"}

@app.post("/items", status_code=201)
async def create_item(item: Item) -> Item:
    """Create a new item."""
    logger.info("Creating item", item=item)
    return item

Configuration (
src/myproject/config.py
)

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    app_name: str = "My App"
    debug: bool = False

    class Config:
        env_file = ".env"

settings = Settings()

Test (
tests/test_main.py
)

import pytest
from fastapi.testclient import TestClient

from myproject.main import app

client = TestClient(app)

def test_root():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"message": "Hello World"}

def test_create_item():
    item = {"name": "Test Item", "price": 9.99}
    response = client.post("/items", json=item)
    assert response.status_code == 201
    assert response.json() == item

Run Project

# Run tests
uv run pytest

# Run API
uv run uvicorn myproject.main:app --reload

# Type check
uv run mypy src

# Format/lint
uv run ruff check --fix .
uv run ruff format .

Integration with Other Skills

This skill provides comprehensive Python development guidance and can be integrated with other skills in the OpenCode ecosystem:

  • gtk-ui-ux-engineer: Use Python for backend APIs that serve GTK applications
  • frontend-ui-ux-engineer: Create Python-based REST APIs for frontend consumption
  • document-writer: Generate API documentation from Python docstrings
  • rails-basecamp-engineer: Apply Python patterns for microservices alongside Rails monoliths

The skill is designed to be invoked automatically when:

  • Working with
    .py
    files
  • Managing
    pyproject.toml
    or
    requirements.txt
  • Running Python-related commands (
    pytest
    ,
    uv
    ,
    ruff
    )
  • Setting up Python development environments

When to Use This Skill

Use this skill when:

  • Creating new Python projects or modules
  • Setting up Python development environments
  • Writing Python code with type hints and async patterns
  • Choosing frameworks (FastAPI, Django, Flask)
  • Packaging and distributing Python libraries
  • Setting up testing, linting, and CI/CD
  • Implementing configuration, logging, and error handling

Do NOT use this skill for:

  • JavaScript/TypeScript development (use frontend-ui-ux-engineer)
  • GTK UI development (use gtk-ui-ux-engineer)
  • Ruby/Rails development (use rails-basecamp-engineer)
  • Generic system administration (use appropriate domain skills)

Skill Compatibility

Minimum Python Version: 3.9 Recommended Python Version: 3.11+ (for latest features and performance) Compatible Tools: uv, ruff, pytest, mypy, FastAPI, Django 5+, SQLAlchemy 2.0+