Skip to main content

PyPGKit

PyPI version Python versions License Tests codecov Code style: ruff

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() and Database.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)

Source distribution for PyPGKit 1.0.0
File Size Uploaded
pypgkit-1.0.0.tar.gz 29.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for PyPGKit 1.0.0
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

This release

1.0.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page