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

pyasyncdb_driver-0.2.0.tar.gz (24.2 kB view details)

Uploaded Source

Built Distribution

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

pyasyncdb_driver-0.2.0-py3-none-any.whl (22.9 kB view details)

Uploaded Python 3

File details

Details for the file pyasyncdb_driver-0.2.0.tar.gz.

File metadata

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

File hashes

Hashes for pyasyncdb_driver-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c602e52005f9fa467b0432f83cebdc944b37b48bb2d8465a638779523b17775c
MD5 2c58e63bbec44d44aa874c95c95c7d00
BLAKE2b-256 4c5316acfca3c3c1550f66eaf5ea6b9e9ce1d85878965fd54ed30235185fd9f7

See more details on using hashes here.

File details

Details for the file pyasyncdb_driver-0.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for pyasyncdb_driver-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c41682a584b5214b80a82b11931711c163bf5c6c3469642145833456be96ba0b
MD5 ffd16c79d2ec9addabe5ff72fd49ab6d
BLAKE2b-256 f15f50019f7d28f5293df683526f4fa79f6c8a981ae8b32f75713949753af371

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