Skip to main content

pycomad

Python client library for the Comad DAM (Digital Asset Management) API.

Installation

pip install pycomad

Quick start

from pycomad import ComadClient

client = ComadClient(
    api_url="http://localhost:8080",
    auth_url="http://localhost:8081",   # ullav-user-management service
)
client.login(email="user@example.com", password="secret")

# Upload a file (creates the record and uploads in one step)
asset = client.assets.upload("photo.jpg", creator="alice", is_private=False)

# Or create a record first, then upload the file
record = client.assets.create("Report", "application/pdf")
client.assets.upload_file(record.id, "report.pdf")

# Download and thumbnail
raw_bytes = client.assets.download(asset.id)
thumb_png  = client.assets.thumbnail(asset.id)

# Categories
cat = client.categories.create("Architecture", access_level="Global")
client.assets.add_category(asset.id, cat.id)
detail = client.assets.get(asset.id)   # AssetWithCategories

# Search
results = client.search.search(q="photo", creator="alice")
nearby  = client.search.nearby(lat=53.3, lon=-6.2, radius_km=5)

# Metadata (EXIF / IPTC / XMP)
meta = client.metadata.get(asset.id)
if meta.exif:
    print(meta.exif.get("camera_make"))

# Usage quotas
usage = client.assets.usage()
print(f"{usage.asset_count} assets, {usage.used_bytes // 1024**2} MB used")

# ZIP batch import
result = client.zip.upload("photos.zip", creator="alice")
print(f"Imported {len(result.assets)} assets into {len(result.categories)} categories")

Example: upload a file

Print asset details after uploading a local file:

import os
from pycomad import ComadClient

client = ComadClient(
    api_url=os.environ["COMAD_API_URL"],
    auth_url=os.environ.get("COMAD_AUTH_URL", os.environ["COMAD_API_URL"]),
)
client.login(email=os.environ["COMAD_EMAIL"], password=os.environ["COMAD_PASSWORD"])

asset = client.assets.upload("photo.jpg", creator="alice")
print(f"{asset.name}  ({asset.asset_type}, {asset.size:,} bytes)  id={asset.id}")

A runnable version of this script is at examples/upload_asset.py.

Authentication

ComadClient authenticates against the ullav-user-management service, which issues the JWT accepted by the Comad DAM server.

  • api_url — Comad DAM server base URL (e.g. http://comad-server:8080)
  • auth_url — auth service base URL (e.g. http://ullav-user-management:8081); omit if both services are behind the same proxy

Call client.login(email, password) before any other method. Tokens expire according to the server's configuration; call login() again to refresh.

Resource clients

Attribute Resource
client.assets Asset CRUD, file upload/download/thumbnail, category links, usage
client.metadata EXIF/IPTC/XMP metadata get and refresh
client.files Additional files per asset: list, upload (role master/derivative/source/sidecar/preview), download, delete
client.models 3D model facts and documentation: get, update, re-extract
client.media Video/audio recording information: get, update documentation, store probe facts
client.uploads Resumable multipart upload of large files (upload_file, with progress, resume and per-part retry)
client.search Full-text and metadata-driven search, geo search
client.categories Category CRUD (hierarchical tree)
client.custom_field_schemas Team custom field schema CRUD
client.zip ZIP batch import

File uploads

client.assets.upload() and client.assets.upload_file() accept:

  • A file path as a str or pathlib.Path
  • An already-open binary file object (IO[bytes])

The MIME type is inferred from the file extension if asset_type is omitted.

Error handling

from pycomad import ComadAuthError, ComadNotFoundError, ComadValidationError

try:
    asset = client.assets.get("non-existent-id")
except ComadNotFoundError:
    print("not found")
except ComadAuthError:
    client.login(email, password)   # token expired — re-authenticate
except ComadValidationError as e:
    print("bad request:", e)
Exception HTTP status
ComadAuthError 401 / 403, or login() not called
ComadNotFoundError 404
ComadValidationError 400
ComadServerError 5xx
ComadError base class

Access levels

Use the AccessLevel enumeration or plain strings when creating categories:

from pycomad import AccessLevel

client.categories.create("Press", access_level=AccessLevel.GLOBAL)
client.categories.create("Internal", access_level="Private")  # equivalent

Licence

MIT

Metadata

Release files for pycomad 26.7.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pycomad 26.7.1
File Size Uploaded Provenance
pycomad-26.7.1.tar.gz 51.8 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for pycomad 26.7.1
File Interpreter ABI Platform
pycomad-26.7.1-py3-none-any.whl Python 3 none any Details

Total release size: 91.1 kB

Release files / pycomad-26.7.1.tar.gz

Download URL pycomad-26.7.1.tar.gz
Size 51.8 kB
Tags Source
SHA-256 checksum
How to use checksums
1e82e72ecd01975da9e00beb3beb2127567995920c30a9ed6debc6467a3cba0e
BLAKE2b-256 checksum
How to use checksums
dc5387021d91845068088bbf8d6587e6b87f44d113e6d62837964ca69931c5c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / pycomad-26.7.1-py3-none-any.whl

Download URL pycomad-26.7.1-py3-none-any.whl
Size 39.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
db3c69c7a696a87a2bec42e84b5bb3c2d2606f0c015e5da5940fb86740141492
BLAKE2b-256 checksum
How to use checksums
80ebfc6c41c8778baf423024ce549738f5869f49e9ceeea4336e8714f5a43285
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Security for pycomad 26.7.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pycomad-26.7.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page