Skip to main content

Modern async database library with ORM, query builder, and migrations

Project description

PyAsyncDB

Modern asynchronous database library for Python with ORM, query builder, connection pooling, migrations, and more.

PyPI version Python versions License

✨ Features

  • Async/Await - Full async support for PostgreSQL, MySQL, SQLite
  • ORM - Django-like model definitions with relationships
  • Query Builder - Fluent SQL builder
  • Connection Pooling - Efficient connection management
  • Migrations - Schema version control with CLI
  • Transactions - ACID transactions with nested savepoints
  • Query Logging - Slow query detection and profiling
  • Batch Operations - Bulk insert/update/delete
  • Pydantic Integration - Automatic validation and serialization
  • CLI Tool - Database management from command line
  • Type Hints - Full type annotations

📦 Installation

pip install pyasyncdb

For Pydantic support:

pip install pyasyncdb[pydantic]

For development:

pip install pyasyncdb[dev]

🚀 Quick Start

Basic Usage

import asyncio
from asyncdb import Database

async def main():
    db = Database("postgresql://user:pass@localhost/mydb")
    
    async with db:
        # Create table
        await db.execute("""
            CREATE TABLE IF NOT EXISTS users (
                id SERIAL PRIMARY KEY,
                name VARCHAR(100),
                email VARCHAR(255) UNIQUE
            )
        """)
        
        # Insert
        await db.execute(
            "INSERT INTO users (name, email) VALUES ($1, $2)",
            ("John", "john@example.com")
        )
        
        # Select
        users = await db.fetch_all("SELECT * FROM users")
        print(users)

asyncio.run(main())

Transactions

from asyncdb import Database

db = Database("postgresql://localhost/mydb")

async with db:
    async with db.transaction():
        # All queries in transaction
        await db.execute("INSERT INTO users (name) VALUES ($1)", ("Alice",))
        await db.execute("UPDATE accounts SET balance = balance - 100 WHERE id = $1", (1,))
        await db.execute("UPDATE accounts SET balance = balance + 100 WHERE id = $2", (2,))
        # Automatically commits on success, rollbacks on error

ORM with Validation

from asyncdb import Database, Model, Field, PydanticModelMixin

db = Database("postgresql://localhost/mydb")

class User(Model, PydanticModelMixin):
    __tablename__ = "users"
    
    id = Field(primary_key=True, auto_increment=True)
    name = Field(type="VARCHAR", max_length=100, nullable=False)
    email = Field(type="VARCHAR", max_length=255, unique=True)
    age = Field(type="INTEGER", default=0)

async with db:
    await User.create_table(db)
    
    # Create instance
    user = User(name="Alice", email="alice@example.com", age=25)
    await user.insert(db)
    
    # Query with filters
    users = await User.objects().filter(age__gte=18).all(db)
    
    # Generate Pydantic schema
    UserSchema = User.pydantic_model()
    validated = UserSchema(name="Bob", email="bob@example.com")

Query Builder

from asyncdb import select, insert, update, delete

# SELECT with joins
q = (
    select("users")
    .columns("id", "name", "email")
    .left_join("orders", "users.id = orders.user_id")
    .where("age > $1", 18)
    .and_where("status = $2", "active")
    .order_by("name")
    .limit(10)
)
sql, params = q.build()

# INSERT
q = insert("users").columns("name", "email").values("John", "john@example.com")
sql, params = q.build()

# UPDATE
q = update("users").set("email", "new@example.com").where("id = $1", 1)
sql, params = q.build()

# DELETE
q = delete("users").where("id = $1", 1)
sql, params = q.build()

Batch Operations

from asyncdb import Database, Model, Field

db = Database("postgresql://localhost/mydb")

class User(Model):
    __tablename__ = "users"
    name = Field(type="VARCHAR", max_length=100)
    email = Field(type="VARCHAR", max_length=255)

