Metadata-Version: 2.4
Name: waveium
Version: 0.2.4
Summary: Official Python SDK for the Waveium API
Project-URL: Homepage, https://waveium.io
Project-URL: Documentation, https://docs.waveium.io
Project-URL: Repository, https://github.com/waveium/waveium-sdk
Author: Waveium Team
License: MIT
License-File: LICENSE
Keywords: api,environment,execution,rf-simulation,scene,sdk,waveium
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
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 :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.9
Requires-Dist: anyio>=4.0.0
Requires-Dist: httpx>=0.27.0
Requires-Dist: pydantic>=2.0.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: typing-extensions>=4.9.0
Provides-Extra: dev
Requires-Dist: black>=24.0.0; extra == 'dev'
Requires-Dist: flake8>=7.0.0; extra == 'dev'
Requires-Dist: mypy>=1.8.0; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23.0; extra == 'dev'
Requires-Dist: pytest>=8.0.0; extra == 'dev'
Provides-Extra: parquet
Requires-Dist: pandas>=2.0.0; extra == 'parquet'
Requires-Dist: pyarrow>=14.0.0; extra == 'parquet'
Description-Content-Type: text/markdown

# Waveium Python SDK

Official Python client library for the Waveium API.

## Current Status

The SDK is fully functional for simulation management. File upload/download endpoints are implemented in the SDK but not yet available on the server (they return 404/405 errors). The SDK is production-ready and will work automatically once these endpoints are deployed.

## Features

- Full support for Waveium API simulation endpoints
- File upload/download implementation (ready for when endpoints are deployed)
- Both synchronous and asynchronous clients
- Type-safe with Pydantic models
- Automatic 3-step file upload workflow
- Batch file downloads
- Environment variable configuration (supports WAVEIUM_API_KEY and WAVEIUM_SDK_TOKEN)
- Comprehensive error handling

## Installation

```bash
pip install waveium
```

For development:

```bash
pip install waveium[dev]
```

## Quick Start

### Using an API Key

```python
import waveium

# Initialize with API key
client = waveium.init(api_key="wvx_your_api_key_here")

# Create a simulation
simulation = client.simulations.create(
    name="My First Simulation",
    parameters={"param1": "value1"}
)

print(f"Created simulation: {simulation.simulation_id}")

# Upload a file
client.files.upload(
    simulation_id=simulation.simulation_id,
    file_path="./input_data.json",
    subdir="Assets"
)

# List files
files = client.files.list(simulation.simulation_id)
for file in files.files:
    print(f"File: {file.filename} ({file.file_size_bytes} bytes)")

# Download a file
client.files.download(
    simulation_id=simulation.simulation_id,
    file_id=files.files[0].file_id,
    destination="./downloaded_file.json"
)
```

### Using Firebase Authentication

```python
import waveium

# Exchange Firebase JWT for API key
client = waveium.auth(
    firebase_token="your_firebase_jwt_token",
    token_name="My Python App"
)

# Use client as normal
simulation = client.simulations.create(name="Test Simulation")
```

### Using Environment Variables

Create a `.env` file:

```env
WAVEIUM_API_KEY=wvx_your_api_key_here
```

Then use without arguments:

```python
import waveium

client = waveium.init()  # Automatically loads from environment
```

## Async Support

The SDK provides full async support:

```python
import asyncio
import waveium

async def main():
    async with waveium.AsyncClient(api_key="wvx_...") as client:
        # Create simulation
        simulation = await client.simulations.create(
            name="Async Simulation"
        )

        # Upload file
        await client.files.upload(
            simulation_id=simulation.simulation_id,
            file_path="./data.json"
        )

        # List and download files
        files = await client.files.list(simulation.simulation_id)
        for file in files.files:
            await client.files.download(
                simulation_id=simulation.simulation_id,
                file_id=file.file_id,
                destination=f"./{file.filename}"
            )

asyncio.run(main())
```

## API Reference

### Client Initialization

#### `waveium.init(api_key=None, base_url=None, timeout=None, max_retries=None)`

Initialize a synchronous client with an API key.

**Parameters:**
- `api_key` (str, optional): API key. Falls back to `WAVEIUM_API_KEY` env var
- `base_url` (str, optional): Custom API base URL
- `timeout` (float, optional): Request timeout in seconds (default: 60)
- `max_retries` (int, optional): Max retry attempts (default: 3)

**Returns:** `Client` instance

#### `waveium.auth(firebase_token=None, token_name="Python SDK Token", expires_days=30, ...)`

Initialize a client by exchanging Firebase JWT for an API key.

**Parameters:**
- `firebase_token` (str, optional): Firebase JWT. Falls back to `FIREBASE_TOKEN` env var
- `token_name` (str): Name for the created token
- `expires_days` (int): Token expiration in days (1-365, default: 30)

**Returns:** `Client` instance with API key

### Simulations

#### `client.simulations.create(name=None, parameters=None, template_id=None)`

Create a new GSCM simulation.

**Parameters:**
- `name` (str, optional): Simulation name
- `parameters` (dict, optional): Simulation parameters
- `template_id` (str, optional): Template ID to use

