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
strorpathlib.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)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| pycomad-26.7.1.tar.gz | 51.8 kB | With provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 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 logRelease 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 logSecurity 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.
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 logA 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.