Skip to main content

lexigram-sql

SQL database abstractions for Lexigram Framework — Postgres, MySQL, SQLite with migrations, repositories, and query building.


Overview

lexigram-sql provides an async SQLAlchemy ORM layer with the repository pattern, unit-of-work, connection pooling, multi-database support, Alembic migrations, and optional HMAC audit checksums. All database operations are wired through DatabaseProviderProtocol in the DI container.


Full documentation: docs.lexigram.dev

Install

uv add lexigram lexigram-sql

# With async PostgreSQL driver
uv add "lexigram-sql[postgres]"

# With async MySQL driver
uv add "lexigram-sql[mysql]"

# With SQLite async driver
uv add "lexigram-sql[sqlite]"

Quick Start

from lexigram import Application, StandardModule
from lexigram.di.module import Module, module
from lexigram.sql import DatabaseModule
from lexigram.sql.config import DatabaseConfig


@module(
    imports=[
        DatabaseModule.configure(
            DatabaseConfig(url="postgresql+asyncpg://user:pass@localhost/mydb")
        )
    ]
)
class AppModule(Module):
    pass


async def main() -> None:
    async with Application.boot(modules=[AppModule]) as app:
        from lexigram.contracts.data.sql.database import DatabaseProviderProtocol
        db = await app.container.resolve(DatabaseProviderProtocol)
        result = await db.execute_query("SELECT 1")


if __name__ == "__main__":
    import asyncio
    asyncio.run(main())

Configuration

Zero-config usage: Call DatabaseModule.configure() with no arguments to use all defaults (SQLite).

Option 1 — YAML file

# application.yaml
sql:
  backend:
    url: "${LEX_SQL__BACKEND__URL}"
  pool:
    min_size: 2
    max_size: 10
    timeout: 30
  operations:
    echo: false

Option 2 — Profiles + Environment Variables (recommended)

export LEX_SQL__BACKEND__URL=postgresql+asyncpg://user:pass@host/db
export LEX_SQL__POOL__MAX_SIZE=20
export LEX_SQL__POOL__TIMEOUT=60

Option 3 — Python

from lexigram.sql import DatabaseModule
from lexigram.sql.config import DatabaseConfig

DatabaseModule.configure(
    DatabaseConfig(
        url="postgresql+asyncpg://user:pass@localhost/mydb",
    )
)

Config reference

Field Default Env var Description
backend.url "sqlite:///piccolina.db" LEX_SQL__BACKEND__URL Database connection URL
pool.min_size 1 LEX_SQL__POOL__MIN_SIZE Minimum pool connections
pool.max_size 10 LEX_SQL__POOL__MAX_SIZE Maximum pool connections
pool.timeout 30 LEX_SQL__POOL__TIMEOUT Pool acquire timeout (seconds)
operations.echo False LEX_SQL__OPERATIONS__ECHO Echo SQL statements
audit_hmac_key None LEX_SQL__AUDIT_HMAC_KEY HMAC key for audit checksums

Module Factory Methods

Method Description
DatabaseModule.configure(config, enable_migrations, migration_dir) Configure with explicit DatabaseConfig
DatabaseModule.scope(*repositories) Scope repository classes into a feature module
DatabaseModule.stub(config=None) In-memory SQLite for testing

Key Features

  • Repository patternSQLRepository base class with find, create, update, delete, count
  • Unit of workAbstractUnitOfWork tracks changes and publishes domain events on commit
  • Multi-databaseNamedDatabaseConfig for multiple backends resolved via Annotated[DatabaseProviderProtocol, Named("analytics")]
  • Connection pooling — SQLAlchemy async pool with configurable min/max size
  • Alembic migrations — auto-run on boot in development; disabled by default in production
  • HMAC audit checksums — optional signing of write operations for integrity verification
  • Production security — blocks default passwords (:password@, :postgres@, etc.) when LEX_ENV=production

Testing

from lexigram import Application
from lexigram.sql import DatabaseModule
from lexigram.sql.config import DatabaseConfig

async def test_repository():
    async with Application.boot(
        modules=[
            DatabaseModule.stub(
                DatabaseConfig(url="sqlite+aiosqlite:///:memory:")
            )
        ]
    ) as app:
        db = await app.container.resolve(DatabaseProviderProtocol)
        # run your test queries

Key Source Files

File What it contains
src/lexigram/sql/module.py DatabaseModule.configure(), .scope(), .stub()
src/lexigram/sql/config.py DatabaseConfig, DatabasePoolConfig, NamedDatabaseConfig
src/lexigram/sql/di/provider.py DatabaseProvider boot and registration
src/lexigram/sql/repositories/base.py SQLRepository base class
src/lexigram/sql/unit_of_work/base.py AbstractUnitOfWork

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distribution

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

lexigram_sql-0.1.3006-py3-none-any.whl (295.7 kB view details)

Uploaded Python 3

File details

Details for the file lexigram_sql-0.1.3006-py3-none-any.whl.

File metadata

File hashes

Hashes for lexigram_sql-0.1.3006-py3-none-any.whl
Algorithm Hash digest
SHA256 7c09e56e74acc789b07c3736c04518d8c3e2c75d3d7cc001200a9f5c86635ce1
MD5 f688db09edf0bc368b0084be9655c704
BLAKE2b-256 7507a4b511972b66b2783c836be1a7c7443f2633a5b7bab160fb05840fbfbe00

See more details on using hashes here.

Release history Release notifications | RSS feed

0.1.5010

1 file

0.1.5007

2 files

0.1.5004

2 files

0.1.5001

2 files

0.1.3007

1 file

This release

0.1.3006 This release

1 file

0.1.3005

1 file

0.1.4

2 files

0.1.2

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page