Skip to main content

PostgreSQL ORM using Pydantic models - simple, type-safe database operations

Project description

wpostgresql

PyPI version Python versions License Tests Pylint Bandit PyPI Downloads LTS Version

wpostgresql is a high-performance, type-safe PostgreSQL ORM that leverages Pydantic models for schema definition and automatic table synchronization. It provides a seamless developer experience with full support for both synchronous and asynchronous operations.

Key Features

  • Pydantic Integration — Define database schemas using Pydantic v2 models with automatic type validation
  • Auto Table Synchronization — Tables are created and updated automatically based on model changes
  • Type-Safe Operations — Full type hints with Pydantic validation for data integrity
  • Async/Await Support — Complete async API for high-performance applications
  • Connection Pooling — Built-in connection pooling for both sync and async operations
  • Transaction Management — Robust transaction support with automatic rollback
  • Bulk Operations — Efficient bulk insert, update, and delete operations
  • Constraint Support — Primary Key, UNIQUE, and NOT NULL constraints via field descriptions
  • Query Builder — Safe SQL query construction with injection prevention
  • CLI Tool — Command-line interface for database management
  • Code Quality — Pylint score > 9.5, Bandit security checks passing, mypy type checking
  • Pagination — LIMIT/OFFSET and page-number based pagination

Technical Stack

Component Technology
Language Python 3.9+
Database PostgreSQL 13+
ORM Core psycopg 3.x, psycopg_pool
Validation Pydantic 2.x
Logging Loguru
CLI Click
Testing pytest, pytest-cov
Linting ruff, pylint
Type Checking mypy
Security bandit, detect-secrets
Containerization Docker, Docker Compose
Documentation Sphinx, Read the Docs

Installation & Setup

Prerequisites

  • Python 3.9 or higher
  • PostgreSQL 13 or higher
  • Docker (optional, for containerized setup)

Using pip

pip install wpostgresql

From Source

# Clone the repository
git clone https://github.com/wisrovi/wpostgresql.git
cd wpostgresql

# Create and activate virtual environment
python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install with development dependencies
pip install -e ".[dev]"

Using Docker (Optional)

cd docker
docker-compose up -d

This starts:

  • PostgreSQL 13.2 on port 5432
  • pgAdmin4 on port 1717

Architecture & Workflow

File Tree

wpostgresql/
├── .github/
│   └── workflows/           # CI/CD pipelines
│       ├── pr-validation.yml
│       ├── test.yml
│       ├── pylint.yml
│       └── static.yml
├── src/wpostgresql/         # Core library
│   ├── __init__.py
│   ├── builders/            # SQL query builder
│   │   └── query_builder.py
│   ├── cli/                 # CLI tool
│   │   └── main.py
│   ├── core/                # ORM core
│   │   ├── connection.py    # Connection pooling
│   │   ├── repository.py   # WPostgreSQL class
│   │   └── sync.py         # Table sync
│   ├── exceptions/          # Custom exceptions
│   │   └── __init__.py
│   └── types/               # SQL type mapping
│       └── sql_types.py
├── docs/                    # Sphinx documentation
│   ├── getting_started/
│   ├── api_reference/
│   └── tutorials/
├── examples/                # Usage examples
│   ├── 01_crud/
│   ├── 02_new_columns/
│   ├── 03_restrictions/
│   ├── 04_pagination/
│   ├── 05_transactions/
│   ├── 06_bulk_operations/
│   ├── 07_connection_pooling/
│   ├── 08_logging/
│   ├── 09_async/
│   ├── 10_aggregations/
│   ├── 11_timestamps/
│   ├── 12_raw_sql/
│   ├── 13_soft_delete/
│   └── 14_relationships/
├── test/                    # Unit and integration tests
│   └── ...
├── docker/                  # Docker configuration
│   ├── docker-compose.yaml
│   └── Dockerfile.postgress
├── pyproject.toml          # Project configuration
└── README.md

System Workflow

flowchart TD
    A[Developer defines Pydantic Model] --> B[WPostgreSQL Instance Created]
    B --> C{Table Exists?}
    C -->|No| D[TableSync creates table]
    C -->|Yes| E[Column sync check]
    D --> F[Schema synchronized]
    E -->|New columns detected| G[Add missing columns]
    E -->|No changes| H[Ready for operations]
    G --> F
    F --> H
    H --> I[CRUD Operations Available]
    I --> J[insert/get/update/delete]
    J --> K[Query Builder constructs SQL]
    K --> L[Connection Pool]
    L --> M[PostgreSQL Database]
    M --> N[Results returned as Pydantic models]