**Returns:** `SimulationResponse` object

```python
simulation = client.simulations.create(
    name="Production Run",
    parameters={
        "duration": 365,
        "model_type": "deterministic"
    }
)
```

### File Operations

#### `client.files.upload(simulation_id, file_path, subdir="Assets", content_type=None)`

Upload a file to a simulation. Handles the complete 3-step workflow automatically.

**Parameters:**
- `simulation_id` (str): Simulation ID
- `file_path` (str | Path): Path to file to upload
- `subdir` (str): Target subdirectory ("Assets" or "Results")
- `content_type` (str, optional): MIME type (auto-detected if not provided)

**Returns:** `CompleteUploadResponse` object

```python
result = client.files.upload(
    simulation_id="sim_123",
    file_path="./model_config.json",
    subdir="Assets"
)
print(f"Uploaded: {result.file_id}")
```

#### `client.files.list(simulation_id, subdir=None)`

List all files in a simulation.

**Parameters:**
- `simulation_id` (str): Simulation ID
- `subdir` (str, optional): Filter by subdirectory ("Assets" or "Results")

**Returns:** `SimulationFileListResponse` object

```python
files = client.files.list("sim_123", subdir="Results")
print(f"Total files: {files.total_files}")
for file in files.files:
    print(f"  {file.filename}: {file.file_size_bytes} bytes")
```

#### `client.files.download(simulation_id, file_id, destination)`

Download a single file from a simulation.

**Parameters:**
- `simulation_id` (str): Simulation ID
- `file_id` (str): File ID
- `destination` (str | Path): Path where to save the file

**Returns:** `Path` object pointing to downloaded file

```python
path = client.files.download(
    simulation_id="sim_123",
    file_id="file_456",
    destination="./results/output.json"
)
print(f"Downloaded to: {path}")
```

#### `client.files.download_batch(simulation_id, destination_dir, subdir=None)`

Download all files from a simulation.

**Parameters:**
- `simulation_id` (str): Simulation ID
- `destination_dir` (str | Path): Directory where to save files
- `subdir` (str, optional): Filter by subdirectory

**Returns:** `BatchDownloadResponse` object

```python
batch = client.files.download_batch(
    simulation_id="sim_123",
    destination_dir="./results/",
    subdir="Results"
)
print(f"Downloaded {batch.total_files} files")
```

### Authentication

#### `client.auth.create_token(name, expires_days=30, firebase_token=None)`

Create a new API token from Firebase JWT.

```python
response = client.auth.create_token(
    name="My Application Token",
    expires_days=90
)
print(f"New API key: {response.api_key}")
```

#### `client.auth.list_tokens()`

List all API tokens for the current user.

```python
tokens = client.auth.list_tokens()
for token in tokens.tokens:
    print(f"{token.name}: {token.id}")
```

#### `client.auth.revoke_token(token_id)`

Revoke a specific API token.

```python
client.auth.revoke_token("tok_123")
```

## Error Handling

The SDK provides a comprehensive exception hierarchy:

```python
from waveium import (
    WaveiumError,           # Base exception
    AuthenticationError,    # 401 errors
    AuthorizationError,     # 403 errors
    NotFoundError,          # 404 errors
    ValidationError,        # 400 errors
    RateLimitError,         # 429 errors
    APIError,               # 5xx errors
    NetworkError,           # Network failures
    FileUploadError,        # Upload failures
    FileDownloadError,      # Download failures
    ConfigurationError,     # Configuration issues
)

try:
    simulation = client.simulations.create(name="Test")
except AuthenticationError as e:
    print(f"Authentication failed: {e}")
except ValidationError as e:
    print(f"Invalid request: {e}")
    print(f"Error code: {e.code}")
    print(f"Details: {e.details}")
except WaveiumError as e:
    print(f"Waveium error: {e}")
```

## Configuration

### Environment Variables

- `WAVEIUM_API_KEY`: API key for authentication
- `FIREBASE_TOKEN`: Firebase JWT token for authentication
- `WAVEIUM_BASE_URL`: Custom API base URL
- `WAVEIUM_TIMEOUT`: Request timeout in seconds
- `WAVEIUM_MAX_RETRIES`: Maximum retry attempts

### Custom Configuration

```python
client = waveium.init(
    api_key="wvx_...",
    base_url="https://custom-api.example.com",
    timeout=120.0,
    max_retries=5
)
```

## Examples

See the `examples/` directory for complete working examples:

- `basic_usage.py` - Basic synchronous usage
- `async_usage.py` - Asynchronous operations
- `upload_download.py` - File operations workflow

## Development

### Setup

```bash
cd python313
pip install -e ".[dev]"
```

### Code Quality

```bash
# Format code
black src/

# Lint
flake8 src/

# Type check
mypy src/
```

### Testing

```bash
pytest
```

## License

MIT License

## Support

- Documentation: https://docs.waveium.io
- Issues: https://github.com/waveium/waveium-sdk/issues
- Email: support@waveium.io
