- Add AI code generation requirements to AGENTS.md - Add module-level docstrings to all 46 Python modules - Add detailed Google-style docstrings to all classes and functions - Remove all inline comments following self-documenting code principle - Include Args, Returns, Raises sections in function docstrings - Add Attributes and Examples sections to class docstrings
7.3 KiB
7.3 KiB
Blog AGENTS.md
Stack
- Python 3.13+, FastAPI, pydantic, uvicorn
- SQLAlchemy 2.0 (async), aiosqlite
- Package manager:
uv - CI: Woodpecker (lint, test, type on push/PR to
dev)
Commands
uv sync --group dev # Install all dev dependencies
uv run pytest # Run tests (coverage >= 70% required)
uv run pytest tests/unit/ # Run single test directory
uv run ruff check . --fix # Lint
uv run ruff format # Format
uv run isort . # Sort imports
uv run mypy . # Type check (strict mode)
uv run blog # Start dev server (port 8000)
Pre-commit order
ruff check --fix → ruff format → isort → mypy
DDD Architecture
Layer Structure
app/
├── domain/ # Domain Layer - business logic, no dependencies
│ ├── entities/ # Domain entities (Post, User, etc.)
│ │ ├── base.py # Base entity class
│ │ └── post.py # Post entity with business logic
│ ├── value_objects/ # Value objects (Title, Content, Slug)
│ │ ├── base.py
│ │ ├── title.py
│ │ ├── content.py
│ │ └── slug.py
│ ├── repositories/ # Repository interfaces (abstract)
│ │ ├── base.py
│ │ └── post.py
│ └── exceptions.py # Domain exceptions
│
├── application/ # Application Layer - use cases
│ ├── dtos/ # Data Transfer Objects
│ │ └── post.py
│ ├── interfaces/ # Abstract interfaces (UoW)
│ │ └── unit_of_work.py
│ └── use_cases/ # Use cases (CQRS-like)
│ ├── create_post.py
│ ├── get_post.py
│ ├── update_post.py
│ ├── delete_post.py
│ ├── list_posts.py
│ └── publish_post.py
│
├── infrastructure/ # Infrastructure Layer - external concerns
│ ├── config/ # Configuration
│ │ └── settings.py
│ ├── database/ # Database connection & ORM models
│ │ ├── connection.py
│ │ └── models.py
│ ├── repositories/ # Repository implementations
│ │ ├── post.py # SQLAlchemyPostRepository
│ │ └── unit_of_work.py # SQLAlchemyUnitOfWork
│ ├── di/ # Dependency Injection
│ │ └── container.py
│ └── middleware/ # Exception handlers
│ └── error_handler.py
│
├── presentation/ # Presentation Layer - API
│ ├── api/ # FastAPI routes
│ │ ├── v1/ # API version 1
│ │ │ ├── __init__.py
│ │ │ └── posts.py # Posts endpoints
│ │ ├── deps.py # FastAPI dependencies
│ │ └── __init__.py
│ └── schemas/ # Pydantic schemas
│ └── post.py
│
└── main.py # Application entry point
tests/
├── unit/ # Unit tests (domain, use cases)
│ ├── domain/ # Domain layer tests
│ ├── application/ # Application layer tests
│ └── infrastructure/ # Infrastructure tests
├── integration/ # Integration tests (DB, repos)
├── api/ # API endpoint tests
└── e2e/ # End-to-end tests
Key Conventions
Dependency Rule
- Domain layer has NO dependencies on other layers
- Application layer depends only on Domain
- Infrastructure depends on Domain and Application
- Presentation depends on all other layers
Testing
- Unit tests: Test domain logic without DB/external services
- Integration tests: Test repository implementations with real DB
- API tests: Test endpoints with mocked use cases
- E2E tests: Full workflow testing
Code Patterns
- Use dataclasses for entities and value objects
- Use frozen dataclasses for value objects (immutable)
- Use Unit of Work pattern for transactions
- Use Repository pattern for data access
- Use Dependency Injection via FastAPI's Depends()
AI Code Generation Requirements
Documentation Standards
- Write self-documenting code - use clear, descriptive variable names and function names
- NO inline comments - code should be readable without explanatory comments
- Google-style docstrings are REQUIRED for all modules, classes, and functions
Docstring Requirements
Modules
Every module must have a module-level docstring:
"""Module for managing blog posts.
This module provides use cases for creating, updating, and deleting
blog posts in the application layer.
"""
Classes
Every class must have a detailed docstring:
class CreatePostUseCase:
"""Use case for creating a new blog post.
This class encapsulates the business logic for creating posts,
including validation and slug generation.
Attributes:
uow: Unit of Work for database transactions.
slug_service: Service for generating URL-friendly slugs.
Example:
>>> use_case = CreatePostUseCase(uow, slug_service)
>>> result = await use_case.execute(dto)
"""
Functions/Methods
Every function must have a detailed docstring with Args, Returns, Raises:
async def execute(self, dto: CreatePostDTO) -> PostDTO:
"""Execute the use case to create a new post.
Args:
dto: Data transfer object containing post creation data
including title, content, and author information.
Returns:
PostDTO: The created post data transfer object with
generated ID and slug.
Raises:
TitleValidationError: If the title is empty or too long.
ContentValidationError: If the content is empty.
DuplicateSlugError: If a post with the same slug exists.
Note:
This method is idempotent - calling it multiple times with
the same data will create separate posts with unique slugs.
"""
Google-Style Docstring Format
Use the following sections as appropriate:
Args- Parameter descriptions with typesReturns- Return value description with typeRaises- Exceptions that may be raisedYields- For generator functionsExample- Usage examplesNote- Additional important informationWarning- Critical warningsAttributes- For class attributesSee Also- References to related code
DDD Concepts Used
Entities
- Have identity (UUID)
- Mutable state
- Business logic methods (publish, update_title, etc.)
- Example:
Postentity
Value Objects
- Immutable
- Defined by attributes
- Validated on creation
- Examples:
Title,Content,Slug
Aggregates & Repositories
Postis an aggregate rootPostRepositoryinterface in DomainSQLAlchemyPostRepositoryimplementation in Infrastructure
Domain Events
- Placeholder for future implementation
- Can be added via event bus in application layer
Configuration
.envfile loaded by pydantic-settings- Settings available via
app.infrastructure.config.settings
Database
- SQLAlchemy 2.0 with async support
- SQLite by default (aiosqlite)
- Tables auto-created on startup
- Use
init_db()andclose_db()in lifespan