Metadata-Version: 2.5
Name: annapurna
Version: 0.1.1
Summary: Python SDK for Annapurna Suite: automate projects, block models, points, drillholes, modeling instances and compute jobs.
Author-email: Annapurna Suite <sebastian.avalos@annapurnasuite.com>
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: Other/Proprietary License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Information Analysis
Classifier: Typing :: Typed
Requires-Python: >=3.10
Requires-Dist: pandas>=2.0
Requires-Dist: pyarrow>=14.0
Requires-Dist: requests>=2.31.0
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == 'dev'
Description-Content-Type: text/markdown

# Annapurna Suite Python SDK

Automate your Annapurna workspace from Python: projects, points, block models,
drillholes, surfaces, meshes, modeling instances, sharing and Compute jobs.

```bash
pip install annapurna
```

## Authenticate

Create a key in **Account Settings → API Key**, then keep it out of your code:

```bash
export ANNAPURNA_API_KEY="aps_live_..."          # Windows: setx ANNAPURNA_API_KEY "aps_live_..."
export ANNAPURNA_ENV="prod"      # optional: "prod" (default, api.annapurnasuite.com) or "dev" (dev-api.annapurnasuite.com)
```

```python
import annapurna as ap

client = ap.Client()          # or ap.Client(api_key=..., environment="dev")
print(client.whoami())
```

## Work with a project

```python
proj = client.project("Fireweed")          # client.project() = active project
proj.objects()                             # everything, grouped by kind

# Block models / points ------------------------------------------------------
bm = proj.block_models.read("BM_123", columns=["Easting", "Northing", "Elevation", "Au"])
proj.block_models["BM_123"].clone("BM_123_backup")
proj.block_models.rename("BM_123_backup", "BM_123_v1")
proj.block_models.reblock("BM_123", "BM_123_25m", size=(25, 25, 10), weight_column="Density")
proj.points.upload("Comps_2026", comps_df)                  # refuses to overwrite unless overwrite=True
proj.points.rename_columns("Comps_2026", {"AU": "Au_gpt"})
proj.points.delete("Old_Comps")

# Drillholes ------------------------------------------------------------------
proj.drillholes.list()                       # drillhole projects
proj.drillholes.tables("Fireweed_DH")        # their tables
assays = proj.drillholes.read("Fireweed_DH", "Assays")

# Surfaces & meshes (OBJ) -------------------------------------------------------
proj.meshes.upload("Ore_Shell", "shell.obj")
proj.surfaces.download("Topo_2025", "topo.obj")
```

## Modeling instances

```python
inst = proj.instances
inst.upload("Au_OK", method="kriging", csv="params.csv")    # path, CSV text or DataFrame
result = inst.run("Au_OK", wait=True)                       # blocks until Completed/Failed/Killed
print(result.status, result.run_time)
```

## Compute: evaluate geometries

```python
from annapurna import GeometryMapping as G

proj.evaluate(
    "block_models", "BM_123", attribute="Domain", default_label="WASTE",
    mappings=[G("Ore_Shell", "ORE"), G("Topo_2025", "AIR", geometry_type="surface", side="above")],
)
```

## Share datasets

```python
code = proj.share("block_models", "BM_123")      # give code.access_code and code.password (separately)
client.sharing.preview(access_code, password)
client.project("Target").import_shared(access_code, password)
```

## Inside Annapurna (Project Scripting page)

`ap` is already loaded and works without a key:

```python
ap.list_datasets("block_models")
bm = ap.load("block_models", "BM_123")
ap.save(bm.describe(), "reports/summary.csv")
```

## Errors

Every error derives from `ap.AnnapurnaError`:
`AuthenticationError`, `PermissionDeniedError`, `NotFoundError`, `ConflictError`,
`ValidationError`, `RateLimitError`, `ServerError`, `APIConnectionError`,
`TaskFailedError`, `TaskTimeoutError`.

## Security

* The key is read from the environment, sent only to `base_url` over HTTPS, and never printed.
* Redirects are not followed with the key; file transfers use short-lived signed URLs without the key.
* Names are validated and URL-encoded, so they cannot alter request paths.
* TLS verification cannot be disabled (use `verify="/path/ca.pem"` for corporate proxies).
* Revoke a leaked key immediately in Account Settings.

## Upgrading from 0.0.x

Old flat methods (`client.read_parquet`, `client.upload_points`, `client.run_instance`, …)
still work and print a `DeprecationWarning` that names the new call. `whoami()` now returns
an `Identity` object (dict-style access `me["username"]` still works).
