Metadata-Version: 2.4
Name: picopyn
Version: 2.0.0
Summary: Python connector for working with the distributed Picodata database.
Author-email: Asya Lomakina <a.lomakina@picodata.io>, Igor Kuznetsov <i.kuznetsov@picodata.io>, Dmitriy Koltsov <dkoltsov@picodata.io>, Daniil Gorlyakov <d.gorlyakov@picodata.io>
License-Expression: BSD-2-Clause
Project-URL: Source, https://git.picodata.io/core/drivers/picopyn
Project-URL: Documentation, https://picopyn.readthedocs.io/en/stable/
Project-URL: Changelog, https://git.picodata.io/core/drivers/picopyn/-/blob/main/CHANGELOG.md
Keywords: database,picodata
Classifier: Programming Language :: Python :: 3.10
Classifier: Operating System :: OS Independent
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Database
Classifier: Framework :: AsyncIO
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: AUTHORS.md
Requires-Dist: asyncpg==0.30.0
Requires-Dist: typing_extensions<5,>=4.12.2
Requires-Dist: psycopg[binary]==3.3.4
Requires-Dist: msgpack<2,>=1.0.0
Requires-Dist: mmh3<6,>=5.2.1
Provides-Extra: test
Requires-Dist: pytest==8.3.5; extra == "test"
Requires-Dist: pytest-asyncio==0.25.3; extra == "test"
Requires-Dist: ruff==0.11.13; extra == "test"
Requires-Dist: mypy==1.16.0; extra == "test"
Requires-Dist: black==25.1.0; extra == "test"
Provides-Extra: docs
Requires-Dist: mkdocs<2.0,>=1.6; extra == "docs"
Requires-Dist: mkdocs-material; extra == "docs"
Requires-Dist: mkdocstrings[python]; extra == "docs"
Provides-Extra: benchmark
Requires-Dist: numpy==1.24.4; extra == "benchmark"
Requires-Dist: matplotlib==3.8.4; extra == "benchmark"
Requires-Dist: colorama==0.4.6; extra == "benchmark"
Provides-Extra: publish
Requires-Dist: pypi-cleanup; extra == "publish"
Dynamic: license-file

[![Version](https://img.shields.io/pypi/v/picopyn.svg?maxAge=86400)](https://pypi.org/project/picopyn/)
[![Supported Versions](https://img.shields.io/pypi/pyversions/picopyn.svg)](https://pypi.org/project/picopyn)
[![Documentation](https://readthedocs.org/projects/picopyn/badge/?version=stable)](https://picopyn.readthedocs.io)

# Picopyn - Picodata Python driver

**Picopyn** is a Python package for working with the distributed [Picodata](https://picodata.io/en/) database.

**Version compatibility**:
| Picodata version  | Picopyn version   |
| ----------------- | ----------------- |
| >=25.2.1, <25.4.4 | 0.1.1             |
| >=25.4.4, <25.5.1 | 0.2.0             |
| >=25.5.1, <26.1.x | 1.0.0             |
| >=26.1.1, <26.2.x | 2.0.0             |
| 26.2.x            | ⚠️ Unreleased yet |

## Features
* Connection pooling with configurable pool size
* Optional automatic node discovery
* Pluggable load-balancing strategies
* Asynchronous API based on [asyncpg](https://github.com/MagicStack/asyncpg)
    * (async only) Shard-aware routing
    * (async only) Automatic pool membership reconciliation
* Synchronous [DPAPI-compatible](https://peps.python.org/pep-0249/) API based on [psycopg](https://www.psycopg.org/)

## Navigation
* [Installation](#installation)
* [Quickstart](#quickstart)
* [Development](#development)
    * [Docs](#documentation)
    * [Lint](#how-to-write-code)
    * [Test](#how-to-test)
    * [Debug](#how-to-debug)
* [Benchmark](#benchmark)

## Installation

```sh
pip install picopyn
```

Or from source:

```sh
git clone https://git.picodata.io/core/drivers/picopyn.git
cd picopyn
pip install -e .
```

## Quickstart

Async:

```python
import asyncio
from picopyn.asynchronous import Client

async def main():
    # create and connect client to the picodata cluster
    client = Client(dsn="postgresql://admin:pass@localhost:5432")
    await client.connect()

    # execute DDL operations
    await client.execute('''
        CREATE TABLE "warehouse" (id INTEGER NOT NULL, item TEXT NOT NULL, PRIMARY KEY (id)) USING memtx DISTRIBUTED BY (id) OPTION (TIMEOUT = 3.0);
    ''')

    # execute DML/DQL operations
    await client.execute('INSERT INTO "warehouse" VALUES ($1::int, $2::varchar)', 1, "test")
    rows = await client.fetch('SELECT * FROM "warehouse"')
    print(rows)

    await client.close()

asyncio.run(main())
```

Sync:

```python
from picopyn.synchronous import connect

# create and connect to the picodata cluster
with connect("postgresql://admin:pass@localhost:5432") as conn:
    cur = conn.cursor()

    # execute DDL operations
    cur.execute('''
        CREATE TABLE "warehouse" (id INTEGER NOT NULL, item TEXT NOT NULL, PRIMARY KEY (id)) USING memtx DISTRIBUTED BY (id) OPTION (TIMEOUT = 3.0);
    ''')

    # execute DML/DQL operations
    cur.execute('INSERT INTO "warehouse" VALUES (%s, %s)', (1, "test"))
    cur.execute('SELECT * FROM "warehouse"')
    print(cur.fetchall())
```

## Development
For development we use [uv](https://docs.astral.sh/uv/getting-started/installation/) as package manager and [docker compose](https://docs.docker.com/compose/install/) for test environment.

To install development dependencies:
```bash
uv sync --extra test
```

Inside the test container, run the same command to keep dependencies up to date if the image is outdated:
```bash
make shell
# inside the container:
make install
```

### Documentation

The documentation is written in Markdown and built with [MkDocs](https://www.mkdocs.org/) using the [Material theme](https://squidfunk.github.io/mkdocs-material/). API reference is generated automatically from docstrings via [mkdocstrings](https://mkdocstrings.github.io/).

Published documentation is available at **[picopyn.readthedocs.io](https://picopyn.readthedocs.io/en/stable/)**.

Source files are located in the `docs/` directory. To work on docs locally, install the docs dependencies and start the live-reload server:

```bash
uv sync --extra docs
make doc
```

### How to write code

We use several tools to ensure code style and type safety.
* ruff — code style, lint checks and automatic lint fixing
* mypy — static type checking
* black — code formatting

To check code style and static types:
```bash
make lint
```

To automatically fix formatting and style issues:

```bash
make fmt
```

### How to test
We use [docker compose](https://docs.docker.com/compose/install/) for test environment.

Run the general test suite:

```bash
make test
```

or run SSL tests:

```bash
make test-ssl
```

This will:

1. Start required test containers (Picodata cluster and test-runner) using Docker Compose

2. Execute tests using pytest


### How to debug
Do not forget to run the environment via `make env`

For debugging purposes:

1. Open a bash shell in the test container:

```bash
make shell
```

2. For interactive Python (with asyncio support) run inside of container:

```bash
python -m asyncio
```

3. To connect directly to Picodata:

```bash
picodata admin tmp/data/picodata-1-1/admin.sock
```

## Benchmark

Benchmark instructions and usage examples are available [here](benchmark/README.md).
