SnakeORM¶
Navegación profunda de relaciones completamente tipada en Python. Sin codegen. Sin plugin de type-checker.
Mypy, Pyright y Pylance lo saben. Y genera esto:
SELECT t0."id", t0."model", t0."maker_id" FROM "public"."trucks" AS t0
JOIN "public"."makers" AS t1 ON t0."maker_id" = t1."id"
JOIN "public"."nations" AS t2 ON t1."nation_id" = t2."id"
WHERE t2."name" = %s
En Django escribirías filter(maker__nation__name="España"): una cadena mágica que no autocompleta,
no se comprueba, y si renombras nation te enteras en producción.
La distribución es snake-orm y el paquete es snakeorm. La versión se fija porque es una beta:
un pip install snake-orm a secas no recoge una preliminar.
Empezar en cinco minutos Cómo funciona el tipado
Un vistazo completo¶
from snakeorm import (
SnakeColumn, SnakeModel, SnakeQuery, SnakeSession, SnakeToOne,
PostgresDialect, PsycopgDriver,
snake_auto, snake_int, snake_link, snake_model, snake_str, snake_to_one,
)
@snake_model(table="brands")
class Brand(SnakeModel):
id: SnakeColumn[int] = snake_auto()
name: SnakeColumn[str] = snake_str(unique=True)
@snake_model(table="cars")
class Car(SnakeModel):
id: SnakeColumn[int] = snake_auto()
model: SnakeColumn[str] = snake_str()
brand_id: SnakeColumn[int] = snake_int()
brand: SnakeToOne[Brand] = snake_to_one(brand_id)
snake_link()
session = SnakeSession(PsycopgDriver.connect(dsn), PostgresDialect())
cars = session.all(
SnakeQuery(Car).filter(Car.brand.name == "Seat").order_by(Car.model)
)
La tesis¶
Un ORM moderno puede tener navegación profunda de relaciones totalmente tipada, sin generar código y sin plugin de type-checker. El sistema de tipos es la única fuente de verdad; el runtime solo ejecuta SQL sobre metadata ya compilada. Verificado con mypy y pyright: un test exige que coincidan — cómo funciona.
Qué trae¶
-
Tipado que no miente
Relaciones profundas, agregados, proyecciones y enumerados devuelven su tipo real. Cero
Any, verificado con--strict. -
Migraciones con autogen
Diff del modelo contra el histórico, ficheros legibles y reversibles, squash y detección de deriva contra la base real.
-
Tres motores, una metadata
PostgreSQL, MySQL/MariaDB y SQLite. El modelo es 100% agnóstico: el motor solo entra al emitir y al ejecutar.
-
Síncrono y asíncrono
La generación de SQL no tiene color, así que
AsyncSessionreutiliza el núcleo entero. Paridad comprobada por la máquina.
Principios¶
- Nada falla en silencio. Cuando algo no se puede hacer, se dice; cuando se puede traducir, se traduce; cuando la herramienta no sabe decidir, para y pregunta.
- El tipo viene de Python.
SnakeColumn[str | None]es nulable porque lo dice la anotación, no unnullable=Trueque pueda contradecirla. - Cada límite está escrito. La página de límites conocidos es parte del contrato, no una lista de disculpas.