PyPGKit
A PostgreSQL database framework for Python using psycopg3 with connection pooling, thread-safety, and repository pattern.
Features
- Connection Pooling: Thread-safe connection pool using
psycopg_pool - Singleton Pattern: Global database instance with
Database.init()andDatabase.get_instance() - Repository Pattern: Base repository class with CRUD operations
- Automatic Setup: Create database, user, and schema automatically
- Fork Safety: Compatible with gunicorn and other forking servers
- Configurable Logging: Built-in logging with multiple formats
- Type Hints: Full type annotations for better IDE support
Installation
pip install PyPGKit
Quick Start
Basic Usage
from pypgkit import Database, DatabaseConfig
# Initialize once at application startup
config = DatabaseConfig(
host="localhost",
port=5432,
database="myapp",
user="myuser",
password="mypassword",
)
# This creates the database/user if needed and initializes the connection pool
Database.init(config=config, schema_path="schemas/init.sql")
# Use anywhere in your application
db = Database.get_instance()
# Execute queries
users = db.fetch_all("SELECT * FROM users WHERE active = %s", (True,))
Environment Variables
pypgkit supports configuration via environment variables:
export PYPGKIT_HOST=localhost
export PYPGKIT_PORT=5432
export PYPGKIT_DATABASE=myapp
export PYPGKIT_USER=myuser
export PYPGKIT_PASSWORD=mypassword
from pypgkit import Database, DatabaseConfig
# Load from environment
config = DatabaseConfig.from_env()
Database.init(config=config)
Repository Pattern
Create type-safe repositories for your entities:
from dataclasses import dataclass
from typing import Optional
from pypgkit import Database
from pypgkit.repositories import BaseRepository
@dataclass
class User:
id: Optional[int] = None
email: str = ""
name: str = ""
active: bool = True
class UserRepository(BaseRepository[User]):
table_name = "users"
primary_key = "id"
def _row_to_entity(self, row: dict) -> User:
return User(
id=row.get("id"),
email=row.get("email", ""),
name=row.get("name", ""),
active=row.get("active", True),
)
def _entity_to_row(self, entity: User) -> dict:
row = {"email": entity.email, "name": entity.name, "active": entity.active}
if entity.id is not None:
row["id"] = entity.id
return row
# Usage
db = Database.get_instance()
repo = UserRepository(db)
# Create
user = repo.create(User(email="user@example.com", name="John"))
# Read
user = repo.find_by_id(1)
users = repo.find_all(limit=10)
active_users = repo.find_by({"active": True})
# Update
user.name = "Jane"
repo.update(user)
# Delete
repo.delete(1)
Logging Configuration
from pypgkit.logging import configure_logging, LogLevel, DETAILED_FORMAT
# Basic configuration
configure_logging(level=LogLevel.INFO)
# Debug mode with detailed format
configure_logging(level=LogLevel.DEBUG, format=DETAILED_FORMAT)
# Log to file
configure_logging(level=LogLevel.INFO, filename="pypgkit.log")
# Include psycopg logs
configure_logging(level=LogLevel.DEBUG, include_psycopg=True)
Automatic Database Setup
pypgkit can automatically create the database and user if they don't exist:
from pypgkit import Database, DatabaseConfig
config = DatabaseConfig(
database="myapp",
user="myuser",
password="mypassword",
)
# Interactive mode (prompts for admin credentials)
Database.init(config=config, auto_setup=True, interactive=True)
# Non-interactive mode (for CI/CD)
from pypgkit.setup import setup_database
setup_database(
config,
admin_user="postgres",
admin_password="adminpass",
interactive=False,
)
Using with Gunicorn
pypgkit automatically handles fork detection for compatibility with gunicorn:
# wsgi.py
from pypgkit import Database, DatabaseConfig
config = DatabaseConfig.from_env()
Database.init(config=config)
# The connection pool automatically resets after fork
gunicorn -w 4 myapp:app
API Reference
DatabaseConfig
Configuration dataclass for database connections.
| Parameter | Type | Default | Description |
|---|---|---|---|
| host | str | "localhost" | Database host |
| port | int | 5432 | Database port |
| database | str | "postgres" | Database name |
| user | str | "postgres" | Database user |
| password | str | "" | Database password |
| connection_string | str | None | Full connection string (optional) |
| min_connections | int | 1 | Minimum pool connections |
| max_connections | int | 10 | Maximum pool connections |
| connection_timeout | float | 30.0 | Connection timeout in seconds |
| sslmode | str | "prefer" | SSL mode |
| check_connection | bool | True | Enable pool health checks |
| max_idle_time | float | 600.0 | Max idle time before connection recycled |
Database
Main database facade class.
| Method | Description |
|---|---|
Database.init(config, schema_path, schema_sql, auto_setup, interactive) |
Initialize singleton |
Database.get_instance() |
Get initialized instance |
Database.is_initialized() |
Check if initialized |
Database.reset_instance() |
Reset singleton (for testing) |
db.connect() |
Establish connection |
db.disconnect() |
Close connection pool |
db.execute(query, params) |
Execute query, return row count |
db.execute_many(query, params_seq) |
Execute with multiple parameter sets |
db.fetch_one(query, params, as_dict) |
Fetch single row |
db.fetch_all(query, params, as_dict) |
Fetch all rows |
db.fetch_value(query, params) |
Fetch single value |
db.table_exists(table_name, schema) |
Check if table exists |
db.transaction() |
Context manager for transactions |
db.get_stats() |
Get connection pool statistics |
db.health_check() |
Check connection health |
BaseRepository
Base class for repositories with CRUD operations.
| Method | Description |
|---|---|
find_by_id(id) |
Find entity by primary key |
find_all(limit, offset, order_by, order_desc) |
Find all entities |
find_by(conditions, limit, offset, order_by, order_desc) |
Find by conditions |
find_one_by(conditions) |
Find one by conditions |
create(entity) |
Create new entity |
create_many(entities) |
Create multiple entities |
update(entity) |
Update existing entity |
delete(id) |
Delete by primary key |
delete_by(conditions) |
Delete by conditions |
count(conditions) |
Count entities |
exists(id) |
Check if entity exists |
Development
Setup
git clone https://github.com/miichoow/PyPGKit.git
cd PyPGKit
pip install -e ".[dev]"
Running Tests
pytest tests/ -v --cov=pypgkit --cov-report=term-missing
Linting
ruff check pypgkit/
ruff format pypgkit/
License
MIT License - see LICENSE file for details.
Release files for PyPGKit 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| pypgkit-1.0.0.tar.gz | 29.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| pypgkit-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 55.6 kB
Release files / pypgkit-1.0.0.tar.gz
| Download URL | pypgkit-1.0.0.tar.gz |
|---|---|
| Size | 29.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f3f0d460b17af9aa5de7f7c7c91b996e8528aa6e454903c83efc9c4ba933c763
|
|
BLAKE2b-256 checksum How to use checksums |
82b20a2e062edf143d9f39d546f42e3d2c5bacaf170983c3f00bfefd8cd8e40e
|
| 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 Feb 4, 2026.
Transparency logRelease files / pypgkit-1.0.0-py3-none-any.whl
| Download URL | pypgkit-1.0.0-py3-none-any.whl |
|---|---|
| Size | 26.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1f7e5afa9f5dc92cdaf07b0208a12702760e86ffbba15c021bbb47e6f382017b
|
|
BLAKE2b-256 checksum How to use checksums |
618c11f5be06a9e8da75cacd46a50f1f2045a5e199247b3dc89e95b1ddadf50c
|
| 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 Feb 4, 2026.
Transparency log