Skip to main content

A future-proof, greenlet-free adapter for SQLAlchemy 2.0 and databases.

Project description

SQLAlchemy-Lite 🚀

SQLAlchemy-Lite 是一个专为受限环境(如老旧 ARM 设备、嵌入式系统)设计的轻量级异步数据库适配层。

核心定位:A future-proof, greenlet-free adapter for SQLAlchemy 2.0 and databases.

它通过缝合 SQLAlchemy 2.0 的表达式能力databases 的异步驱动桥接 以及 Pydantic 的数据校验,在彻底摆脱 greenlet 依赖的同时,提供了一套现代化的开发体验。


🌟 核心特性

  • 去 Greenlet 化: 彻底避开原生 AsyncSessiongreenlet 的硬依赖,解决在特定硬件上无法编译或运行的问题。
  • Schema 驱动查询: 配合 select_for 工具,自动根据 Pydantic 模型生成精简的 SQL 投影,仅查询所需字段,极大压榨老旧设备的 IO 性能。
  • 2.0 风格语法: 100% 兼容 SQLAlchemy 2.0 的 select, insert, update, delete 表达式构造。
  • 多数据库适配: 原生支持 SQLite, MySQL, 及 PostgreSQL,支持连接池管理。
  • 类型安全: 内置 py.typed,对 Mypy 和 IDE 自动补全友好。
  • 原生分页支持:内置 fetch_page 异步工具,支持物理分页与总数自动统计,并提供包含 total_pageshas_next 等智能属性的返回容器。

📦 安装

使用 uv 或 pip 进行安装:

# 基础安装 (含核心逻辑)
uv add sqlalchemy-lite

# 根据需求安装数据库驱动扩展
uv add "sqlalchemy-lite[sqlite]"   # 默认 SQLite
uv add "sqlalchemy-lite[mysql]"    # MySQL 支持
uv add "sqlalchemy-lite[postgres]" # PostgreSQL 支持

🛠️ 快速上手

1. 定义数据结构

from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
from pydantic import BaseModel

class Base(DeclarativeBase): pass

# 数据库模型
class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    username: Mapped[str] = mapped_column()
    email: Mapped[str] = mapped_column()
    bio: Mapped[str] = mapped_column() # 大字段,非必要不查询

# 业务视图模型
class UserSimple(BaseModel):
    username: str
    email: str

2. 核心查询示例

from sqlalchemy_lite import Engine, select_for

async def main():
    db = Engine("sqlite+aiosqlite:///app.db")
    db.init_db(Base.metadata)

    await db.connect()

    async with db.session() as sess:
        # 自动生成精简 SQL: SELECT username, email FROM users
        stmt = select_for(User, UserSimple)
        result = await sess.execute(stmt)
        
        # 映射为 Pydantic 对象列表
        users = [UserSimple.model_validate(m) for m in result.mappings()]
    
    await db.disconnect()

📖 标准业务服务模板 (Best Practice)

为了确保代码的健壮性与可移植性,推荐采用以下模式:

from sqlalchemy_lite import auto_query, PageResult, select_for, fetch_page

class UserService:
    def __init__(self, db: Engine):
        self.db = db

    @auto_query(User, UserSimple, single=True)
    async def get_by_name(self, stmt, name: str):
        """使用装饰器:自动处理 session 开启、SQL 投影与模型验证"""
        return stmt.where(User.username == name)

    async def list_paged(self, page: int, size: int) -> PageResult[UserSimple]:
        """标准分页:计算总数 + 物理分页 + 结果包装"""
        async with self.db.session() as sess:
            base_stmt = select_for(User, UserSimple)
            return await fetch_page(sess, base_stmt, UserSimple, page, size)

🛡️ 模板关键原则 (The Principles)

维度 推荐做法 (未来证明) 禁忌做法
查询列 使用 select_for 或明确指定列 严禁 select(User) (全实体查询)
单条转换 Schema.model_validate(dict(row)) 严禁依赖 ORM 的延迟加载属性
结果访问 使用 result.mappings()result.scalar() 严禁依赖 result.scalars().all() 获取整个对象
事务 始终使用 async with session.begin(): 手动显式调用 commit()

🔗 高级配置与连接池

对于 MySQLPostgreSQL,建议配置连接池以提升性能:

db = Engine(
    url="mysql+aiomysql://root:pass@localhost/db",
    min_size=5,
    max_size=20,
    pool_recycle=3600
)

💎 未来证明 (Future-Proofing)

SQLAlchemy-Lite 的设计理念是“不产生负担”。当你不再受限于硬件环境,想要迁移回官方的 SQLAlchemy AsyncSession 时:

  1. 零逻辑修改: 由于 select_for 生成的是标准 SQLAlchemy 语句,你的业务函数体无需任何修改。
  2. 零迁移成本: 我们的 SessionResult 接口高度模拟了官方 API。你只需将 Engine 替换为 create_async_engine,并调整 Session 获取方式即可。

⚖️ 开源协议

本项目采用 MIT 协议。

Acknowledgment

This project was developed with the assistance of AI (Gemini). While the core architecture and logic were human-steered and rigorously reviewed to ensure security and compliance with SQLAlchemy 2.0 standards, this collaboration allowed for a more rapid exploration of lite-weight patterns for restricted environments.

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

sqlalchemy_lite-0.1.0.tar.gz (6.9 kB view details)

Uploaded Source

Built Distribution

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

sqlalchemy_lite-0.1.0-py3-none-any.whl (9.3 kB view details)

Uploaded Python 3

File details

Details for the file sqlalchemy_lite-0.1.0.tar.gz.

File metadata

  • Download URL: sqlalchemy_lite-0.1.0.tar.gz
  • Upload date:
  • Size: 6.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for sqlalchemy_lite-0.1.0.tar.gz
Algorithm Hash digest
SHA256 74e1e2ef9c1a8601567e076714f21f4f78a174563c664c0b53d95860bf45013d
MD5 4f59aeb6c97d7030ccc979dac3028dd4
BLAKE2b-256 cf30372d0517b0fbf081653528f5137f268b8a99c71b9c4593abc55b119340cb

See more details on using hashes here.

File details

Details for the file sqlalchemy_lite-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: sqlalchemy_lite-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 9.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.9.29 {"installer":{"name":"uv","version":"0.9.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Arch Linux","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for sqlalchemy_lite-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c626368b5c27c5254053182923abced3b75a153e82505c30378391ddb6a50d10
MD5 10dc9d8eaf48e52c499d85f7c9499329
BLAKE2b-256 9695f2e0812540e01637193b4c9e542e4e8621503d95ef3b7e0ba98097141f23

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