Configuration

Database Connection Configuration

Create a configuration dictionary:

DB_CONFIG = {
    "dbname": "your_database",
    "user": "your_user",
    "password": "your_password",
    "host": "localhost",
    "port": 5432,
}

Environment Variables (Recommended)

For production, use environment variables to avoid exposing credentials:

import os

DB_CONFIG = {
    "dbname": os.getenv("DB_NAME", "mydb"),
    "user": os.getenv("DB_USER", "postgres"),
    "password": os.getenv("DB_PASSWORD"),
    "host": os.getenv("DB_HOST", "localhost"),
    "port": int(os.getenv("DB_PORT", 5432)),
}

Connection Pool Configuration

POOL_CONFIG = {
    "min_size": 2,
    "max_size": 20,
    "timeout": 30,
}

Usage

Basic Sync Usage

from pydantic import BaseModel
from wpostgresql import WPostgreSQL

class User(BaseModel):
    id: int
    name: str
    email: str

DB_CONFIG = {
    "dbname": "mydb",
    "user": "postgres",
    "password": "secret",
    "host": "localhost",
    "port": 5432,
}

db = WPostgreSQL(User, DB_CONFIG)

# Insert
db.insert(User(id=1, name="John", email="john@example.com"))

# Query all
users = db.get_all()

# Query by field
john = db.get_by_field(name="John")

# Update
db.update(1, User(id=1, name="Jane", email="jane@example.com"))

# Delete
db.delete(1)

Async Usage

import asyncio
from pydantic import BaseModel
from wpostgresql import WPostgreSQL

class User(BaseModel):
    id: int
    name: str
    email: str

async def main():
    db = WPostgreSQL(User, DB_CONFIG)
    
    await db.insert_async(User(id=1, name="John", email="john@example.com"))
    users = await db.get_all_async()
    print(users)

asyncio.run(main())

CLI Commands

# View help
wpostgresql --help

# Sync table from model
wpostgresql sync path/to/model.py

# Check connection status
wpostgresql status

Testing

# Run all tests
pytest

# Run with coverage
pytest --cov=wpostgresql --cov-report=html

# Run specific test file
pytest test/unit/test_connection.py -v

Project Quality Metrics

Metric Status
Version 1.0.0 (LTS)
Pylint Score > 9.5
Bandit Security Passing
mypy Type Check Passing
Code Coverage 70%+
Docstring Coverage > 90%
Python Support 3.9 - 3.13

Contributing

Contributions are welcome. Please read our Contributing Guide for guidelines.

License

MIT License — see LICENSE file for details.

Author

William Rodríguez - wisrovi

Technology Evangelist & Software Architect

LinkedIn: William Rodríguez


Built with ❤️ for the Python community

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

wpostgresql-1.0.0.tar.gz (882.7 kB view details)

Uploaded Source

Built Distribution

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

wpostgresql-1.0.0-py3-none-any.whl (29.6 kB view details)

Uploaded Python 3

File details

Details for the file wpostgresql-1.0.0.tar.gz.

File metadata

  • Download URL: wpostgresql-1.0.0.tar.gz
  • Upload date:
  • Size: 882.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wpostgresql-1.0.0.tar.gz
Algorithm Hash digest
SHA256 2200d89170fb29671d5186d17730c365851501e5683c09eab09efc844a3a3a87
MD5 481cabf9b5ebcc8f45778f7dda133ef1
BLAKE2b-256 93874e265331a37020ef5edad365d16a42a8c53ed58c22a303b5d946a677b67a

See more details on using hashes here.

File details

Details for the file wpostgresql-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: wpostgresql-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 29.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for wpostgresql-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f2c7871fe5c7995d7e59cd49db7b46e87d16b258f41be291f9c7530b938b24a4
MD5 6c7fd77a3259258526961db2db3e96ac
BLAKE2b-256 89bb436ff4548cfd4ae04fc3f35a1e2f339e806bf2bd84a7bdc48e981c1e19a5

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