wey-gu/py-pglite(新しいタブで開きます)
主要言語: Python
PGlite wrapper in Python for testing. Test your app with Postgres just as lite as SQLite.
- star 数
- 638
- watcher 数
- 4
- fork 数
- 22
- issue 数
- 22
- 最終更新
- 2025/09/17
主要言語: Python
PGlite wrapper in Python for testing. Test your app with Postgres just as lite as SQLite.
A Pythonic interface for PGlite - the instant, zero-config PostgreSQL. ⚡️
py-pglite brings the magic of PGlite to Python with a high-level, developer-friendly API. Real PostgreSQL, instant testing.
pip install py-pglite
def test_users(pglite_session): user = User(name="Alice") pglite_session.add(user) pglite_session.commit() assert user.id == 1 # It's real PostgreSQL!
That's it. No Docker, no setup, no config files. Real PostgreSQL, instant testing.
# ❌ Traditional testing def test_old_way(): # 1. Install PostgreSQL # 2. Configure connection # 3. Manage test databases # 4. Handle cleanup # 5. Docker containers... pass # ✅ py-pglite way def test_new_way(pglite_session): User.objects.create(name="Alice") # Just works!
The magic:
# Core (framework-agnostic) pip install py-pglite # With your stack pip install py-pglite[sqlalchemy] # SQLAlchemy + SQLModel pip install py-pglite[django] # Django + pytest-django pip install py-pglite[asyncpg] # Pure async client pip install py-pglite[all] # Everything # Extra Features pip install py-pglite[extensions] # pglite extensions, like pgvector, fuzzystrmatch etc.
def test_sqlalchemy_just_works(pglite_session): user = User(name="Alice", email="alice@test.com") pglite_session.add(user) pglite_session.commit() assert user.id is not None assert User.query.count() == 1 # Real PostgreSQL!
🔹 Lightweight/Socket (Minimal setup)
def test_django_socket_pattern(configured_django): Post.objects.create(title="Hello", content="World") assert Post.objects.count() == 1 # Real PostgreSQL via socket!
🔸 Full Integration/Backend (Enhanced features)
def test_django_backend_pattern(django_pglite_db): Post.objects.create(title="Hello", content="World", metadata={"tags": ["test"]}) assert Post.objects.count() == 1 # Custom backend with JSON support!
Choose your pattern:
👉 See Django patterns guide for detailed examples and migration guide.
def test_any_client_works(pglite_manager): # Extract connection details engine = pglite_manager.get_engine() host, port, database = str(engine.url.host), engine.url.port, engine.url.database # Use with any PostgreSQL client # conn = psycopg.connect(host=host, port=port, dbname=database) # engine = create_async_engine(f"postgresql+asyncpg://{host}:{port}/{database}") # For asyncpg specifically, use TCP mode with proper configuration: async def test_asyncpg_works(pglite_tcp_manager): config = pglite_tcp_manager.config conn = await asyncpg.connect( host=config.tcp_host, port=config.tcp_port, user="postgres", password="postgres", database="postgres", ssl=False, server_settings={} # CRITICAL: Required for PGlite compatibility ) result = await conn.fetchval("SELECT 1") await conn.close()
from fastapi.testclient import TestClient def test_api_endpoint(client: TestClient): response = client.post("/users/", json={"name": "Alice"}) assert response.status_code == 201 response = client.get("/users/") assert len(response.json()) == 1
def test_postgresql_power(pglite_session): pglite_session.execute(text(""" CREATE TABLE analytics ( data JSONB, tags TEXT[], created TIMESTAMP DEFAULT NOW() ) """)) pglite_session.execute(text(""" INSERT INTO analytics (data, tags) VALUES ('{"clicks": 100}', ARRAY['web', 'mobile']) """)) result = pglite_session.execute(text(""" SELECT data->>'clicks' as clicks, array_length(tags, 1) as tag_count FROM analytics WHERE data->>'clicks' > '50' """)).fetchone() assert result.clicks == '100'
py-pglite supports PostgreSQL extensions, allowing you to test advanced features like vector similarity search for AI/RAG applications.
Enable pgvector to test vector embeddings and similarity search directly in your test suite.
1. Install with the [extensions] extra:
pip install 'py-pglite[extensions]'2. Enable pgvector in the configuration:
from py_pglite import PGliteConfig, PGliteManager from pgvector.psycopg import register_vector import psycopg import numpy as np # Enable the extension config = PGliteConfig(extensions=["pgvector"]) with PGliteManager(config=config) as db: with psycopg.connect(db.get_dsn(), autocommit=True) as conn: # Create the extension and register the type conn.execute("CREATE EXTENSION IF NOT EXISTS vector") register_vector(conn) # Create a table and insert a vector conn.execute("CREATE TABLE items (embedding vector(3))") conn.execute("INSERT INTO items (embedding) VALUES (%s)", (np.array([1, 2, 3]),)) # Perform a similarity search result = conn.execute("SELECT * FROM items ORDER BY embedding <-> %s LIMIT 1", (np.array([1, 1, 1]),)).fetchone() assert np.array_equal(result[0], np.array([1, 2, 3]))
py-pglite can support many other extensions available in the underlying PGlite extensions ♥️.
from py_pglite import PGliteConfig from py_pglite.sqlalchemy import SQLAlchemyPGliteManager config = PGliteConfig( timeout=60, # Extended timeout for CI/CD log_level="INFO", # Balanced logging cleanup_on_exit=True, # Automatic cleanup work_dir=Path("./test-data") # Custom directory ) with SQLAlchemyPGliteManager(config) as manager: engine = manager.get_engine( pool_recycle=3600, # Connection recycling echo=False # SQL logging )
py-pglite supports both Unix domain sockets (default) and TCP sockets for different use cases:
# Default configuration - uses Unix domain socket for best performance from py_pglite import PGliteManager with PGliteManager() as db: # Connection via Unix socket - fastest for local testing dsn = db.get_dsn() # host=/tmp/... dbname=postgres
from py_pglite import PGliteConfig, PGliteManager # Enable TCP mode for any TCP-only clients config = PGliteConfig( use_tcp=True, tcp_host="127.0.0.1", # Default: localhost only tcp_port=5432, # Default: PostgreSQL standard port extensions=["pgvector"] ) with PGliteManager(config) as db: # Now compatible with any TCP-only clients uri = db.get_psycopg_uri() # postgresql://postgres:postgres@127.0.0.1:5432/postgres?sslmode=disable
When to use TCP mode:
Important notes:
sslmode=disableserver_settings={} to prevent hanging# py-pglite provides a REAL PostgreSQL server - any client works! with SQLAlchemyPGliteManager() as manager: engine = manager.get_engine() url = engine.url # Extract connection details for any PostgreSQL client host, port, database = str(url.host), url.port, url.database # Examples for different clients: # psycopg: psycopg.connect(host=host, port=port, dbname=database) # Django: Uses custom py-pglite backend automatically # asyncpg requires TCP mode and specific configuration: config = PGliteConfig(use_tcp=True) with PGliteManager(config) as manager: conn = await asyncpg.connect( host=config.tcp_host, port=config.tcp_port, user="postgres", password="postgres", database="postgres", ssl=False, server_settings={} # Required for PGlite compatibility )
Installation Matrix:
| Client | Install | Use Case |
|---|---|---|
[sqlalchemy] |
SQLAlchemy + SQLModel | ORM, modern Python |
[django] |
Django + pytest-django | Django projects |
[psycopg] |
psycopg (sync/async) | Raw SQL, custom |
[asyncpg] |
Pure async client | High-performance async |
[all] |
Everything | Full compatibility |
# Perfect isolation - no framework bleeding pytest -m sqlalchemy -p no:django # Pure SQLAlchemy pytest -m django -p no:sqlalchemy # Pure Django pytest tests/sqlalchemy/ # Directory isolation
Built for developers who want PostgreSQL testing without the complexity.
🎯 Examples • 📚 Contributing • 🐛 Issues
py-pglite: Because testing should be simple. ⚡
Powered by the 🚀 amazing and ♥️ beloved PGlite.