Metadata-Version: 2.5
Name: hydopt-client
Version: 0.0.5
Summary: Python client for the HydOpt hydropower optimization API
Requires-Python: >=3.13
Requires-Dist: google-auth>=2.56.3
Requires-Dist: httpx>=0.28.1
Requires-Dist: pydantic>=2.13.4
Requires-Dist: requests>=2.34.2
Description-Content-Type: text/markdown

# hydopt-client

Python client for the [HydOpt](https://hydopt.io) hydropower optimization API.

## Install

```bash
uv add hydopt-client
```

## Authentication

Every provider implements `TokenProvider` and plugs into the client via `Client(token_provider=...)`. The default is `ServiceAccountTokenProvider` targeting `WEB_CLIENT_ID`, the OAuth client id the HydOpt API accepts as token audience.

**Local development** — mint an ID token from a service account key:

```python
from hydopt_client.auth import WEB_CLIENT_ID, ServiceAccountTokenProvider
from hydopt_client.client import Client

client = Client(
    token_provider=ServiceAccountTokenProvider(
        audience=WEB_CLIENT_ID,
        key_path="/path/to/sa-key.json",
    )
)
```

Create the key in Google Cloud Console (*IAM & Admin → Service Accounts → Keys*, project `hydopt`) or with:

```bash
gcloud iam service-accounts keys create ~/.config/gcloud/hydopt-sa.json \
    --iam-account <SA_EMAIL> --project hydopt
```

If `key_path` is omitted, credentials are resolved through Application Default Credentials. Locally, point `GOOGLE_APPLICATION_CREDENTIALS` at your key file before running:

```bash
export GOOGLE_APPLICATION_CREDENTIALS=$HOME/.config/gcloud/hydopt-sa.json
uv run streamlit run examples/streamlit_app.py
```

Note: end-user credentials from `gcloud auth application-default login` do **not** work for this flow — use a service account key. Keep the key file outside any git repository.

**Deployed on Cloud Run** — mints a service-to-service ID token for `WEB_CLIENT_ID` via the metadata server (no key file needed). Only without a configured audience does it forward the IAP JWT injected into the incoming request — such forwarded tokens carry this app's own IAP client id as audience and are only accepted by APIs that explicitly trust it:

```python
from hydopt_client.auth import WEB_CLIENT_ID
from hydopt_client.auth.iap import CloudRunIAPTokenProvider  # requires streamlit

client = Client(token_provider=CloudRunIAPTokenProvider(audience=WEB_CLIENT_ID))
```

The bundled example app picks automatically: `CloudRunIAPTokenProvider` when it detects it runs on Cloud Run (`K_SERVICE` env var), `ServiceAccountTokenProvider` otherwise.

## Quick Start

```python
from hydopt_client.client import Client

client = Client()

# List available partition dates
dates = client.list_partitions()
print(dates)  # ["2026-01-01", "2026-01-02", ...]

# Fetch a time series
records = client.series(dates[0], "production")
for record in records:
    print(record.name, record.x[0], record.y[0])

# Filter and group results
from hydopt_client.client import Filters, GroupBy

filtered = client.series(
    dates[0],
    "production",
    filters=Filters(country=["norway"]),
    group_by=[GroupBy.region],
)
```

## Available Methods

| Method | Description |
|--------|-------------|
| `list_partitions()` | List available partition dates |
| `series(asof, category1, ...)` | Query time-series data |
| `diff(category1, from, to, ...)` | Compare two partitions |
| `static(category1, ...)` | Query static dataset |
| `realized(category1, ...)` | Query realized dataset |
| `catchments(asof)` | Fetch catchment geometries |
| `orders(asof)` | Fetch energy orders |
| `object_report(source, target)` | Compare two partition objects |
