Metadata-Version: 2.3
Name: tonbo
Version: 0.1.0
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Implementation :: PyPy
Requires-Dist: pytest ; extra == 'test'
Requires-Dist: pytest-asyncio ; extra == 'test'
Requires-Dist: pytest ; extra == 'bench'
Requires-Dist: pytest-asyncio ; extra == 'bench'
Requires-Dist: pytest-benchmark ; extra == 'bench'
Requires-Dist: duckdb ; extra == 'bench'
Requires-Dist: pdoc ; extra == 'docs'
Provides-Extra: test
Provides-Extra: bench
Provides-Extra: docs
Summary: Tonbo Python Binding
License: Apache-2.0
Requires-Python: >=3.10
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
Project-URL: Source Code, https://github.com/tonbo-io/tonbo

# Tonbo Python Binding

This package intends to build a native python binding for [Tonbo](https://github.com/tonbo-io/tonbo).

Tonbo's Python bindings can be used to build data-intensive applications, including other types of databases.

## Example

```py
from tonbo import DbOption, Column, DataType, Record, TonboDB, Bound
from tonbo.fs import from_filesystem_path
import asyncio
import os

# define a Tonbo record
@Record
class User:
    age = Column(DataType.Int8, name="age", primary_key=True)
    height = Column(DataType.Int16, name="height", nullable=True)
    weight = Column(DataType.Int8, name="weight", nullable=False)

async def main():

    if not os.path.exists("db_path/users"):
        os.makedirs("db_path/users")
    db = TonboDB(DbOption(from_filesystem_path("db_path/users")), User())

    await db.insert(User(age=18, height=175, weight=60))
    record = await db.get(18)
    assert record == {"age": 18, "height": 175, "weight": 60}

    txn = await db.transaction()
    txn.insert(User(age=19, height=195, weight=75))
    result = await txn.get(19)
    assert result == {"age": 19, "height": 195, "weight": 75}

    # commit transaction
    await txn.commit()

    txn = await db.transaction()
    # range scan, supports pushing down and limit
    scan = await txn.scan(
        Bound.Excluded(18), None, limit=100, projection=["age", "weight"]
    )
    async for record in scan:
        print(record)

asyncio.run(main())
```

See [examples](example/README.md) for more information.

### Roadmap

- Remote storage API mapping and test
- Integrate with other Arrow analytical tools

## Development

This assumes that you have Rust and cargo installed. We use the [pyo3](https://github.com/PyO3/pyo3) to generate a native Python module and use [maturin](https://github.com/PyO3/maturin) to build Rust-based Python packages.

First, follow the commands below to build a new Python virtualenv, and install maturin into the virtualenv using Python's package manager, pip:

```bash
# setup virtualenv
python -m venv .env
# activate venv
source .env/bin/activate

# install maturin
pip install maturin
# build bindings
maturin develop
```

Whenever Rust code changes run:

```bash
maturin develop
```

Run tests:

```bash
maturin develop -E test
python -m pytest
```

