Metadata-Version: 2.4
Name: moltres
Version: 1.1.0
Summary: DataFrame API with SQL pushdown execution and real SQL CRUD - the missing layer for SQL in Python
Author-email: Odos Matthews <odosmatthews@gmail.com>
License: MIT License
Project-URL: Homepage, https://github.com/eddiethedean/moltres
Project-URL: Repository, https://github.com/eddiethedean/moltres
Project-URL: Issues, https://github.com/eddiethedean/moltres/issues
Keywords: dataframe,sql,crud,pushdown,etl,data-engineering,sqlalchemy,pandas,polars,spark,database,query-builder
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: SQLAlchemy>=2.0
Requires-Dist: typing-extensions>=4.5
Requires-Dist: moltres-core<2,>=1.1.0
Provides-Extra: polars
Requires-Dist: polars>=1.0; extra == "polars"
Provides-Extra: pandas
Requires-Dist: pandas>=2.1; extra == "pandas"
Provides-Extra: sqlmodel
Requires-Dist: sqlmodel>=0.0.14; extra == "sqlmodel"
Provides-Extra: django
Requires-Dist: django>=3.2; extra == "django"
Provides-Extra: streamlit
Requires-Dist: streamlit>=1.28.0; extra == "streamlit"
Provides-Extra: airflow
Requires-Dist: apache-airflow>=3.0.0; (python_version >= "3.10" and platform_system != "Windows") and extra == "airflow"
Provides-Extra: prefect
Requires-Dist: prefect>=2.0.0; extra == "prefect"
Provides-Extra: dbt
Requires-Dist: dbt-core>=1.5.0; extra == "dbt"
Provides-Extra: async
Requires-Dist: aiofiles>=23.0; extra == "async"
Requires-Dist: greenlet>=3.0.0; extra == "async"
Provides-Extra: async-postgresql
Requires-Dist: aiofiles>=23.0; extra == "async-postgresql"
Requires-Dist: asyncpg>=0.29.0; extra == "async-postgresql"
Requires-Dist: greenlet>=3.0.0; extra == "async-postgresql"
Provides-Extra: async-mysql
Requires-Dist: aiofiles>=23.0; extra == "async-mysql"
Requires-Dist: aiomysql>=0.2.0; extra == "async-mysql"
Requires-Dist: greenlet>=3.0.0; extra == "async-mysql"
Provides-Extra: async-sqlite
Requires-Dist: aiofiles>=23.0; extra == "async-sqlite"
Requires-Dist: aiosqlite>=0.19.0; extra == "async-sqlite"
Requires-Dist: greenlet>=3.0.0; extra == "async-sqlite"
Provides-Extra: parquet
Requires-Dist: pyarrow>=10.0; extra == "parquet"
Provides-Extra: fastapi
Requires-Dist: fastapi; extra == "fastapi"
Requires-Dist: uvicorn[standard]; extra == "fastapi"
Provides-Extra: duckdb
Requires-Dist: duckdb-engine>=0.9.0; extra == "duckdb"
Provides-Extra: pydantable-integration
Requires-Dist: pydantable>=1.0; extra == "pydantable-integration"
Provides-Extra: dev
Requires-Dist: pytest>=8.0; extra == "dev"
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
Requires-Dist: pytest-cov>=4.1; extra == "dev"
Requires-Dist: pytest-green-light>=0.2.0; extra == "dev"
Requires-Dist: pytest-xdist>=3.5; extra == "dev"
Requires-Dist: mypy>=1.8; extra == "dev"
Requires-Dist: sphinx>=7.0; extra == "dev"
Requires-Dist: sphinx-rtd-theme>=2.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: pre-commit>=3.5; extra == "dev"
Requires-Dist: pandas>=2.1; extra == "dev"
Requires-Dist: pandas-stubs>=2.1; extra == "dev"
Requires-Dist: polars>=1.0; extra == "dev"
Requires-Dist: pyarrow>=10.0; extra == "dev"
Requires-Dist: aiofiles>=23.0; extra == "dev"
Requires-Dist: aiosqlite>=0.19.0; extra == "dev"
Requires-Dist: asyncpg>=0.29.0; extra == "dev"
Requires-Dist: greenlet>=3.0.0; extra == "dev"
Requires-Dist: testing.postgresql>=1.3.0; extra == "dev"
Requires-Dist: testing.mysqld>=1.4.0; extra == "dev"
Requires-Dist: psycopg2-binary>=2.9.0; extra == "dev"
Requires-Dist: pymysql>=1.0.0; extra == "dev"
Requires-Dist: duckdb-engine>=0.9.0; extra == "dev"
Requires-Dist: sqlmodel>=0.0.14; extra == "dev"
Requires-Dist: fastapi>=0.100.0; extra == "dev"
Requires-Dist: uvicorn>=0.23.0; extra == "dev"
Requires-Dist: django>=3.2; extra == "dev"
Requires-Dist: streamlit>=1.28.0; extra == "dev"
Requires-Dist: apache-airflow>=3.0.0; (python_version >= "3.10" and platform_system != "Windows") and extra == "dev"
Requires-Dist: prefect>=2.0.0; extra == "dev"
Requires-Dist: dbt-core>=1.5.0; extra == "dev"

