nene2-python
A Python reference framework implementing the NENE2 design philosophy — clean architecture, security-first, and AI-readable code.
Current release: v1.8.97 · 466 tests · CI on Python 3.12 and 3.14
Features
- FastAPI + Pydantic v2 — modern Python API stack with automatic OpenAPI docs
- Clean Architecture — UseCase / Domain layer fully decoupled from HTTP and DB
mypy --strict— equivalent to PHPStan level 8 type safety- ruff — lint and format in one tool (replaces flake8, isort, black, bandit)
- RFC 9457 Problem Details — uniform error responses across all endpoints
- Bearer Token / API Key auth —
LocalTokenVerifier,CompositeAuthMiddleware, dev JWT helpers - MCP support — expose UseCases as AI agent tools via
LocalMcpServer - SQLAlchemy Core — parameterised SQL without ORM overhead
- Security middleware — CSP, rate limiting, request size limit, CORS via
setup_middlewares() - ETag / conditional requests —
generate_etag(),check_not_modified(),check_precondition() - TTL cache & webhooks —
TtlCache[V],verify_hmac_signature() - structlog — structured JSON logging with request ID correlation
- 219 field trials — stdlib and framework patterns validated in sandbox apps (INDEX)
Installation
pip install nene2-python
# or
uv add nene2-python
Requires Python 3.12+ (CI also tests 3.14).
Quick Start
Use APIRouter + create_app() at the end of the file (see CLAUDE.md). Register middlewares with setup_middlewares() so 500 responses still get X-Request-Id and security headers.
from fastapi import APIRouter, FastAPI
from nene2.config import AppSettings
from nene2.middleware import setup_middlewares
router = APIRouter()
@router.get("/health")
def health() -> dict[str, str]:
return {"status": "ok"}
def create_app() -> FastAPI:
cfg = AppSettings()
app = FastAPI(title=cfg.app_name)
setup_middlewares(
app,
debug=cfg.app_debug,
throttle_limit=cfg.throttle_limit if cfg.throttle_enabled else None,
cors_allowed_origins=cfg.cors_origins if cfg.cors_enabled else None,
)
app.include_router(router)
return app
app = create_app()
See the full reference app in src/example/ (Note / Tag / Comment CRUD, auth, MCP).
Define a domain
from dataclasses import dataclass
from abc import ABC, abstractmethod
@dataclass(frozen=True, slots=True)
class Note:
id: int
title: str
body: str
class NoteRepositoryInterface(ABC):
@abstractmethod
def find_by_id(self, note_id: int) -> Note | None: ...
@dataclass(frozen=True, slots=True)
class GetNoteInput:
note_id: int
class GetNoteUseCase:
def __init__(self, repository: NoteRepositoryInterface) -> None:
self._repository = repository
def execute(self, input_: GetNoteInput) -> Note:
note = self._repository.find_by_id(input_.note_id)
if note is None:
raise NoteNotFoundException(input_.note_id)
return note
Wire to HTTP
from fastapi import APIRouter
from fastapi.responses import JSONResponse
router = APIRouter(prefix="/notes", tags=["notes"])
@router.get("/{note_id}")
async def get_note(note_id: int) -> JSONResponse:
note = get_use_case.execute(GetNoteInput(note_id))
return JSONResponse({"id": note.id, "title": note.title, "body": note.body})
Development Commands
uv sync # install dependencies
uv run pytest # 466 tests, coverage ≥ 80%
uv run mypy src/ # type check (strict)
uv run ruff check src/ tests/ # lint
uv run ruff format src/ tests/ # format
uv run uvicorn src.example.app:app --reload --port 8080 # dev server
Full CI check (equivalent to GitHub Actions):
uv run pytest && \
uv run mypy src/ && \
uv run ruff check src/ tests/ && \
uv run ruff format --check src/ tests/ && \
uv run pip-audit --ignore-vuln PYSEC-2025-183
CI also runs a 90% coverage gate on example/*/use_case.py, entity.py, and async_use_case.py.
Framework Modules
| Module | Purpose |
|---|---|
nene2.http |
Pagination, Problem Details, health checks, ETag, query helpers, RequestScopedContext |
nene2.middleware |
Full pipeline + setup_middlewares(), rate-limit storage protocol |
nene2.auth |
Bearer / API Key / composite auth, LocalTokenIssuer, make_require_auth() |
nene2.database |
SqlAlchemyQueryExecutor, SqlAlchemyTransactionManager, DatabaseHealthCheck |
nene2.config |
AppSettings (pydantic-settings, reads from env / .env) |
nene2.validation |
ValidationException, ValidationError |
nene2.cache |
TtlCache[V] — thread-safe in-memory TTL cache |
nene2.security |
verify_hmac_signature() for webhook verification |
nene2.mcp |
LocalMcpServer, HttpxMcpClient |
nene2.log |
setup_logging() (structlog, JSON in production) |
nene2.use_case |
UseCaseProtocol[I, O], AsyncUseCaseProtocol[I, O] |
Details: Framework modules reference · How-to guides
Versioning
pyproject.tomlversion— bumped with each merged FT or feature PR (currently1.8.97).- Git tags (
v1.8.N) — created on selected releases; may lag behindpyproject.tomlduring rapid FT loops. - See docs/todo/current.md for the latest milestone table.
PHP NENE2 Correspondence
| PHP | Python |
|---|---|
readonly class |
dataclass(frozen=True, slots=True) |
PHPStan level 8 |
mypy --strict |
PHP-CS-Fixer |
ruff format |
composer check |
uv run pytest && mypy && ruff check && ruff format --check && pip-audit --ignore-vuln PYSEC-2025-183 |
ValidationException |
nene2.validation.ValidationException |
PaginationQueryParser |
nene2.http.PaginationQueryParser |
ErrorHandlerMiddleware |
nene2.middleware.ErrorHandlerMiddleware |
LocalMcpServer |
nene2.mcp.LocalMcpServer |
Related
- NENE2 (PHP) — PHP reference implementation
- Documentation (GitHub Pages) — tutorials, how-to, reference (Diátaxis)
- Field Trial INDEX — FT1–FT219 searchable index
- Roadmap — current status and planned work
Metadata
Release files for nene2-python 1.8.164
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| nene2_python-1.8.164.tar.gz | 908.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| nene2_python-1.8.164-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 961.4 kB
Release files / nene2_python-1.8.164.tar.gz
| Download URL | nene2_python-1.8.164.tar.gz |
|---|---|
| Size | 908.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
0db3053006acaf4ddcef35dfb29f42c6383da077e3e11e473caae3ac88d93770
|
|
BLAKE2b-256 checksum How to use checksums |
0ec959884d4e13003b86c346551ab9e5af6416ccc1035f096dfef952cf8764fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / nene2_python-1.8.164-py3-none-any.whl
| Download URL | nene2_python-1.8.164-py3-none-any.whl |
|---|---|
| Size | 53.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bf62a00bed09f01526a717e4e78b8627c07394258d8e428dda3acf80de00c230
|
|
BLAKE2b-256 checksum How to use checksums |
ebb64428827ecc7d0a0f4329c8c53a127dc84c2c357f8f274e1a1aace5f33a26
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.11.17 {"installer":{"name":"uv","version":"0.11.17","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|