milpa 🌽
milpa es un microframework de Python 3.14 para construir monolitos modulares, inspirado en la ergonomía de Laravel y la disciplina de capas de Spring. Junta cuatro piezas maduras detrás de una estructura opinada y un kernel reutilizable:
FastAPI para HTTP · Celery para tareas/crons · SQLAlchemy 2.0 para datos · Typer para la consola.
Pensado para dos cosas: arrancar servicios nuevos sin re-decidir la arquitectura cada vez, y migrar apps legacy de Laravel a Python conservando conceptos familiares (artisan, scheduler, mailables, soft-deletes, timestamps, Passport).
🚀 Quickstart
milpa se instala como cualquier paquete y trae el comando milpa new, que genera un proyecto
listo para correr (estilo laravel new / django-admin startproject):
# 1) instala el paquete (de forma aislada con uv, o como dependencia con pip)
uv tool install milpa-core # o: pipx install milpa-core · pip install milpa-core
# El paquete se llama `milpa-core` en PyPI (porque `milpa` choca con otro proyecto), pero el
# comando de consola y el import SIGUEN siendo `milpa`: `milpa new …` / `import milpa`.
# 2) crea un proyecto CON el demo de notas (auth, RBAC/ABAC, correos, patrones estilo milpa)
milpa new miapp --demo
cd miapp
# 3) instálalo y arráncalo
uv sync # instala milpa + deps + faker (dev)
uv run python jornal migrate run # crea las tablas (sqlite por default, zero-config)
uv run python jornal db seed # admin@demo.test + ana/beto + notas (todos: "password")
uv run python jornal serve # 👉 http://127.0.0.1:8000
Entra como admin@demo.test / password. La API con OpenAPI está en /docs. Sin --demo
obtienes un esqueleto limpio (un módulo Hello mínimo) para empezar de cero.
jornales el "artisan" de milpa (lo genera el scaffolder en la raíz del proyecto):serve,queue work,schedule work,make controller|model|module,migrate,db seed, … Ve todo conuv run python jornal list.
✨ Características
Todo es OPT-IN y auto-descubrible (no estorba si no lo usas):
- Patrones estilo milpa —
Events/Observers(1:N, transporte adaptativo: worker si hay broker, si no síncrono),Mediator(command bus 1:1, transport-neutral HTTP+CLI) yPipeline(modelo cebolla). Patrones ya probados que un arquitecto puede sugerir, no impuestos. - Background —
@job(on-demand,.dispatch()) y@cron_task(agendado, anti-overlap), separados a propósito (job ≠ cron). - API REST (estilo DRF) — versionado (
@Controller(version="v1")), rate limiting (@rate_limit), filtering DSL (FilterQueryModel) + paginación por cursor, y negociación de contenido (una ruta sirve JSON o HTML segúnAccept). - Auth — RBAC (roles) + ABAC (
Gate/@policy), JWT (API) + sesión cookie/CSRF (browser, estilo Sanctum); valida también tokens OAuth2 de Laravel Passport. - Errores que NUNCA fallan en silencio — todo error HTTP sale en RFC 9457
(
application/problem+json); el CLI rinde errores limpios (sin traceback crudo ni fuga de valores); mensajes accionables que apuntan al fix. - Datos estilo Spring Data —
Repository[Model, Id]tipado,@transactional, serializers Pydantic v2 (computed_field), soft-delete y timestamps automáticos; engine agnóstico del motor. - HTTP — controllers class-based (
@Controller/@Get/@Post), Jinja2 + HTMX/Alpine (sin Inertia) · i18n (YAML) · mail (Mailable+ drivers smtp/log/null + plantillas firmadas). - Frontend con Vite (estilo laravel-vite) — helpers
vite()/vite_asset()(HMR en dev, chunks hasheados en prod), microfrontends por vertical (surcos/: cada equipo su app Vite — React/Vue/Svelte/vanilla — servida same-origin, cero CORS), runtime-configwindow.__ENVsin rebuild y PWA sin boilerplate (manifest en runtime + Service Worker).
🎮 El demo (milpa new --demo)
--demo materializa un módulo de referencia corrible (usuarios + notas) que ejercita TODO el
stack y sirve de plantilla viva: auth dual (JWT API + sesión cookie/CSRF), RBAC + ABAC,
routing class-based, los patrones estilo milpa (eventos→correos automáticos, mediator,
pipeline, @job, @cron_task) y UI HTMX + Alpine + Pico.css. Corre sobre SQLite sin
levantar infraestructura.
- Web (HTMX):
http://127.0.0.1:8000comoadmin@demo.test/password. Crea/borra notas (HTMX), entra a Usuarios (solo roladmin→ RBAC); editas/borras solo tus notas (ABAC). - API (JWT):
POST /api/login→{access_token}; luegoAuthorization: Bearer <token>en/api/me,/api/notes(CRUD),/v1/reports/notesvs/v2/...(versionado). OpenAPI en/docs. - Microfrontends (Vite, OPT-IN): el demo trae dos surcos —
demo-spa(React + PWA con file-router) en/spaytablero(vanilla) en/tablero. Requieren Node ≥22.13 y pnpm 11:pnpm install && pnpm -r builden la raíz del proyecto, recarga y listo (en dev:pnpm --filter demo-spa deven paralelo ajornal serve). - Correos: el
.envtraeMAIL_DRIVER=log(los correos se imprimen en la terminal dejornal serve). Para verlos en un inbox web,docker compose up -dlevanta Mailpit (http://localhost:8025) y ponesMAIL_DRIVER=smtp.
Cada feature tiene su página en el manual y se demuestra ejecutable en el módulo Demo (contrastando la forma tradicional vs estilo milpa).
📦 API pública
La superficie estable vive en la fachada raíz — un import plano con lo que el demo y la guía enseñan (87 símbolos, web incluida):
from milpa import (
Controller, Get, Post, Put, Patch, Delete, # HTTP estilo Laravel
Fallback, api_version, rate_limit, view, # rutas, versionado, vistas
authenticated, Can, Roles, Scope, # auth: RBAC/ABAC y scopes Passport
job, cron_task, daily_at, hourly, # background: jobs y crons
Mail, Mailable, MailContent, # correo
Observer, dispatch, handles, send, # eventos (1:N) y mediator (1:1)
Pipeline, Pipe, # modelo cebolla
Repository, Factory, Seeder, transactional, # datos estilo Spring Data
console_command, settings, # consola y config tipada
)
La fachada es perezosa (PEP 562): import milpa a secas no instancia Celery, ni Settings,
ni el kernel web — cada símbolo se resuelve en su primer acceso. Las rutas profundas
(from milpa.Core.Http import Controller) siguen siendo válidas, y el paquete publica
py.typed (PEP 561): mypy y tu IDE reciben los tipos completos.
📖 Documentación
La guía completa estilo Laravel se publica en https://calcifux.github.io/milpa/: instalación, configuración, ciclo de vida HTTP, módulos, consola, correo, colas, cron, jobs, i18n, autenticación, base de datos (modelos, repositorios, filtrado/paginación), los patrones estilo milpa (eventos/observers, mediator, pipeline), la API REST (versionado, rate limiting, negociación de contenido, serializadores) y los errores RFC 9457.
🗂️ Estructura de un proyecto milpa
milpa new genera un proyecto donde TÚ trabajas en app/, y milpa (el framework, instalado
como paquete) aporta el kernel milpa.Core:
miapp/
app/
Modules/
Demo/ # con --demo: módulo de referencia (users/notes + TODOS los patrones)
Models/ # modelos SQLAlchemy (auto-discovery)
Dictionaries/ # constantes de dominio
Resources/ # assets/lang/views del proyecto
migrations/ # revisiones Alembic (motor-agnóstico)
jornal # consola (artisan) del proyecto
docker-compose.yml # SOLO infra de dev: redis + mailpit
.env # configuración (DATABASE_URL, MAIL_*, secretos, …)
pyproject.toml # depende de `milpa`
El kernel que aporta el paquete (milpa.Core) es genérico y reutilizable: Http (create_app +
@Controller + RateLimit), Database (Repository, @transactional, Filtering), Auth (RBAC+ABAC,
JWT/sesión, Passport), Events/Mediator/Pipeline, Jobs/Cron, Mail, Errors (RFC 9457),
Translate (i18n), Console (kernel Typer). No tocas el kernel: el framework descubre tus
modelos, diccionarios, recursos, comandos y crons por convención.
Agregar un módulo
uv run python jornal make module Facturacion
Crea app/Modules/Facturacion/ con Http/, Services/, Repositories/, Jobs/, Crons/,
Observers/, Handlers/, Pipes/, Policies/, Mail/, Resources/, Console/Commands/. La API
y el beat lo descubren solos; el import-linter garantiza que no se enrede con otros módulos
(cada módulo es un microservicio en potencia: se puede extraer sin desenredar imports cruzados).
✅ Calidad
milpa trae los guardrails de fábrica; en el proyecto generado corres:
uv run pytest # tests rápidos, SIN base de datos
uv run ruff check . # lint (ruff format . para formato)
uv run mypy # tipos (estricto)
uv run lint-imports # fronteras entre módulos
fakeres dependencia de dev (la usan factories/seeders parajornal db seed): viene en el grupo dev del proyecto, así queuv syncla trae; unpip install milpa-core"pelón" no la incluye.
🐘 Base de datos
El engine es agnóstico del motor; se elige con DATABASE_URL. Por default sqlite (zero-config,
viene en Python). Para otro motor instala su extra:
uv add "milpa-core[postgres]" # PostgreSQL (psycopg v3)
uv add "milpa-core[mysql]" # MySQL / MariaDB (pymysql)
uv add "milpa-core[oracle]" # Oracle (oracledb)
uv add "milpa-core[mssql]" # SQL Server (pyodbc)
Migrar desde Laravel
El kernel reproduce conceptos familiares para acortar la curva: artisan→jornal,
scheduler→@cron_task, mailables, soft-deletes (deleted_at), timestamps automáticos
(created_at/updated_at), y validación de tokens OAuth2 de Passport (coloca la llave pública
RS256 del legacy y apunta PASSPORT_PUBLIC_KEY_PATH a ella).
Licencia
MIT © @Calcifux (Carlos Guillermo Reyes Ramiro)
Metadata
Release files for milpa-core 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| milpa_core-1.1.0.tar.gz | 234.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| milpa_core-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 540.1 kB
Release files / milpa_core-1.1.0.tar.gz
| Download URL | milpa_core-1.1.0.tar.gz |
|---|---|
| Size | 234.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
e3eb0bb77e588d9499b058ac7040a92da4ad1071bbddd1df4736f5e31ab83d93
|
|
BLAKE2b-256 checksum How to use checksums |
2511d3c8e99fd6bb31606589c2ff18a7fd95293942ab44aefb336b540ae804c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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 / milpa_core-1.1.0-py3-none-any.whl
| Download URL | milpa_core-1.1.0-py3-none-any.whl |
|---|---|
| Size | 305.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e50b5d291940cc2c0339147b18b82131ffeee2a8da3387c7ec50fdd63fe97c78
|
|
BLAKE2b-256 checksum How to use checksums |
cc7530e70c13a268b36618231606b663b271a467b7ac723cbe4b6238c533f090
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","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}
|