NENE2 Python — minimal API framework following NENE2's design philosophy
Project description
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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file nene2_python-1.8.164.tar.gz.
File metadata
- Download URL: nene2_python-1.8.164.tar.gz
- Upload date:
- Size: 908.1 kB
- Tags: Source
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0db3053006acaf4ddcef35dfb29f42c6383da077e3e11e473caae3ac88d93770
|
|
| MD5 |
133a2b3abb450088236fa92ee00fc27f
|
|
| BLAKE2b-256 |
0ec959884d4e13003b86c346551ab9e5af6416ccc1035f096dfef952cf8764fd
|
File details
Details for the file nene2_python-1.8.164-py3-none-any.whl.
File metadata
- Download URL: nene2_python-1.8.164-py3-none-any.whl
- Upload date:
- Size: 53.2 kB
- Tags: Python 3
- Uploaded using 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}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bf62a00bed09f01526a717e4e78b8627c07394258d8e428dda3acf80de00c230
|
|
| MD5 |
de24d8b58ed30593da9bd8ab647e6479
|
|
| BLAKE2b-256 |
ebb64428827ecc7d0a0f4329c8c53a127dc84c2c357f8f274e1a1aace5f33a26
|