Metadata-Version: 2.4
Name: pydantable
Version: 1.3.0
Classifier: Development Status :: 5 - Production/Stable
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Dist: pydantic>=2.0,<3
Requires-Dist: typing-extensions>=4.7
Requires-Dist: pyarrow>=14.0 ; extra == 'arrow'
Requires-Dist: maturin>=1.4,<2.0 ; extra == 'benchmark'
Requires-Dist: pandas>=2.0 ; extra == 'benchmark'
Requires-Dist: polars>=1.0.0,<2 ; extra == 'benchmark'
Requires-Dist: google-cloud-bigquery>=3.0 ; extra == 'bq'
Requires-Dist: fsspec>=2023.0 ; extra == 'cloud'
Requires-Dist: fastapi>=0.100 ; extra == 'dev'
Requires-Dist: httpx>=0.24 ; extra == 'dev'
Requires-Dist: sqlalchemy>=2.0,<3 ; extra == 'dev'
Requires-Dist: python-multipart>=0.0.6 ; extra == 'dev'
Requires-Dist: hypothesis>=6.0 ; extra == 'dev'
Requires-Dist: numpy>=1.24 ; extra == 'dev'
Requires-Dist: pyarrow>=14.0 ; extra == 'dev'
Requires-Dist: pytest>=7.0 ; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23 ; extra == 'dev'
Requires-Dist: pytest-cov>=4.0 ; extra == 'dev'
Requires-Dist: pytest-xdist>=3.0 ; extra == 'dev'
Requires-Dist: ruff>=0.8.0 ; extra == 'dev'
Requires-Dist: pyright>=1.1.0 ; extra == 'dev'
Requires-Dist: coverage[toml]>=7.0 ; extra == 'dev'
Requires-Dist: polars>=1.0.0,<2 ; extra == 'dev'
Requires-Dist: streamlit>=1.30,<2 ; extra == 'dev'
Requires-Dist: dataframe-api-compat>=0.2.7 ; extra == 'dev'
Requires-Dist: fsspec>=2023.0 ; extra == 'dev'
Requires-Dist: google-cloud-bigquery>=3.0 ; extra == 'dev'
Requires-Dist: kafka-python>=2.0 ; extra == 'dev'
Requires-Dist: openpyxl>=3.1 ; extra == 'dev'
Requires-Dist: pandas>=2.0 ; extra == 'dev'
Requires-Dist: rapcsv>=0.2 ; extra == 'dev'
Requires-Dist: rapfiles>=0.1 ; extra == 'dev'
Requires-Dist: rapsqlite>=0.1 ; extra == 'dev'
Requires-Dist: snowflake-connector-python>=3.0 ; extra == 'dev'
Requires-Dist: sphinx ; extra == 'docs'
Requires-Dist: myst-parser ; extra == 'docs'
Requires-Dist: sphinx-autodoc-typehints ; extra == 'docs'
Requires-Dist: sphinx-copybutton ; extra == 'docs'
Requires-Dist: sphinx-rtd-theme ; extra == 'docs'
Requires-Dist: sqlalchemy>=2.0,<3 ; extra == 'docs'
Requires-Dist: openpyxl>=3.1 ; extra == 'excel'
Requires-Dist: pyarrow>=14.0 ; extra == 'io'
Requires-Dist: polars>=1.0.0,<2 ; extra == 'io'
Requires-Dist: kafka-python>=2.0 ; extra == 'kafka'
Requires-Dist: pandas>=2.0 ; extra == 'pandas'
Requires-Dist: polars>=1.0.0,<2 ; extra == 'polars'
Requires-Dist: rapcsv>=0.2 ; extra == 'rap'
Requires-Dist: rapfiles>=0.1 ; extra == 'rap'
Requires-Dist: rapsqlite>=0.1 ; extra == 'rap'
Requires-Dist: snowflake-connector-python>=3.0 ; extra == 'snowflake'
Requires-Dist: sqlalchemy>=2.0,<3 ; extra == 'sql'
Provides-Extra: arrow
Provides-Extra: benchmark
Provides-Extra: bq
Provides-Extra: cloud
Provides-Extra: dev
Provides-Extra: docs
Provides-Extra: excel
Provides-Extra: io
Provides-Extra: kafka
Provides-Extra: pandas
Provides-Extra: polars
Provides-Extra: rap
Provides-Extra: snowflake
Provides-Extra: sql
License-File: LICENSE.md
Summary: Strongly-typed DataFrames for Python, powered by Rust.
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# PydanTable

