Skip to main content

rbatis-py

Python async database client powered by rbdc (Rust Database Connectivity) — a high-performance async database connectivity layer.

Supports

  • SQLite
  • MySQL
  • PostgreSQL
  • MSSQL
  • Turso/libSQL
  • DuckDB

Installation

# https://pypi.org/project/rbatis-py/
pip install rbatis-py

Requires Python ≥ 3.8.

Quick Start

Raw SQL

import asyncio
from rbatis_py import RBatis

async def main():
    db = RBatis()
    await db.link("sqlite:///path/to/test.db")

    # CREATE / INSERT / UPDATE / DELETE
    await db.exec("CREATE TABLE IF NOT EXISTS user (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)")
    await db.exec("INSERT INTO user (name, age) VALUES (?, ?)", ["Alice", 30])

    # Query — returns List[Dict]
    rows = await db.exec_decode("SELECT * FROM user")
    for row in rows:
        print(row["name"], row["age"])

    # Transaction (auto commit/rollback)
    tx = await db.begin()
    async with tx.auto_commit() as g:
        await g.exec("UPDATE user SET age = ? WHERE name = ?", [31, "Alice"])

asyncio.run(main())

CRUD via Model

from rbatis_py import RBatis, Model

class User(Model):
    __table__ = "user"
    id: int | None = None
    name: str | None = None
    age: int | None = None

async def main():
    db = RBatis()
    await db.link("sqlite:///path/to/test.db")

    await User.insert(db, {"name": "Alice", "age": 30})
    await User.insert_batch(db, [
        {"name": "Bob", "age": 25},
        {"name": "Charlie", "age": 35},
    ], batch_size=1000)
    rows = await User.select_by_map(db, {"name": "Alice"})
    affected = await User.update_by_map(db, {"age": 31}, {"name": "Alice"})
    affected = await User.delete_by_map(db, {"name": "Bob"})

API

RBatis

Method Description
exec(sql, params) Execute INSERT/UPDATE/DELETE
exec_decode(sql, params) Query returns List[Dict]
insert(table, data) Insert one row
insert_batch(table, data_list, batch_size=None) Batch insert (chunked by batch_size)
select_by_map(table, condition) Select by condition
update_by_map(table, data, condition) Update by condition
delete_by_map(table, condition) Delete by condition
link(url) Connect to database
acquire() Acquire a raw connection from pool
begin() Begin transaction (explicit, returns Transaction)
begin_defer() Begin transaction with auto-commit guard
commit() Commit current active transaction
rollback() Rollback current active transaction
ping() Test connection
close() Close connection
set_pool_max_size(n) Set max connections in the pool
set_pool_max_idle(n) Set max idle connections in the pool
set_pool_connect_timeout(s) Set connection timeout (seconds)
set_pool_max_lifetime(s) Set max connection lifetime (seconds)
pool_state() Inspect pool state (returns dict)

Transaction

Method Description
exec(sql, params) Execute SQL on the transaction connection
exec_decode(sql, params) Query returns List[Dict]
commit() Commit the transaction
rollback() Rollback the transaction
auto_commit() Return an AutoCommitGuard context manager

AutoCommitGuard

Method Description
exec(sql, params) Execute SQL on the transaction connection
exec_decode(sql, params) Query returns List[Dict]
commit() Commit explicitly (guard no-ops on exit)
rollback() Rollback explicitly (guard no-ops on exit)

Created by Transaction.auto_commit() or RBatis.begin_defer(). On context exit:

  • No exception → auto-commit
  • Exception → auto-rollback

If commit() or rollback() is called explicitly inside the block, the guard does nothing on exit.

Connection

Method Description
exec(sql, params) Execute SQL on this connection
exec_decode(sql, params) Query returns List[Dict]
begin() Begin a transaction (returns Transaction)
close() Release connection back to the pool (not async)

Transaction Usage

Three transaction modes are supported:

A) Explicit (manual commit/rollback):

tx = await db.begin()
try:
    await tx.exec("INSERT INTO user (name) VALUES (?)", ["Alice"])
    await tx.commit()
except Exception:
    await tx.rollback()
    raise

B) Auto-commit via auto_commit():

tx = await db.begin()
async with tx.auto_commit() as g:
    await g.exec("INSERT INTO user (name) VALUES (?)", ["Alice"])
    # auto-commit on success, auto-rollback on exception

If you call await g.commit() or await g.rollback() explicitly inside the block, the guard will no-op on exit:

tx = await db.begin()
async with tx.auto_commit() as g:
    await g.exec("INSERT ...")
    await g.commit()   # explicit commit — guard does nothing on exit

C) One-liner via begin_defer():

async with db.begin_defer() as g:
    await g.exec("INSERT INTO user (name) VALUES (?)", ["Alice"])
    # auto-commit on success, auto-rollback on exception

Connection

Acquire a raw connection from the pool to run queries in isolation:

conn = await db.acquire()
try:
    rows = await conn.exec_decode("SELECT * FROM user WHERE age > ?", [20])

    # You can also begin a transaction on this specific connection
    tx = await conn.begin()
    async with tx.auto_commit() as g:
        await g.exec("INSERT INTO user (name) VALUES (?)", ["Alice"])
finally:
    conn.close()  # return to pool (not async)

Model

Define a table model:

class User(Model):
    __table__ = "user"
    id: int | None = None
    name: str | None = None
    age: int | None = None

Then use classmethods for CRUD. The db parameter accepts RBatis, Connection, or Transaction — all support exec() / exec_decode():

