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.0

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.0
File Size Uploaded Provenance
pycomad-26.7.0.tar.gz 51.9 kB With provenance Details

Built distribution (wheel)

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

Total release size: 91.1 kB

Release files / pycomad-26.7.0.tar.gz

Download URL pycomad-26.7.0.tar.gz
Size 51.9 kB
Tags Source
SHA-256 checksum
How to use checksums
263cf34f35a09096cb636a07b04e00ed2cb858b900ac8cf6c172b118fc75a0c2
BLAKE2b-256 checksum
How to use checksums
806533c0762e2ccb4706698bdfa41b21aee7bddec79ed3835dfff83d8bd69a5f
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.0-py3-none-any.whl

Download URL pycomad-26.7.0-py3-none-any.whl
Size 39.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d7e10269bb1c307c741bfb6bed508d38f3ebd782eb62160fa911dc511759d602
BLAKE2b-256 checksum
How to use checksums
08a85b87761dd9cd729b99ce8e167188219ee1cf3aa5ca27d106af3774878468
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.0

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.0.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