[![CI](https://github.com/eddiethedean/pydantable/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/eddiethedean/pydantable/actions/workflows/ci.yml?query=branch%3Amain)
[![Documentation](https://readthedocs.org/projects/pydantable/badge/?version=latest)](https://pydantable.readthedocs.io/en/latest/)
[![PyPI version](https://img.shields.io/pypi/v/pydantable)](https://pypi.org/project/pydantable/)
[![Python versions](https://img.shields.io/pypi/pyversions/pydantable)](https://pypi.org/project/pydantable/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

Typed DataFrame workflows for Python services, with Pydantic schemas and a Rust execution core.

## Why PydanTable

- Define table shape once using Pydantic types.
- Catch many errors early with typed expressions.
- Use familiar DataFrame operations (`select`, `filter`, `join`, `group_by`, windows).
- Materialize as row models or `dict[str, list]`, depending on API needs.
- Fit cleanly into FastAPI request/response flows.

## Install

```bash
pip install pydantable
```

Common extras:

```bash
pip install "pydantable[polars]"  # to_polars
pip install "pydantable[arrow]"   # to_arrow / Arrow constructors
pip install "pydantable[io]"      # full file I/O convenience (arrow + polars)
pip install "pydantable[sql]"     # fetch_sql / write_sql helpers
```

## Quick start

```python
from pydantable import DataFrameModel

class User(DataFrameModel):
    id: int
    age: int | None

df = User({"id": [1, 2], "age": [20, None]})
result = (
    df.with_columns(age2=df.age * 2)
      .filter(df.age > 10)
      .select("id", "age2")
)

print(result.to_dict())   # {'id': [1], 'age2': [40]}
print(result.collect())   # list of Pydantic row models
```

## Core concepts

- `DataFrameModel`: SQLModel-like table class (`class Orders(DataFrameModel): ...`).
- `DataFrame[Schema]`: generic API over your own Pydantic `BaseModel`.
- `Expr`: typed expressions used in transforms.
- Static typing:
  - **mypy** can infer schema-evolving return types for many transform chains (via the mypy plugin).
  - **pyright/Pylance** relies on shipped stubs; use `as_model(...)` / `try_as_model(...)` / `assert_model(...)` when you want an explicit after-schema model.
- **1.2.0 column types** (`typing.Literal[...]`, `ipaddress` IPv4/IPv6, `WKB`, `Annotated[str, ...]`) are documented in [SUPPORTED_TYPES](https://pydantable.readthedocs.io/en/latest/SUPPORTED_TYPES.html) (including `Expr` comparison notes).
- Materialization:
  - `collect()` -> list of row models
  - `to_dict()` -> `dict[str, list]`
  - `to_polars()` / `to_arrow()` with matching extras installed

## I/O at a glance

- Lazy file pipelines: `read_*` / `aread_*` -> transform -> `write_*`
- Eager reads: `materialize_*`, `fetch_sql`, `fetch_*_url`
- Eager writes: `export_*`, `write_sql`
- Full I/O API is in `pydantable.io`

## Validation controls

- Strict by default on constructors.
- Optional ingest controls: `trusted_mode`, `ignore_errors`, `on_validation_errors`.
- Missing optional fields are controlled by `fill_missing_optional` (default `True`).

## Documentation

- Docs home: [pydantable.readthedocs.io](https://pydantable.readthedocs.io/en/latest/)
- Quickstart: [QUICKSTART](https://pydantable.readthedocs.io/en/latest/QUICKSTART.html)
- DataFrameModel guide: [DATAFRAMEMODEL](https://pydantable.readthedocs.io/en/latest/DATAFRAMEMODEL.html)
- I/O overview: [IO_OVERVIEW](https://pydantable.readthedocs.io/en/latest/IO_OVERVIEW.html)
- FastAPI patterns: [FASTAPI](https://pydantable.readthedocs.io/en/latest/FASTAPI.html)
- Behavioral contract: [INTERFACE_CONTRACT](https://pydantable.readthedocs.io/en/latest/INTERFACE_CONTRACT.html)
- Versioning policy: [VERSIONING](https://pydantable.readthedocs.io/en/latest/VERSIONING.html)
- Changelog: [changelog](https://pydantable.readthedocs.io/en/latest/changelog.html)

## Development

```bash
make check-full
```

Contributor setup and release workflow: [DEVELOPER](https://pydantable.readthedocs.io/en/latest/DEVELOPER.html)

## License

MIT

