---
overlay: Python Specialization
parent_agent: Super Coder
description: "Python best practices, type hints, and packaging"
---

## PYTHON-SPECIFIC GUIDELINES

You are working in a **Python** codebase. Apply these principles with zero exceptions.

### Code Style — PEP 8 Strictly
- Follow **PEP 8** without exception — use the project's formatter config if present (black, ruff, autopep8)
- **Type hints on ALL function signatures** (PEP 484) — parameters AND return types
- Use `from __future__ import annotations` at the top of every file for modern type hint syntax
- **Google-style docstrings** on all public functions — include Args, Returns, Raises sections
- Max line length: follow project config, default to 88 (black) or 79 (PEP 8)

### Type Safety
- Use `TypedDict` for structured dictionaries instead of `Dict[str, Any]`
- Use `Protocol` for structural typing (duck typing with type safety)
- Use `Optional[X]` explicitly — never rely on implicit `None` default
- Use `Literal` types for fixed string/int values
- Use `@overload` decorator for functions with multiple signatures
- Prefer `dataclasses` or **Pydantic** for data structures over raw dicts or tuples
- Use `Final` for constants: `MAX_RETRIES: Final = 3`

### Error Handling
- **Custom exception classes** for domain-specific errors — inherit from a base app exception
- Use `contextlib.contextmanager` or `contextlib.asynccontextmanager` for resource management
- **Never bare `except:`** — always specify the exception type
- Use `except Exception as e:` at minimum, prefer specific exceptions
- Chain exceptions with `raise NewError(...) from original_error`
- Use `logging` module, never `print()` for error reporting

### Imports & Structure
- Import grouping: **stdlib → third-party → local** (separated by blank lines)
- Use **absolute imports** — never relative imports unless in a package's `__init__.py`
- Use `__all__` to define the public API of modules
- Never use `from module import *` — always import specific names

### Patterns
- Prefer **pathlib.Path** over `os.path` for file operations
- Use **f-strings** over `.format()` or `%` formatting
- Use **generators** and `yield` for large sequences — avoid loading everything into memory
- Use `enumerate()` instead of manual index tracking
- Use `collections.defaultdict`, `collections.Counter` when appropriate
- Use `functools.lru_cache` or `functools.cache` for expensive pure function calls
- Prefer list/dict/set **comprehensions** over `map()`/`filter()` for readability

### Async Code (if applicable)
- Use `async/await` consistently — never mix sync and async in the same function
- Use `asyncio.gather()` for concurrent operations
- Use `aiofiles` for async file I/O if the project uses it
- Always handle `asyncio.CancelledError` properly

### Testing Considerations
- Write code that is **easily testable** — pure functions, dependency injection
- Use `pytest` fixtures and parametrize for clean test setup
- Prefer deterministic code — accept `datetime` params instead of calling `datetime.now()` directly
