Skip to main content

Python SDK

The official Gumnut Python SDK provides a Pythonic interface to the Gumnut API with full type hints support for better IDE experience.

Installation

pip install gumnut
# or
poetry add gumnut

Quick Start

from gumnut import Gumnut
import os

client = Gumnut(
    api_key=os.environ.get("GUMNUT_API_KEY")
)

# Upload an asset
with open('photo.jpg', 'rb') as f:
    asset = client.assets.create(
        asset_data=f,
        device_asset_id='photo_001',
        device_id='my_device',
        file_created_at='2024-01-01T00:00:00Z',
        file_modified_at='2024-01-01T00:00:00Z'
    )

# Create an album
album = client.albums.create(
    album_name='Vacation 2024',
    description='Summer vacation photos'
)

# Add asset to album
client.albums.add_assets(
    album_id=album.id,
    asset_ids=[asset.id]
)

# Search for assets
results = client.search.query(
    q="sunset beach",
    limit=10
)

Key Features

  • Python 3.8+ Support: Compatible with modern Python versions
  • Type Hints: Full type annotations for better IDE support
  • Async/Await Support: Built-in async client using httpx
  • Automatic Retries: Configurable retry logic with exponential backoff
  • Context Managers: Proper resource handling for file operations
  • Comprehensive Error Handling: Detailed exception types

Async Support

Use the async client for better performance:
import asyncio
from gumnut import AsyncGumnut

async def main():
    client = AsyncGumnut(
        api_key=os.environ.get("GUMNUT_API_KEY")
    )
    
    # Async operations
    assets = await client.assets.list()
    albums = await client.albums.list()
    
    # Process results concurrently
    tasks = [
        client.assets.get(asset.id) 
        for asset in assets[:5]
    ]
    detailed_assets = await asyncio.gather(*tasks)
    
    await client.aclose()  # Clean up

asyncio.run(main())

File Uploads

Multiple ways to handle file uploads:
# File object
with open('photo.jpg', 'rb') as f:
    asset = client.assets.create(
        asset_data=f,
        device_asset_id='unique_id',
        device_id='my_device'
    )

# Bytes
with open('photo.jpg', 'rb') as f:
    data = f.read()
    asset = client.assets.create(
        asset_data=data,
        device_asset_id='unique_id',
        device_id='my_device'
    )

# Path string (automatically opens file)
asset = client.assets.create(
    asset_data='photo.jpg',
    device_asset_id='unique_id',
    device_id='my_device'
)

Configuration

from gumnut import Gumnut

client = Gumnut(
    api_key="your_api_key",
    max_retries=3,
    timeout=60.0,
    base_url="https://api.gumnut.ai"  # Usually not needed
)

Error Handling

from gumnut import APIError, RateLimitError

try:
    asset = client.assets.get('invalid_id')
except RateLimitError as e:
    print(f"Rate limited. Retry after: {e.retry_after}s")
except APIError as e:
    print(f"API Error: {e.status_code} - {e.message}")
    print(f"Request ID: {e.request_id}")

Pagination

Handle large result sets easily:
# Automatic pagination
all_assets = []
for page in client.assets.list_pages():
    all_assets.extend(page.assets)
    if len(all_assets) >= 1000:  # Limit if needed
        break

# Manual pagination
page1 = client.assets.list(limit=50)
page2 = client.assets.list(limit=50, offset=50)

# Async pagination
async for page in client.assets.list_pages_async():
    for asset in page.assets:
        await process_asset(asset)

Repository & Documentation

GitHub Repository: github.com/gumnut-ai/photos-sdk-python For complete API documentation, examples, and advanced usage:

Common Use Cases

Batch Upload

import os
from pathlib import Path

def upload_directory(directory_path):
    photos = Path(directory_path).glob('*.{jpg,jpeg,png,heic}')
    
    for photo in photos:
        with open(photo, 'rb') as f:
            asset = client.assets.create(
                asset_data=f,
                device_asset_id=str(photo.stem),
                device_id='batch_uploader',
                file_created_at=photo.stat().st_ctime,
                file_modified_at=photo.stat().st_mtime
            )
        print(f"Uploaded: {photo.name} -> {asset.id}")

Data Analysis

import pandas as pd

# Get all assets with metadata
assets = client.assets.list(limit=1000)

# Convert to DataFrame for analysis
df = pd.DataFrame([{
    'id': asset.id,
    'created_at': asset.created_at,
    'camera_make': asset.exif_info.get('make'),
    'camera_model': asset.exif_info.get('model'),
    'has_faces': len(asset.faces) > 0
} for asset in assets])

# Analyze by camera
camera_stats = df.groupby(['camera_make', 'camera_model']).size()
print(camera_stats)

Next Steps

I