await User.insert(db, {...})
await User.select_by_map(db, {condition})
await User.update_by_map(db, {set_data}, {condition})
await User.delete_by_map(db, {condition})

For example, with a raw connection:

conn = await db.acquire()
try:
    await User.insert(conn, {"name": "Alice"})
    rows = await User.select_by_map(conn, {"name": "Alice"})
finally:
    conn.close()

Type Conversion

Python types are automatically converted to/from rbdc extended types:

Python type Database type
datetime.datetime DateTime
datetime.date Date
datetime.time Time
decimal.Decimal Decimal
uuid.UUID Uuid
dict / list Json

Note: SQLite stores all types as TEXT; the conversion to Python types works for all databases. PostgreSQL returns timestamps as integer (milliseconds) rather than datetime objects.

Connection URLs

# SQLite
await db.link("sqlite:///path/to/db.sqlite")

# MySQL
await db.link("mysql://user:pass@localhost:3306/db")

# PostgreSQL
await db.link("postgres://user:pass@localhost:5432/db")

# MSSQL
await db.link("jdbc:sqlserver://localhost:1433;User=SA;Password=xxx;Database=db")

Connection Pool

Configure the connection pool after calling link(). These methods must be called after a connection is established.

await db.link("mysql://user:pass@localhost:3306/mydb")

# Configure pool
await db.set_pool_max_size(20)          # Max 20 connections
await db.set_pool_max_idle(5)           # Keep at most 5 idle connections
await db.set_pool_connect_timeout(30)   # Timeout waiting for a connection (seconds)
await db.set_pool_max_lifetime(3600)    # Max connection lifetime (seconds)

# Inspect pool state
state = await db.pool_state()
print(state)
# e.g. {"max_open": 20, "connections": 3, "in_use": 1, "idle": 2, "waits": 0, ...}

Development

git clone https://github.com/rbatis/rbatis-py.git
cd rbatis-py
pip install maturin
maturin develop  # build and install in current venv

Running examples

uv run python examples/basic_usage.py     # exec, exec_decode, transactions
uv run python examples/tx.py              # transaction patterns
uv run python examples/crud_usage.py      # Model CRUD

Publishing to PyPI

# Install maturin if not already installed
pip install maturin

# Build wheel
maturin build

# Publish to PyPI (requires PyPI account and API token)
maturin publish

# Or use the official GitHub Action:
# https://github.com/PyO3/maturin-action

License

MIT

Metadata

Release files for rbatis-py 0.1.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for rbatis-py 0.1.6
File Size Uploaded Provenance
rbatis_py-0.1.6.tar.gz 48.4 kB Without provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for rbatis-py 0.1.6
File Interpreter ABI Platform
rbatis_py-0.1.6-cp311-abi3-win_amd64.whl CPython 3.11 abi3 Windows x86-64 Details
rbatis_py-0.1.6-cp311-abi3-manylinux_2_28_x86_64.whl CPython 3.11 abi3 Linux glibc 2.28+ x86-64 Details
rbatis_py-0.1.6-cp311-abi3-macosx_11_0_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl CPython 3.11 abi3 macOS 11.0+ ARM64, macOS 11.0+ x86-64, macOS 11.0+ universal2 (ARM64, x86-64) Details

Total release size: 94.9 MB

Release files / rbatis_py-0.1.6.tar.gz

Download URL rbatis_py-0.1.6.tar.gz
Size 48.4 kB
Tags Source
SHA-256 checksum
How to use checksums
377973992d2e9c257dd3fe5f5132428d4b54b5ec8b348e16ef11e2e87ce11b42
BLAKE2b-256 checksum
How to use checksums
df369a334866ee98243e6267d3117dc818f88f7ce90d81e9e234f74475a9ed80
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / rbatis_py-0.1.6-cp311-abi3-win_amd64.whl

Download URL rbatis_py-0.1.6-cp311-abi3-win_amd64.whl
Size 19.6 MB
Tags CPython 3.11 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
45ba91a359026050de654580081756f4379aeca56786f200d6e4e4c075e6f90e
BLAKE2b-256 checksum
How to use checksums
c550067c775d48f1909cf4421b3a4186917fd0c3463c0d2edb17f42e71f5d29c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / rbatis_py-0.1.6-cp311-abi3-manylinux_2_28_x86_64.whl

Download URL rbatis_py-0.1.6-cp311-abi3-manylinux_2_28_x86_64.whl
Size 27.3 MB
Tags CPython 3.11 Linux glibc 2.28+ x86-64 abi3
SHA-256 checksum
How to use checksums
bacdc0f76e0d3ce3d2f939ba82b6a244d2859cb7584323b9cfaa67ddd963c493
BLAKE2b-256 checksum
How to use checksums
a80c656ed3d00bef15c4d122aee51f94fa97236d13edb77d9d5b3f2b274e5fde
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Release files / rbatis_py-0.1.6-cp311-abi3-macosx_11_0_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl

Download URL rbatis_py-0.1.6-cp311-abi3-macosx_11_0_x86_64.macosx_11_0_arm64.macosx_11_0_universal2.whl
Size 48.0 MB
Tags CPython 3.11 abi3 macOS 11.0+ ARM64 macOS 11.0+ universal2 (ARM64, x86-64) macOS 11.0+ x86-64
SHA-256 checksum
How to use checksums
ad5da6bc7c008cf5c4029d22f1469af1845b7d92c17d73139901a32318d44b68
BLAKE2b-256 checksum
How to use checksums
0867ffc3caa5abcaea0eb91457336ec7ca599ded1445922b14464d594d4b31d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.16

Security for rbatis-py 0.1.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

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