Python Engineering Standards

SkillDocs & knowledge

Master modern Python development with production-grade tooling and idioms. Use when writing Python code, configuring project structure, managing dependencies with uv, linting with ruff, adding type hints, writing pytest tests, or building FastAPI/Django/Flask applications. Triggers on "Python", "FastAPI", "Django", "Flask", "pytest", "uv", "ruff", "pyproject.toml". Do NOT trigger for generic 'build a server' requests unless the platform/language is explicitly specified as Python (e.g. FastAPI, Django, Flask).

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the Python Engineering Standards skill

What this skill tells your AI

The instructions your AI receives, as published by neverinfamous/memory-journal-mcp in skills/python/SKILL.md and read by ahel’s review.

This skill codifies 2026 Python best practices — modern tooling (uv, ruff), strict typing, and idiomatic patterns that produce maintainable, performant code.

1. Project Setup & Structure

Tooling: uv (Not pip/pipenv/poetry)

uv is the standard package manager for Python in 2026. It replaces pip, pipenv, and poetry with a single, fast Rust binary.

uv init <project-name>       # Initialize a new project
uv add <package>              # Add a dependency
uv add --dev <package>        # Add a dev dependency
uv run <command>              # Run a command in the project's venv
uv sync                      # Install all deps from uv.lock
uv python install 3.13        # Install a specific Python version
  • ALWAYS commit both pyproject.toml AND uv.lock to version control.
  • NEVER use requirements.txt for new projects — it is a legacy pattern.
  • NEVER use pip install directly — use uv add to keep the lock file in sync.

Directory Layout: src/ Layout

my-project/
├── .python-version          # Pin Python version (e.g., 3.13)
├── pyproject.toml           # Single source of truth for config
├── uv.lock                  # Deterministic lock file
├── src/
│   └── my_package/
│       ├── __init__.py
│       ├── main.py
│       └── models.py
└── tests/
    ├── __init__.py
    ├── conftest.py          # Shared fixtures
    └── test_main.py
  • Use src/ layout for packages and production apps — it prevents tests from accidentally importing the local source instead of the installed package.
  • Group by domain, not file type — prefer users/, billing/, auth/ over models/, utils/, services/.
  • Use kebab-case for directory names, snake_case for Python modules.

pyproject.toml Configuration (PEP 621)

See references/config-templates.md for the standard pyproject.toml template.

2. Type Hints (Mandatory)

Type hints are not optional — they are foundational design tools.

Rules

  • Use built-in generics (Python 3.9+): list[str], dict[str, int], tuple[int, ...]
  • Use union syntax (Python 3.10+): str | None instead of Optional[str]
  • Avoid Any — use object, Unknown, or narrow with type guards
  • Use TypedDict for dict-shaped data with known keys
  • Use Protocol for structural subtyping instead of ABCs
  • Run static analysis: mypy --strict or pyright

Examples

# ✅ Good
def get_user(user_id: int) -> User | None:
    ...

class Config(TypedDict):
    host: str
    port: int
    debug: bool

# ❌ Bad
def get_user(user_id):  # Missing type hints
    ...

def process(data: Any):  # Untyped escape hatch
    ...

3. Code Quality: ruff

Ruff is the all-in-one linter and formatter for Python. It replaces Flake8, Black, isort, pyupgrade, and more.

ruff check --fix .    # Lint with auto-fix
ruff format .         # Format (replaces Black)

Configuration in pyproject.toml

See references/config-templates.md for the standard Ruff configuration.

  • NEVER use # noqa to suppress linter errors unless the suppression is explicitly justified by a comment explaining why.
  • NEVER use # type: ignore — fix the type error or use a proper type guard.

4. Error Handling

Patterns

  • Use specific exception types — never catch bare except: or except Exception:
  • Create custom exceptions inheriting from a base project exception
  • Use from for exception chaining: raise ValueError("msg") from original_error
  • Never swallow exceptions silently — at minimum, log them
# ✅ Good
class AppError(Exception):
    """Base exception for the application."""

class NotFoundError(AppError):
    """Raised when a resource is not found."""

try:
    user = get_user(user_id)
except DatabaseError as e:
    raise NotFoundError(f"User {user_id} not found") from e

# ❌ Bad
try:
    user = get_user(user_id)
except:           # Bare except — catches SystemExit, KeyboardInterrupt
    pass          # Silently swallowed

5. Testing with pytest

Structure

  • AAA pattern: Arrange, Act, Assert — one concern per test
  • Use fixtures for setup/teardown, not classes with setUp()/tearDown()
  • Use conftest.py for shared fixtures across test modules
  • Use @pytest.mark.parametrize for data-driven tests
@pytest.fixture
def client(tmp_path: Path) -> TestClient:
    """Create a test client with a temporary database."""
    app = create_app(db_path=tmp_path / "test.db")
    return TestClient(app)

@pytest.mark.parametrize("status_code,expected", [
    (200, True),
    (404, False),
    (500, False),
])
def test_is_success(status_code: int, expected: bool) -> None:
    assert is_success(status_code) == expected

Running Tests

uv run pytest                           # Run all tests
uv run pytest tests/test_main.py        # Run specific file
uv run pytest -k "test_user"            # Run by pattern
uv run pytest --cov=src --cov-report=term-missing  # Coverage

6. Advanced Patterns & Security

For advanced guidance on asyncio concurrency, Pydantic v2 data validation, and Python security best practices, see the reference file:

Read: references/advanced-patterns.md

9. Anti-Patterns (Never Do These)

Anti-PatternWhy It's WrongDo This Instead
import *Pollutes namespace, breaks toolingExplicit imports
Mutable default args (def f(x=[]))Shared across callsUse None + assign
Global mutable stateThread-unsafe, untestableDependency injection
os.path for path manipulationPlatform-inconsistentUse pathlib.Path
print() for loggingNo levels, no rotationUse logging or structlog
== None / == TrueWrong semanticsis None / is True

10. Web Frameworks Quick Reference

FrameworkBest ForKey Pattern
FastAPIREST APIs, async, auto-docsPydantic models, dependency injection, async def routes
DjangoFull-stack, admin, ORMModels → Views → Templates, manage.py, migrations
FlaskLightweight APIs, prototypesBlueprints, application factory pattern

Signals

GitHub stars
20
Forks
5
Last commit
Jul 2026
Advanced
Catalog kind
skill
Gateway key
python-neverinfamous
Source
github.com/neverinfamous/memory-journal-mcp