py-pglite
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.
Why py-pglite?
# ❌ 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:
- 🎯 Zero config - No setup, no Docker, no servers
- ⚡ Instant - 2-3s startup vs 30-60s Docker
- 🔄 Isolated - Fresh database per test
- 🐘 Real PostgreSQL - JSON, arrays, window functions
- 🚀 Any client - SQLAlchemy, Django, psycopg, asyncpg
Install
# 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.
Quick Start
SQLAlchemy (Zero imports needed)
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!
Django
🔹 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:
- Lightweight: Fast, minimal dependencies, standard PostgreSQL backend
- Full Integration: Advanced features, custom backend, enhanced JSON support
👉 See Django patterns guide for detailed examples and migration guide.
Any PostgreSQL client
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()
Examples
FastAPI + SQLModel
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
PostgreSQL Features
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'
PostgreSQL Extensions
py-pglite supports PostgreSQL extensions, allowing you to test advanced features like vector similarity search for AI/RAG applications.
🚀 pgvector for 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 ♥️.
Advanced
🔧 Production Configuration
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
)
🌐 Socket Modes (Unix vs TCP)
py-pglite supports both Unix domain sockets (default) and TCP sockets for different use cases:
Unix Socket Mode (Default)
# 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
TCP Socket Mode
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:
- Any TCP-only clients (doesn't support Unix sockets)
- Cloud-native testing environments
- Docker containers with network isolation
- Testing network-based database tools
- Required for asyncpg: asyncpg only works in TCP mode
Important notes:
- PGlite Socket supports only one active connection at a time
- SSL is not supported - always use
sslmode=disable - Unix sockets are faster for local testing (default)
- TCP mode binds to localhost by default for security
- asyncpg requires
server_settings={}to prevent hanging
🔄 Client Compatibility
# 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 |
🎯 Framework Isolation
# 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.
Release files for py-pglite 0.5.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| py_pglite-0.5.3.tar.gz | 32.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| py_pglite-0.5.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 75.3 kB
Release files / py_pglite-0.5.3.tar.gz
| Download URL | py_pglite-0.5.3.tar.gz |
|---|---|
| Size | 32.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
58c694602b48fa0562588d7d7c70dd05cc75d048b365ddf3e34d76833598194d
|
|
BLAKE2b-256 checksum How to use checksums |
2a12fb2a0b898f0f34b4e98ea2a2158c1e91afbdfb2b4717a77d7840ae44fb9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2025.
Transparency logRelease files / py_pglite-0.5.3-py3-none-any.whl
| Download URL | py_pglite-0.5.3-py3-none-any.whl |
|---|---|
| Size | 42.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c0526d3f69de34bfab2073be43f83b5f023b1856af9623d491bda0de5bef3475
|
|
BLAKE2b-256 checksum How to use checksums |
1be89265f8ffced326468dac06919a1ca1cc7cbf8c4267a4547cddf7ef887602
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
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.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 17, 2025.
Transparency log