Skip to main content

A lightweight Python library providing reusable base classes and design patterns for decoupled application architecture, built on Pydantic and inspired by FastAPI.

Project description

MoleQL Patterns

MoleQL Patterns Logo

CI CodeQL Codecov

Reusable base classes and design patterns for clean, decoupled application architecture.

moleql-patterns is a lightweight Python library built on Pydantic and inspired by FastAPI. It provides small, composable abstractions that standardize common application behaviors without framework lock-in.

The library focuses on explicit contracts and dependency injection. It keeps transport and storage separate from business logic. This project serves infrastructure work. It stays explicit, predictable, and easy to reason about.


Requirements

  • Python 3.12+

Installation

pip install moleql-patterns

Poetry

poetry add moleql-patterns

uv

uv add moleql-patterns

Usage

Command Pattern Contracts

The commands package defines a Command pattern API. Each class holds inputs, dependencies, and behavior. It standardizes operations and background tasks.

Command pattern purpose. It turns deferred work into explicit, testable objects. It gives a stable interface for execution. Concrete classes take dependencies in the constructor. This supports dependency injection in application code. It keeps side effects in one place. Unit tests stay small. It separates orchestration from business logic.

You can import from the top-level package:

from moleql_patterns import APIOperation, AsyncAPIOperation, Task, AsyncTask, TaskData

Or import directly from commands:

from moleql_patterns.commands import APIOperation, AsyncTask, TaskData

Synchronous API operation

from pydantic import BaseModel
from moleql_patterns import APIOperation, AccessDeniedError


class CreateUserResult(BaseModel):
    user_id: str


class CreateUser(APIOperation[CreateUserResult]):
    def __init__(self, repo, current_user) -> None:
        self._repo = repo
        self._current_user = current_user

    def verify_access(self) -> None:
        self._current_user.require_admin()

    def _execute(self) -> CreateUserResult:
        user = self._repo.create_user()
        return CreateUserResult(user_id=user.id)


result = CreateUser(repo, current_user).execute()

Async API operation

from pydantic import BaseModel
from moleql_patterns import AsyncAPIOperation


class FetchUserResult(BaseModel):
    user_id: str


class FetchUser(AsyncAPIOperation[FetchUserResult]):
    def __init__(self, repo, current_user) -> None:
        self._repo = repo
        self._current_user = current_user

    def verify_access(self) -> None:
        return None

    async def _execute_async(self) -> FetchUserResult:
        user = await self._repo.fetch_user()
        return FetchUserResult(user_id=user.id)


result = await FetchUser(repo, current_user).execute_async()

Background task with validated payload

from moleql_patterns import Task, TaskData


class SendEmailData(TaskData):
    recipient: str
    subject: str


class SendEmailTask(Task[SendEmailData]):
    task_data_cls = SendEmailData

    def __init__(self, payload, mailer) -> None:
        self._mailer = mailer
        super().__init__(payload)

    def exec(self) -> str:
        self._mailer.send(self.task_data.recipient, self.task_data.subject)
        return "sent"

Structural Entities

The structural package provides a base Entity class for repository work. It keeps entity definitions separate from persistence choices. Storage details live in a concrete EntityRepository. Each entity must declare a concrete ID type to keep repository interfaces explicit and type-safe.

from datetime import datetime, UTC
from moleql_patterns import Entity


class User(Entity[int]):
    name: str


now = datetime.now(UTC)
user = User(id=1, name="Ada", created_at=now, updated_at=now)

Structural Repositories

The EntityRepository contract defines a technology neutral interface for storage. Concrete repositories take dependencies in the constructor through injection. They implement each method in the contract. Concrete code holds persistence details. This keeps business logic separate from the persistence layer. Liskov's substitution principle allows one repository to replace another.

from moleql_patterns import Entity, EntityRepository


class User(Entity[int]):
    name: str


class UserRepository(EntityRepository[int, User, dict[str, str] | None]):
    def __init__(self, db) -> None:
        self._db = db

    def add(self, entity: User) -> None:
        ...

    def get(self, entity_id: int) -> User | None:
        ...

    def list(self, query: dict[str, str] | None = None) -> list[User]:
        ...

    def update(self, entity: User) -> None:
        ...

    def remove(self, entity: User) -> None:
        ...

Design Goals

  • Keep contracts small and explicit
  • Keep domain logic separate from transport and storage
  • Use Pydantic models for validation and boundaries
  • Use dependency injection for services and repositories
  • Support sync and async flows

Status

This project is in early development. APIs change ahead of a stable 1.0 release.


Documentation


Make Commands

This repository includes a Makefile with common developer workflows:

make help
make test
make format
make build
make hooks
make upgrade
make bump-patch
make bump-minor
make bump-major

Use make help to see the full list of commands and descriptions.


Maintainers Only

The following applies to project maintainers.

Responsibilities

  • Review and merge pull requests
  • Enforce architectural consistency
  • Maintain API stability guarantees
  • Manage releases and PyPI publishing
  • Respond to security disclosures

Expectations

  • Changes affecting public APIs must be discussed ahead of merging
  • Breaking changes require clear documentation and versioning
  • Releases must follow the documented release process

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

moleql_patterns-1.0.0.tar.gz (47.8 kB view details)

Uploaded Source

Built Distribution

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

moleql_patterns-1.0.0-py3-none-any.whl (23.6 kB view details)

Uploaded Python 3

File details

Details for the file moleql_patterns-1.0.0.tar.gz.

File metadata

  • Download URL: moleql_patterns-1.0.0.tar.gz
  • Upload date:
  • Size: 47.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for moleql_patterns-1.0.0.tar.gz
Algorithm Hash digest
SHA256 22659375d542e003af28e31bc07e76c622f94d36a6a4d4c6fceb2411d87756a0
MD5 83bee18b3a798cde5018d3aef5e298a7
BLAKE2b-256 2726394a9abddeb89e98ca1e077adaf7b4927f9f5fdce1606d1ad8c055f933ba

See more details on using hashes here.

Provenance

The following attestation bundles were made for moleql_patterns-1.0.0.tar.gz:

Publisher: release.yml on OneTesseractInMultiverse/moleql-patterns

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file moleql_patterns-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for moleql_patterns-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ad1dbed975bd18bbef6d3985ea1be0e4e05b97a71b0031adecd9b75a8d7c036e
MD5 b7a0bfa5a55461f653142f5c4de3f9ee
BLAKE2b-256 a75eb70d1292b100413d0fe29043fed6af8d81a2e34b479d03802df9d394c847

See more details on using hashes here.

Provenance

The following attestation bundles were made for moleql_patterns-1.0.0-py3-none-any.whl:

Publisher: release.yml on OneTesseractInMultiverse/moleql-patterns

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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