Metadata-Version: 2.3
Name: ineepy
Version: 0.4.1
Summary: A Python client library for the [ineep](https://codeberg.org/cmts/ineep) lakehouse API.
Author: cmts
Author-email: cmts <cmts@noreply.codeberg.org>
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.13.4
Requires-Dist: pydantic-settings>=2.14.1
Requires-Python: >=3.12
Description-Content-Type: text/markdown

# ineepy

[![status-badge](https://woodpecker-ineep.exe.xyz:8000/api/badges/4/status.svg)](https://woodpecker-ineep.exe.xyz:8000/repos/4)
[![PyPI version](https://img.shields.io/pypi/v/ineepy.svg)](https://pypi.org/project/ineepy/)

A Python client library for the [ineep](https://codeberg.org/cmts/ineep) lakehouse API — typed models, sync and async clients, streaming uploads/downloads, and ETag-based caching.

## Links

- **Repository:** [codeberg.org/Ineep/ineepy](https://codeberg.org/Ineep/ineepy)
- **Documentation:** [ineep.codeberg.page/ineepy/](https://ineep.codeberg.page/ineepy/)
- **Changelog:** [CHANGELOG.md](CHANGELOG.md)

## Requirements

- Python 3.12+
- [`uv`](https://docs.astral.sh/uv/)

## Installation

```bash
uv add ineepy
```

Or for development:

```bash
git clone https://codeberg.org/Ineep/ineepy
cd ineepy
uv sync
```

## Authentication

Exchange your credentials for a JWT token once — by default it is saved
to `ineepy.toml` in the current directory, so clients can be constructed
with no arguments afterwards:

```python
from ineepy import Ineepy, get_token

# One-time: saves base_url, api_path and token to ./ineepy.toml
get_token('user@example.com', 'secret',
          base_url='https://lakehouse.example.com')

client = Ineepy()  # picks up ineepy.toml
```

Or keep the token in your hands and pass it explicitly:

```python
token = get_token('user@example.com', 'secret', save_token=False)
client = Ineepy(token=token)
```

`scopes` accepts a single scope name or an iterable of names and
defaults to `'user'`; request `'admin'` for administrative operations.
An async variant, `async_get_token`, mirrors `get_token` exactly.

## Quickstart

```python
from ineepy import Ineepy

with Ineepy() as client:
    user, etag = client.users.get('me')
    namespaces = client.namespaces.list()
    tables = client.tables.list('raw')
```

The same API is available asynchronously:

```python
from ineepy import AsyncIneepy

async with AsyncIneepy() as client:
    user, etag = await client.users.get('me')
    namespaces = await client.namespaces.list()
    tables = await client.tables.list('raw')
```

## Working with data

Upload streams file-like objects straight from disk, query returns
typed JSON rows, and large results stream directly to a file:

```python
with Ineepy() as client:
    # Streaming upload from an open file
    with open('orders.parquet', 'rb') as f:
        client.data.upload('raw.sales.orders', f, 'parquet')

    # JSON query with filters
    result = client.data.query('raw.sales.orders',
                               filters='country:eq:BR')
    print(result.items)

    # Large results: submit as parquet, stream to disk
    job_id = client.data.submit_query('raw.sales.orders',
                                      format='parquet')
    client.data.poll_download_to(job_id, 'result.parquet')
```

Explicit write modes (`append`, `overwrite`, `upsert`), row deletion,
cross-table queries with joins, and job monitoring are covered in the
[data documentation](https://ineep.codeberg.page/ineepy/resources/data/).

## Configuration

Settings are resolved in priority order: constructor arguments →
`ineepy.toml` in the current directory → `INEEPY_*` environment
variables.

| Environment variable | Default | Description |
|---|---|---|
| `INEEPY_BASE_URL` | `https://ineep-lakehouse-prod.exe.xyz` | API base URL |
| `INEEPY_API_PATH` | `/api/v0` | API path prefix |
| `INEEPY_TOKEN` | (empty) | Bearer token |

```python
client = Ineepy(base_url='https://my-server.example.com', token=token)
```

## Error handling

Every failure raises a subclass of `ineepy.exceptions.IneepyError`:

```python
from ineepy.exceptions import NotFoundError

try:
    table, etag = client.tables.get_metadata('raw.sales.ghost')
except NotFoundError as e:
    print(f'missing table: {e}')
```

Concurrent updates are guarded by ETags — a stale `etag` raises
`PreconditionFailedError` instead of silently overwriting.

## Resources

| Resource | Access | Description |
|---|---|---|
| [`users`](https://ineep.codeberg.page/ineepy/resources/users/) | `client.users` | User management (list, get, create, update, delete) |
| [`api_keys`](https://ineep.codeberg.page/ineepy/resources/api-keys/) | `client.api_keys` | API key management (create, list, revoke) |
| [`namespaces`](https://ineep.codeberg.page/ineepy/resources/namespaces/) | `client.namespaces` | Namespace management; `list()` with no arg returns root namespaces |
| [`tables`](https://ineep.codeberg.page/ineepy/resources/tables/) | `client.tables` | Table schema and metadata management within namespaces |
| [`data`](https://ineep.codeberg.page/ineepy/resources/data/) | `client.data` | Upload, JSON/parquet/csv queries, cross-table queries, streaming transfers, write modes (`append`, `overwrite`, `upsert`) |

## Documentation

- [Getting started](https://ineep.codeberg.page/ineepy/getting-started/)
- Guides: [Create an API key](https://ineep.codeberg.page/ineepy/guides/create-api-key/) · [Create a table](https://ineep.codeberg.page/ineepy/guides/create-table/) · [Data pipeline](https://ineep.codeberg.page/ineepy/guides/data-pipeline/)
- [API reference](https://ineep.codeberg.page/ineepy/api-reference/)

## Development

```bash
make format   # format code
make lint     # lint and type-check code
make test     # run unit tests with coverage
make test-e2e # run end-to-end tests against a live server
make docs     # validate doc snippets against a live server, build site
```

### E2E tests

E2E tests require a running ineep server and admin credentials:

```bash
cp .env.example .env
# edit .env with your credentials
make test-e2e
```

The `.env` file is gitignored. See `.env.example` for the available variables.

## Project structure

```
src/ineepy/          Main package
  _auth.py           Token acquisition (sync + async)
  _client.py         Ineepy and AsyncIneepy clients
  _config.py         Pydantic settings (env vars)
  _exceptions.py     Exception hierarchy
  _models.py         Pydantic request/response models
  exceptions.py      Public exceptions re-export
  helpers.py         Public helper utilities
  models.py          Public models re-export
  _resources/        Per-resource implementations
    api_keys.py
    data.py
    namespaces.py
    tables.py
    users.py
tests/
  resources/         Unit tests per resource
  e2e/               End-to-end workflow tests
scripts/             Shell scripts called by make
pyproject.toml       Project metadata and tool config
```

## License

This project is licensed under the GNU General Public License v3.0.

You are free to use, modify, and distribute this software under the terms of the GPL v3. Any derivative work must also be distributed under the same license. See the LICENSE file for the full license text.
