Loom Python project
Project description
loom-kernel
Framework-agnostic Python toolkit to build backend applications with:
- typed use cases (
msgspec.Struct) - repositories decoupled from infrastructure
- REST/FastAPI adapters
- testing utilities for business workflows
Purpose
loom-kernel helps you model domain logic and use cases with clean architecture.
The library separates core contracts from concrete adapters so you can swap
infrastructure (DB, cache, transport) without breaking business logic.
Main subpaths
| Subpath | What it is for |
|---|---|
src/loom/core/use_case |
UseCase definition, rules (Rule), and compute steps (Compute). |
src/loom/core/engine |
Compilation and runtime execution of a use-case plan. |
src/loom/core/repository/abc |
Repository contracts, pagination, and typed query spec. |
src/loom/core/repository/sqlalchemy |
Concrete async SQLAlchemy repository implementation. |
src/loom/core/model |
Base model, fields, relations, and entity introspection. |
src/loom/core/cache |
Decorators and cached repository with dependency invalidation. |
src/loom/rest |
Framework-agnostic REST model and route compiler. |
src/loom/rest/fastapi |
Direct FastAPI integration (auto wiring and runtime router). |
src/loom/prometheus |
Middleware and adapter for runtime metrics. |
src/loom/testing |
Harnesses for unit/integration tests and golden tests. |
Quick example
from loom.core.command import Command, Patch
from loom.core.errors import RuleViolation
from loom.core.model import BaseModel, ColumnField
from loom.core.use_case import Compute, F, Input, UseCase
from loom.rest.fastapi.auto import create_app
from loom.rest.model import RestInterface, RestRoute
class CreateProduct(Command, frozen=True):
name: str
price: float
class UpdateProduct(Command, frozen=True):
name: Patch[str] = None
price: Patch[float] = None
class Product(BaseModel):
__tablename__ = "products"
id: int = ColumnField(primary_key=True, autoincrement=True)
name: str = ColumnField(length=120)
price: float = ColumnField()
def normalize_text(value: str) -> str:
return value.strip()
def validate_create_price(cmd: CreateProduct, _: frozenset[str]) -> None:
if cmd.price <= 0:
raise RuleViolation(field="price", message="price must be greater than zero")
def validate_update_price(cmd: UpdateProduct, fields: frozenset[str]) -> None:
# For Patch fields, validate only when the field was actually sent by caller.
if "price" in fields and cmd.price is not None and cmd.price <= 0:
raise RuleViolation(field="price", message="price must be greater than zero")
normalize_create_name = Compute.set(F(CreateProduct).name).from_fields(
F(CreateProduct).name,
via=normalize_text,
).when_present(F(CreateProduct).name)
normalize_update_name = Compute.set(F(UpdateProduct).name).from_fields(
F(UpdateProduct).name,
via=normalize_text,
).when_present(F(UpdateProduct).name)
class CreateProductUseCase(UseCase[Product, Product]):
computes = (normalize_create_name,)
rules = (validate_create_price,)
async def execute(self, cmd: CreateProduct = Input()) -> Product:
return await self.main_repo.create(cmd)
class UpdateProductUseCase(UseCase[Product, Product | None]):
computes = (normalize_update_name,)
rules = (validate_update_price,)
async def execute(self, product_id: str, cmd: UpdateProduct = Input()) -> Product | None:
return await self.main_repo.update(int(product_id), cmd)
class ProductRestInterface(RestInterface[Product]):
prefix = "/products"
tags = ("Products",)
profile_default = "default"
routes = (
RestRoute(
use_case=CreateProductUseCase,
method="POST",
path="/",
status_code=201,
),
RestRoute(
use_case=UpdateProductUseCase,
method="PATCH",
path="/{product_id}",
),
)
# Auto app bootstrap from YAML config + discovery
app = create_app(config_path="config/conf.yaml", code_path="src")
With this setup, the framework can bootstrap a complete HTTP app (routes, dependency wiring, and runtime execution) from your interfaces, use cases, and discovered models.
For deeper references, review the integration examples under
tests/integration/fake_repo.
We will publish a full functional demo repository soon with end-to-end
documentation.
Status
Project under active development.
Project details
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 loom_kernel-0.0.0.tar.gz.
File metadata
- Download URL: loom_kernel-0.0.0.tar.gz
- Upload date:
- Size: 217.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
01e51a735dd09acf0c960dccb29748a798e088a28eef05c5c6cea6b18b9a973c
|
|
| MD5 |
ecdece6ce7a4a04d66d92a33e7d93e64
|
|
| BLAKE2b-256 |
da107c1e96e928ecfbabe5b1852f314023b73d4b5ddf20530a850ada166dd8b5
|
File details
Details for the file loom_kernel-0.0.0-py3-none-any.whl.
File metadata
- Download URL: loom_kernel-0.0.0-py3-none-any.whl
- Upload date:
- Size: 142.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37cd3bc42f5494329cf34a97f804a1c11df5e990650828cd053d645726fa4598
|
|
| MD5 |
dbf690b7bd825850ba169eb9ae48f216
|
|
| BLAKE2b-256 |
bbe717197be0f65e4c60ef919c2c32b1d03d270b7182e732a630ea303dceff16
|