Metadata-Version: 2.4
Name: oxyde-postgres
Version: 0.2.1
Summary: Type-safe asynchronous ORM for PostgreSQL 18+ with a Rust core
Author-email: E Brake <ebrake123@icloud.com>, Nikita Ryzhenkov <nikita.ryzhenkoff@gmail.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/ebrake/oxyde-postgres
Project-URL: Documentation, https://github.com/ebrake/oxyde-postgres/tree/main/docs
Project-URL: Repository, https://github.com/ebrake/oxyde-postgres
Project-URL: Issues, https://github.com/ebrake/oxyde-postgres/issues
Keywords: orm,async,database,postgresql,pydantic
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: 3.15
Classifier: Programming Language :: Rust
Classifier: Framework :: AsyncIO
Classifier: Topic :: Database
Classifier: Typing :: Typed
Requires-Python: >=3.13
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pydantic>=2.14.3
Requires-Dist: msgpack>=1.2.4
Requires-Dist: typer>=0.29.1
Requires-Dist: oxyde-postgres-core<0.3.0,>=0.2.1
Provides-Extra: dev
Requires-Dist: pytest>=9.2.0; extra == "dev"
Requires-Dist: pytest-asyncio>=1.4.1.post1; extra == "dev"
Requires-Dist: pytest-cov>=7.1.0; extra == "dev"
Requires-Dist: ruff>=0.17.4; extra == "dev"
Requires-Dist: pre-commit>=4.7.0; extra == "dev"
Requires-Dist: mypy==2.4.1; extra == "dev"
Requires-Dist: pyright[nodejs]==1.1.414; extra == "dev"
Requires-Dist: ty==0.0.100; extra == "dev"
Requires-Dist: testcontainers[postgres]>=4.15.0; extra == "dev"
Requires-Dist: psycopg2-binary>=2.9.13; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs<2,>=1.6.1; extra == "docs"
Requires-Dist: mkdocs-material>=9.8.1; extra == "docs"
Requires-Dist: pymdown-extensions>=13.0; extra == "docs"
Requires-Dist: mike>=2.2.0; extra == "docs"
Dynamic: license-file

# Oxyde for PostgreSQL

Oxyde for PostgreSQL is a PostgreSQL-focused fork of [Oxyde ORM](https://github.com/mr-fatalyst/oxyde): a type-safe, Pydantic-centric asynchronous ORM with a high-performance Rust core designed for clarity, speed, and reliability. It builds on Oxyde's great work and optimizes it for PostgreSQL with bug fixes and PostgreSQL-specific features.

**Requires PostgreSQL 18+ and Python 3.13+.** The Rust core checks the server version when connecting. Both `postgres://` and `postgresql://` connection URLs are supported.

## Features

- Pydantic v2 models with validation, type hints, and serialization.
- Familiar `Model.objects.filter()` queries, joins, aggregates, and bulk operations.
- Native PostgreSQL arrays, JSONB, enums, UUIDs, decimals, `RETURNING`, and row locks.
- Array and JSON lookups: `contains`, `contained_by`, and `overlap`.
- Async transactions with nested savepoints and public transaction-depth reporting.
- Schema migrations with PostgreSQL advisory locking and transactional DDL.
- Rust SQL generation, connection pooling, and execution, with Python 3.15 wheel support.
- Cache-disabled unnamed statements for PostgreSQL/PgBouncer, including cold custom-type decoding without replaying queries.

Version **0.2.1** adds PostgreSQL `NULLS NOT DISTINCT` for unique columns and indexes, with reversible migrations. [Release notes](https://github.com/ebrake/oxyde-postgres/blob/main/docs/changelog.md) list the changes and the original fork additions.

## Installation

```bash
pip install oxyde-postgres
```

The distribution names are `oxyde-postgres` and `oxyde-postgres-core`. Python imports remain `oxyde`, the native module remains `_oxyde_core`, and the CLI remains `oxyde`. Use a separate virtual environment from upstream Oxyde because the packages share these import names.

To build this checkout:

```bash
uv venv --python 3.13
source .venv/bin/activate
uv pip install maturin
maturin develop --manifest-path crates/oxyde-core-py/Cargo.toml
uv pip install -e './python[dev]'
```

## Quick start

```python
import asyncio
from oxyde import Field, Model, db
from oxyde.db.schema import create_tables

class User(Model):
    id: int | None = Field(default=None, db_pk=True)
    name: str
    email: str = Field(db_unique=True)
    tags: list[str] = Field(default_factory=list)

    class Meta:
        is_table = True

async def main():
    await db.init(default="postgresql://user:password@localhost:5432/app")
    try:
        connection = await db.get_connection()
        await create_tables(connection)
        await User.objects.create(name="Alice", email="alice@example.com", tags=["python"])
        users = await User.objects.filter(tags__contains=["python"]).all()
        print(users)
    finally:
        await db.close()

asyncio.run(main())
```

For managed schema changes, run `oxyde init`, `oxyde makemigrations`, and `oxyde migrate`. See the [documentation](https://github.com/ebrake/oxyde-postgres/blob/main/docs/index.md), [connection guide](https://github.com/ebrake/oxyde-postgres/blob/main/docs/guide/connections.md), and [contributor guide](https://github.com/ebrake/oxyde-postgres/blob/main/.github/CONTRIBUTING.md).

## Credit and license

Oxyde for PostgreSQL is based on [Oxyde](https://github.com/mr-fatalyst/oxyde), created by Nikita Ryzhenkov and its contributors. The original MIT [license](https://github.com/ebrake/oxyde-postgres/blob/main/LICENSE) is preserved. The vendored SQLx PostgreSQL driver retains its MIT and Apache-2.0 licenses.
