Skip to main content

Loom Python project

Project description

loom-kernel

CI Coverage PyPI Python

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

loom_kernel-0.0.0.tar.gz (217.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

loom_kernel-0.0.0-py3-none-any.whl (142.5 kB view details)

Uploaded Python 3

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

Hashes for loom_kernel-0.0.0.tar.gz
Algorithm Hash digest
SHA256 01e51a735dd09acf0c960dccb29748a798e088a28eef05c5c6cea6b18b9a973c
MD5 ecdece6ce7a4a04d66d92a33e7d93e64
BLAKE2b-256 da107c1e96e928ecfbabe5b1852f314023b73d4b5ddf20530a850ada166dd8b5

See more details on using hashes here.

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

Hashes for loom_kernel-0.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 37cd3bc42f5494329cf34a97f804a1c11df5e990650828cd053d645726fa4598
MD5 dbf690b7bd825850ba169eb9ae48f216
BLAKE2b-256 bbe717197be0f65e4c60ef919c2c32b1d03d270b7182e732a630ea303dceff16

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page