Metadata-Version: 2.5
Name: knexpy
Version: 1.0.0
Summary: A KnexJS like module for abstracting Python's SQLite
Project-URL: Source, https://github.com/carlossilva2/Knexpy
Project-URL: Documentation, https://knexpy.readthedocs.io
Author-email: Carlos Silva <carlos.miguel.silva@protonmail.com>
License-Expression: GPL-3.0-only
License-File: LICENSE
Keywords: builder,knex,orm,query,sqlite
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
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
Classifier: Topic :: Software Development
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: pychalk
Requires-Dist: typing-extensions; python_version < '3.11'
Provides-Extra: async
Requires-Dist: aiosqlite; extra == 'async'
Provides-Extra: dev
Requires-Dist: aiosqlite; extra == 'dev'
Requires-Dist: mkdocs; extra == 'dev'
Requires-Dist: mkdocstrings[python]; extra == 'dev'
Requires-Dist: mypy; extra == 'dev'
Requires-Dist: pytest; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: ruff; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs; extra == 'docs'
Requires-Dist: mkdocstrings[python]; extra == 'docs'
Description-Content-Type: text/markdown

# Knexpy

<a href="https://github.com/carlossilva2/Knexpy/blob/main/LICENSE" target="blank"><img src="https://img.shields.io/github/license/carlossilva2/Knexpy?style=round-square&color=green" alt="Knexpy License" /></a>
[![Downloads](https://pepy.tech/badge/knexpy)](https://pepy.tech/project/knexpy)
[![Supported Versions](https://img.shields.io/pypi/pyversions/knexpy.svg)](https://pypi.org/project/knexpy)
[![Documentation Status](https://readthedocs.org/projects/knexpy/badge/?version=latest)](https://knexpy.readthedocs.io/en/latest/?badge=latest)
[![Ruff](https://img.shields.io/badge/code%20style-ruff-000000)](https://docs.astral.sh/ruff/)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)

A query builder for SQLite3 based on Knexjs. Knexpy compiles chainable,
parameterized SQL for you, so you never interpolate a value into a query
string.

## Features

- **Fluent query building** — `select`, `from_`, aliases, `distinct`, every
  `where_*` variant, `group_by`/`having`, `order_by` (with `NULLS FIRST/LAST`),
  `limit`/`offset`, joins and subqueries.
- **Aggregates** — `count`, `sum`, `avg`, `min`, `max`.
- **Writes** — `insert`, `insert_or_ignore`, `upsert`, `update`, `delete`,
  and batch `insert_json` (accepts dicts, dataclasses and pydantic models, with
  chunked transactions and a `mapping` hook).
- **Type checking** — `Knex(..., type_check=True)` validates values against
  column types on insert/update.
- **Transactions** — context-manager support, atomic batch inserts, and manual
  `begin`/`commit`/`rollback`.
- **Typed row models** — `db.select(...).as_(User).all()` returns `list[User]`
  from dataclasses or `TypedDict`s.
- **Pagination & inspection** — `paginate()` and `explain()` /
  `explain_query_plan()`.
- **Schema & introspection** — create/alter/drop tables and indexes, `tables`,
  `columns`, `foreign_keys`, and `backup`.
- **Migrations** — a runner (`knexpy migrate` CLI + `Knex.run_migrations`).
- **Hooks** — observe or intercept operations (`before_*`/`after_*` events).
- **Async facade** — `AsyncKnex` reuses the same builder over `aiosqlite`.
- **Connection factories** — `from_connection`, `make_db`, and query logging.

## Installation

```bash
pip install knexpy
```

For the async facade, install the optional extra:

```bash
pip install "knexpy[async]"
```

## Quick start

```python
from Knexpy import Field, Knex

db = Knex(":memory:", type_check=True)  # pass a path to persist to a file

db.table("users", [Field.varchar("name"), Field.integer("age", {"null": True})])
db.insert_json(
    "users",
    [
        {"name": "Ada", "age": 36},
        {"name": "Lin", "age": 45},
        {"name": "Grace", "age": 40},
    ],
)

rows = db.select("id", "name").from_("users").order_by("name").query()
# [{"id": "...", "name": "Ada"}, ...]
```

> When creating a table, `id`, `created_at` and `modified_at` are added
> automatically. `id` is a collision-resistant random hex string.

## Examples

Runnable examples live in [`examples/`](examples/) and cover the full feature
set:

| File | Shows |
|---|---|
| [`quickstart.py`](examples/quickstart.py) | connect, schema, insert, query, CRUD helpers |
| [`query_building.py`](examples/query_building.py) | aliases, aggregates, grouping, nulls ordering, raw SQL |
| [`joins_where.py`](examples/joins_where.py) | joins and every `where_*` clause |
| [`writes.py`](examples/writes.py) | insert, upsert, chunked/mapped inserts, update/delete |
| [`transactions.py`](examples/transactions.py) | context manager, atomic batches, manual control |
| [`schema_introspection.py`](examples/schema_introspection.py) | DDL, introspection, backup |
| [`row_models.py`](examples/row_models.py) | typed rows via `as_(Model)` |
| [`pagination_explain.py`](examples/pagination_explain.py) | `paginate`, `explain` |
| [`hooks.py`](examples/hooks.py) | observing and intercepting operations |
| [`migrations.py`](examples/migrations.py) | versioned schema changes |
| [`async_example.py`](examples/async_example.py) | the `AsyncKnex` facade |
| [`connection_factory.py`](examples/connection_factory.py) | `from_connection`, `make_db`, logging |

You can report bugs and discuss features on the
[GitHub issues page](https://github.com/carlossilva2/Knexpy/issues). For the
full API reference check [Readthedocs](https://knexpy.readthedocs.io/).