async with db:
    # Bulk insert
    users = [
        User(name="Alice", email="alice@example.com"),
        User(name="Bob", email="bob@example.com"),
        User(name="Charlie", email="charlie@example.com"),
    ]
    await User.bulk_insert(db, users)
    
    # Bulk update
    for u in users:
        u.name = u.name.upper()
    await User.bulk_update(db, users)
    
    # Bulk delete
    await User.bulk_delete(db, [1, 2, 3])

Query Logging & Debugging

from asyncdb import Database
import logging

logging.basicConfig(level=logging.INFO)

# Enable query logging
db = Database("postgresql://localhost/mydb", echo=True, slow_query_threshold=0.5)

async with db:
    await db.execute("SELECT * FROM users")
    await db.execute("SELECT * FROM orders WHERE amount > 1000")  # Slow query
    
    # Get slow queries
    slow = db.get_slow_queries()
    print(f"Slow queries: {len(slow)}")
    
    # Get all query log
    log = db.get_query_log()
    for entry in log:
        print(f"{entry['duration']:.3f}s - {entry['query']}")

🛠 CLI Commands

# Set database URL
export DATABASE_URL="postgresql://user:pass@localhost/mydb"

# Run migrations
pyasyncdb migrate-up

# Rollback migrations
pyasyncdb migrate-down --steps 2

# Check migration status
pyasyncdb migrate-status

# Create new migration
pyasyncdb migrate-create add_users_table

# Interactive shell
pyasyncdb shell

# Inspect database
pyasyncdb inspect

📊 Database URLs

postgresql://user:pass@host:5432/dbname
mysql://user:pass@host:3306/dbname
sqlite:///path/to/database.db

📖 API Reference

Database

Method Description
connect() Establish connection
disconnect() Close connection
execute(query, params) Execute query
fetch_one(query, params) Fetch single row
fetch_all(query, params) Fetch all rows
fetch_val(query, params) Fetch single value
fetch_col(query, params) Fetch single column
transaction() Transaction context
get_query_log() Get query history
get_slow_queries() Get slow queries

Model

Method Description
create_table(db) Create table
drop_table(db) Drop table
insert(db) Insert instance
update(db) Update instance
delete(db) Delete instance
save(db) Insert or update
bulk_insert(db, instances) Bulk insert
bulk_update(db, instances) Bulk update
bulk_delete(db, ids) Bulk delete
objects() Get queryset
pydantic_model() Generate Pydantic schema

QuerySet

Method Description
filter(**kwargs) Add WHERE filters
exclude(**kwargs) Add NOT filters
order_by(*fields) Add ORDER BY
limit(n) Add LIMIT
offset(n) Add OFFSET
all(db) Fetch all
first(db) Fetch first
count(db) Count records
exists(db) Check existence

📝 License

MIT License - see LICENSE for details.

🤝 Contributing

Contributions welcome! Please read our contributing guidelines first.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

📧 Support

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

asyncdb_lib-0.3.0.tar.gz (25.2 kB view details)

Uploaded Source

Built Distribution

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

asyncdb_lib-0.3.0-py3-none-any.whl (24.0 kB view details)

Uploaded Python 3

File details

Details for the file asyncdb_lib-0.3.0.tar.gz.

File metadata

  • Download URL: asyncdb_lib-0.3.0.tar.gz
  • Upload date:
  • Size: 25.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for asyncdb_lib-0.3.0.tar.gz
Algorithm Hash digest
SHA256 c5e8b33dcef0995226f672062dffa6858c1fd74df179188a8c9b191bdacdc347
MD5 99841a2d6f7558c21eeb26cad2ef4aa3
BLAKE2b-256 d209d73bbc094f3585ca5486aa751c33d500bf3311e8405eec012a4de2a774aa

See more details on using hashes here.

File details

Details for the file asyncdb_lib-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: asyncdb_lib-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 24.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.12

File hashes

Hashes for asyncdb_lib-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3fd85c5fa6f1605be961cdfed9158332495eda65c55cc296579fec3f74233168
MD5 20802c6e19c10ea3b7cbf5e26793981f
BLAKE2b-256 249f350bb4d123cb875d18473a64b6683d2137dc8b686212c54476378f360591

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