# Moltres

<div align="center">

[![CI](https://github.com/eddiethedean/moltres/actions/workflows/ci.yml/badge.svg)](https://github.com/eddiethedean/moltres/actions/workflows/ci.yml)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://github.com/eddiethedean/moltres)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://github.com/eddiethedean/moltres/blob/main/LICENSE)
[![Documentation Status](https://readthedocs.org/projects/moltres/badge/?version=latest)](https://moltres.readthedocs.io/en/latest/?badge=latest)

**The Missing DataFrame Layer for SQL in Python**

**MOLTRES**: **M**odern **O**perations **L**ayer for **T**ransformations, **R**elational **E**xecution, and **S**QL

</div>

---

**Moltres** combines a DataFrame API (like Pandas/Polars), SQL pushdown execution (no data loading into memory), and real SQL CRUD operations (INSERT, UPDATE, DELETE) in one unified interface. See [why Moltres](docs/WHY_MOLTRES.md) and the [comparison guides](https://moltres.readthedocs.io/en/latest/#comparisons) for how it differs from Pandas, Ibis, and PySpark.

Transform millions of rows using familiar DataFrame operations—all executed directly in SQL without materializing data.

## ✨ Key Features

- 🚀 **PySpark-Style DataFrame API** - High compatibility for core operations; see [migration footguns](docs/PYSPARK_MIGRATION_INCONSISTENCIES.md)
- 🗄️ **SQL Pushdown Execution** - All operations compile to SQL and run on your database
- ✏️ **Real SQL CRUD** - INSERT, UPDATE, DELETE with DataFrame-style syntax
- 🐼 **Pandas & Polars Interfaces** - Optional pandas/polars-style APIs
- ⚡ **Async Support** - Full async/await support for all operations
- 🔒 **Security First** - Built-in SQL injection prevention
- 🎯 **Framework Integrations** - FastAPI, Django, Streamlit, SQLModel, Pydantic

## 📦 Installation

```bash
pip install moltres

# Common optional extras
pip install moltres[pandas,polars]     # Pandas/Polars result formats
pip install moltres[async-postgresql]  # Async PostgreSQL
pip install moltres[parquet,duckdb,fastapi]  # File I/O, DuckDB, FastAPI helpers

# Full extras table: docs/PUBLIC_API.md#optional-extras
```

### `moltres-core` and pydantable

SQL execution lives in the companion **`moltres-core`** package. You can use
`MoltresPydantableEngine` with [pydantable](https://pypi.org/project/pydantable/) for a
typed, plan-driven API backed by SQL for supported operations. See
[`docs/PYDANTABLE_ENGINE.md`](docs/PYDANTABLE_ENGINE.md). From source, install
`moltres-core` **before** `moltres`:

```bash
pip install -e ./moltres-core
pip install -e .
```

**1.1.0** ships this split on PyPI: `pip install moltres` pulls in **`moltres-core`** automatically. For breaking changes and upgrade notes, see [CHANGELOG.md](CHANGELOG.md).

### Prerequisites

- **Python 3.10+** (see [Runtime support](docs/RUNTIME_SUPPORT.md))
- **SQLAlchemy 2.0+** (installed automatically with `moltres`)
- **Database driver** for your backend (e.g. `psycopg2-binary` for PostgreSQL, `pymysql` for MySQL; SQLite needs no extra driver)
- **Optional extras**: full list in [Public API — Optional extras](docs/PUBLIC_API.md#optional-extras)

## 🚀 Quick Start

**New here?** Start with the [5-minute quick start](https://moltres.readthedocs.io/en/latest/guides/quick-start.html), then the [complete tutorial](https://moltres.readthedocs.io/en/latest/guides/getting-started.html) when you want more depth.

```python
from moltres import col, connect
from moltres.expressions import functions as F
from moltres.io.records import Records
from moltres.table.schema import column

with connect("sqlite:///:memory:") as db:
    db.create_table("orders", [
        column("id", "INTEGER"),
        column("country", "TEXT"),
        column("amount", "REAL"),
    ]).collect()
    Records.from_list([
        {"id": 1, "country": "US", "amount": 100.0},
        {"id": 2, "country": "UK", "amount": 200.0},
    ], database=db).insert_into("orders")

    df = (
        db.table("orders").select()
        .where(col("country") == "US")
        .group_by("country")
        .agg(F.sum(col("amount")).alias("total_amount"))
    )
    print(df.collect())  # [{'country': 'US', 'total_amount': 100.0}]

    # CRUD: update and delete rows
    db.update("orders", where=col("country") == "US", set={"amount": 150.0})
    db.delete("orders", where=col("amount") < 50)
```

For a fuller CRUD walkthrough (separate tables, `Records`, merge), see the [complete tutorial](https://moltres.readthedocs.io/en/latest/guides/getting-started.html#inserting-data).

### Reading Data: Tables vs Files

| Goal | API | Returns |
|------|-----|---------|
| Query a SQL table lazily | `db.table("orders").select()` | `DataFrame` (SQL pushdown) |
| Load a file as a lazy DataFrame | `db.load.csv("data.csv")` | `DataFrame` (materialized via temp table) |
| Load a file as in-memory rows | `db.read.records.csv("data.csv")` | `Records` (eager, for inserts) |

See [Public API guide](docs/PUBLIC_API.md) for stable import paths.

## 📖 Documentation

- **[Roadmap](ROADMAP.md)** - Future 1.x release phases and competitive priorities
- **[Public API](https://moltres.readthedocs.io/en/latest/PUBLIC_API.html)** - Stable imports and I/O patterns

- **[Getting Started Guide](https://moltres.readthedocs.io/en/latest/guides/quick-start.html)** - 5-minute quick start (start here)
- **[Complete Tutorial](https://moltres.readthedocs.io/en/latest/guides/getting-started.html)** - Full step-by-step introduction
- **[Examples](https://moltres.readthedocs.io/en/latest/EXAMPLE_SCRIPTS.html)** - Runnable example scripts
- **[User Guides](https://moltres.readthedocs.io/en/latest/#guides-how-to)** - Complete guides for all features
- **[API Reference](https://moltres.readthedocs.io/en/latest/api/dataframe.html)** - Complete API documentation

### Framework Integrations

- **[FastAPI Integration](https://moltres.readthedocs.io/en/latest/EXAMPLE_SCRIPTS.html)** - See `docs/examples/22_fastapi_integration.py`
- **[Django Integration](https://moltres.readthedocs.io/en/latest/guides/django-integration.html)**
- **[Streamlit Integration](https://moltres.readthedocs.io/en/latest/guides/streamlit-integration.html)**
- **[SQLModel & Pydantic](https://moltres.readthedocs.io/en/latest/guides/sqlmodel-integration.html)** - Type-safe models

## 🛠️ Supported Operations

**DataFrame Operations**: `select()`, `where()`, `join()`, `group_by()`, `agg()`, `order_by()`, `limit()`, `distinct()`, `pivot()`, and more

**130+ Functions**: Mathematical, string, date/time, aggregate, window, array, JSON, and utility functions

**SQL Dialects**: SQLite, PostgreSQL, MySQL, and DuckDB are CI-tested; other SQLAlchemy-supported databases are best-effort (see [Runtime support](docs/RUNTIME_SUPPORT.md))

**UX Features**: Enhanced SQL display (`show_sql()`, `sql` property), query plan visualization (`plan_summary()`, `visualize_plan()`), schema discovery (`db.schema()`, `db.tables()`), query validation (`validate()`), performance hints (`performance_hints()`), and interactive help (`help()`, `suggest_next()`)

## 🧪 Development

From a git checkout, install **`moltres-core` before `moltres`** (the monorepo ships two packages):

```bash
pip install -e ./moltres-core
pip install -e ".[dev]"

# Run lint/type/doc-example checks (does NOT run the test suite)
make ci-check

# Run tests (matches CI main matrix)
PYTEST_DISABLE_PLUGIN_AUTOLOAD=1 pytest -p pytest_asyncio.plugin -p xdist.plugin \
  -m "not postgres and not mysql and not multidb and not tier2_integration and not tier3_integration" \
  -n auto --dist loadgroup
```

## 🤝 Contributing

Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## 📄 License

MIT License - see [LICENSE](https://github.com/eddiethedean/moltres/blob/main/LICENSE) file for details.

---

<div align="center">

**Made with ❤️ for the Python data community**

[⬆ Back to Top](#moltres)

</div>
