Metadata-Version: 2.4
Name: tupic
Version: 1.0.0
Summary: Official Python SDK for the Tupic Human Data Infrastructure
Project-URL: Homepage, https://tupic.example
Project-URL: Documentation, https://docs.tupic.example/sdk/python
Project-URL: Repository, https://github.com/tupic/tupic-python
Project-URL: Changelog, https://github.com/tupic/tupic-python/blob/main/CHANGELOG.md
Author-email: Tupic <sdk@tupic.example>
License: MIT
License-File: LICENSE
Keywords: assets,datasets,human-data,models,sdk,tupic
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: httpx<1.0,>=0.27
Requires-Dist: pydantic<3.0,>=2.6
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: coverage[toml]>=7.4; extra == 'dev'
Requires-Dist: mypy>=1.9; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: respx>=0.21; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

# Tupic Python SDK

Official Python SDK for the Tupic Human Data Infrastructure. A secure, typed client for discovering and accessing authorized Tupic assets, datasets, models, streams, ownership records, and usage information.

The package is a **client only**: it contains no datasets, model weights, credentials, or large binary assets.

## Installation

```bash
pip install tupic
```

Requires Python 3.10+.

## Five-minute quick start

```python
from tupic import TupicClient

client = TupicClient.from_env()  # reads TUPIC_* environment variables

for asset in client.assets.search(
    tags=["culture", "food"],
    country="AE",
    limit=10,
):
    print(asset.id, asset.uniqueness_score)
```

Environment variables:

```bash
TUPIC_CLIENT_ID=
TUPIC_CLIENT_SECRET=
TUPIC_ACCESS_TOKEN=
TUPIC_API_BASE_URL=
TUPIC_AUTH_BASE_URL=
```

## Authentication

```python
from tupic import TupicClient

# Backend services (client credentials)
client = TupicClient.from_client_credentials(
    client_id="...",
    client_secret="...",
    scopes=["assets:read", "datasets:read", "models:execute", "usage:write"],
)

# Existing access token
client = TupicClient.from_access_token("eyJ...")

# CLI / desktop: device flow via `tupic auth login`, then
client = TupicClient.from_stored_login()
```

Tokens refresh automatically. Credentials are never logged, never included in exceptions, and never appear in object `repr`s.

## Assets

```python
asset = client.assets.get("asset_123")
print(asset.content_type, asset.validation_status, asset.license)
print(asset.provenance)

asset.download("./data/asset_123.jpg", verify_hash=True, resume=True)
```

Downloads stream in chunks, verify checksums, support resume, refuse accidental overwrites, and block path traversal.

## Datasets

```python
dataset = client.datasets.get("dataset_123")
print(dataset.name, dataset.version, dataset.asset_count)

for batch in dataset.iter_samples(split="train", batch_size=32):
    train(batch)
```

## Hosted models

```python
model = client.models.get("model_123")
result = model.predict(input_asset_id="asset_123", parameters={"confidence_threshold": 0.7})

job = client.models.submit_job(model_id="model_123", inputs=["asset_1", "asset_2"])
result = job.wait(timeout=900)
```

## Streaming

```python
with client.streams.open("stream_123") as stream:
    for chunk in stream.iter_bytes(chunk_size=1024 * 1024):
        process(chunk)
```

## Usage attribution

```python
with client.usage.context(project_id="project_123", purpose="research",
                          external_reference="experiment_42"):
    client.models.predict(model_id="model_123", input_asset_id="asset_123")
```

Server-side metering is authoritative; the context attaches attribution headers to every request in the block.

## License checks

```python
info = client.licenses.check(
    resource_type="dataset", resource_id="dataset_123",
    intended_use="commercial_training",
)
if not info.permitted:
    raise RuntimeError(info.reason)
```

API authorization does not imply every intellectual-property or commercial right — check the license before protected use.

## Async

```python
from tupic import AsyncTupicClient

async with AsyncTupicClient.from_env() as client:
    page = await client.assets.search(tags=["culture"], limit=10)
    async for asset in client.assets.iter_all(page_size=100):
        ...
```

## Pagination

```python
page = client.assets.list(limit=100)
print(page.items, page.next_cursor)

for asset in client.assets.iter_all(page_size=100):
    process(asset)
```

Cursors are opaque — never parse or modify them.

## Errors

All errors derive from `tupic.TupicError` and expose `code`, `message`, `status_code`, `correlation_id`, `retry_after`, `retryable`, and `details`. Secrets and signed URLs are never included.

## CLI

```bash
tupic auth login
tupic assets search --tag culture --country AE
tupic models run model_123 --input-asset-id asset_123
tupic usage show --period 2026-07 --json
```

## Documentation

See `docs/` for guides on authentication, asset search, datasets, models, streaming, usage & billing, licensing, error handling, async usage, the CLI reference, and security recommendations. Build and publication instructions are in `docs/publishing.md`. Assumptions pending API confirmation are listed in `ASSUMPTIONS.md`.

## Development

```bash
pip install -e ".[dev]"
pytest
ruff check src tests
mypy
python -m build
```

## Security

See [SECURITY.md](SECURITY.md) for the responsible-disclosure policy.
