This file provides guidelines for AI agents working on the apkit codebase.
apkit is a modern, fast toolkit for building ActivityPub-based applications with Python. It uses FastAPI for the server, supports async HTTP clients, and handles ActivityPub models, HTTP signatures, and Fediverse protocols.
This project uses uv as the package manager.
# Run all tests
uv run pytest
# Run tests with coverage
uv run pytest --cov=src/apkit
# Run a single test
uv run pytest tests/path/to/test_file.py::test_function_name
# Run tests for a specific module
uv run pytest tests/client/# Check all files with ruff
uv run ruff check .
# Check and auto-fix issues
uv run ruff check --fix .
# Format all files
uv run ruff format .
# Type checking with pyrefly
uv run pyrefly check .# Install pre-commit hooks
pre-commit install
# Run all hooks manually
pre-commit run --all-files- Standard library imports first (e.g.,
import json,from typing import ...) - Third-party imports second (e.g.,
import apmodel,from fastapi import ...) - Local/apkit imports last (e.g.,
from ..types import ActorKey) - Use absolute imports for external dependencies, relative imports for internal modules
- Sort imports with
collections.abcbeforetyping
Example:
import json
import re
from collections.abc import Iterable, Mapping
from typing import Any, Dict, List, Optional, TypeVar
import aiohttp
import httpx
from apmodel.types import ActivityPubModel
from ..types import ActorKey
from .models import Resource- Line length: 88 characters (Black-compatible)
- Indent: 4 spaces
- Quotes: Double quotes for strings
- Follow ruff configuration in
pyproject.toml
- Always use type hints for function parameters and return types
- Use
from typing import ...imports at the top - Use
ParamSpecandTypeVarfor generic types - For Python 3.10+, use
X | Ysyntax instead ofOptionalorUnionwhere appropriate
Example:
from typing import Optional, TypeVar
T = TypeVar("T")
def fetch(url: str, headers: Optional[dict] = None) -> dict | None:
...- Classes:
PascalCase(e.g.,ActivityPubClient,WebfingerResult) - Functions/Methods:
snake_case(e.g.,fetch_actor,build_webfinger_url) - Constants:
SCREAMING_SNAKE_CASE - Private methods/vars: Prefix with underscore (e.g.,
__fetch_actor,_client) - Type variables: Single uppercase letter (e.g.,
T,P,R)
- Use
@dataclass(frozen=True)for immutable models - Use regular
@dataclassfor mutable response wrappers - Document classes and methods with docstrings
Example:
@dataclass(frozen=True)
class Link:
"""Represents a link in a WebFinger response."""
rel: str
type: str | None
href: str | None- Use specific exceptions (e.g.,
ValueError,TypeError) - Raise with descriptive messages
- Use custom exceptions in
exceptions.pyfor domain-specific errors - Use
matchstatements for pattern matching (Python 3.11+)
Example:
match headers:
case Mapping() as m:
items = m.items()
case None:
items = []
case _:
raise TypeError(f"Unsupported header type: {type(headers)}")- Use pytest for testing
- Write descriptive test names (e.g.,
test_build_webfinger_url) - Use pytest classes for grouping related tests (e.g.,
class TestResource:) - Mock external dependencies when appropriate
src/apkit/
├── __init__.py # Package exports
├── _version.py # Version info (auto-generated)
├── abc/ # Abstract base classes
├── cache.py # Caching utilities
├── client/ # HTTP client implementation
│ ├── __init__.py
│ ├── base/ # Base context managers
│ ├── client.py # Main ActivityPubClient
│ ├── exceptions.py # Client exceptions
│ ├── models.py # Data models
│ └── types.py # Type definitions
├── config.py # Configuration
├── helper/ # Helper utilities
├── kv/ # Key-value store implementations
├── models/ # ActivityPub model exports
├── nodeinfo/ # NodeInfo implementation
├── server/ # FastAPI server components
│ ├── app.py # ActivityPubServer
│ ├── routes/ # Route handlers
│ ├── responses.py # Response classes
│ └── types.py # Server types
└── types.py # Common types
- Python 3.11+ is required
- Type hints are mandatory for all new code
- Follow the KISS principle - Keep It Simple, Stupid
- Conventional Commits for commit messages (e.g.,
feat:,fix:,docs:) - The codebase is not stable - API changes may break backward compatibility
Key external dependencies:
apmodel>=0.5.1- ActivityPub modelsapsig>=0.6.0- HTTP signaturesfastapi>=0.116.1- Web framework (optional, server extra)aiohttp>=3.13.3- Async HTTP clienthttpx>=0.28.1- Sync HTTP client
- Run
uv run ruff check --fix .to auto-fix linting issues - Run
uv run ruff format .to format code - Run
uv run pyrefly check .to verify type hints - Run
uv run pytestto ensure all tests pass - Ensure imports are organized correctly