Work with the Fotoware API in Python.
Each server-side API endpoint is interacted with using a Tenant.
Create an non-interactive application integration server-side and supply the client ID and secret to the Tenant.
>>> from pyfwapi import Tenant
>>> fw = Tenant("https://tenant.example.org", client_id="abd123", client_secret="sekret")
>>> async for archive in fw.iter_archives():
... print(archive.name)
Marketing
Technical docsAssets (files) are organized into archives.
>>> archive = await fw.archive_by(id=5000)
>>> async for asset in fw.iter_assets(in_archive=archive):
... print(asset.filename, asset.filesize)
IMG_0021.jpg 27182818
logo_v3_final_FINAL.pdf 3141592SE builds search expressions fluently; combine terms with & (and), | (or), - (not).
Some properties that can be filtered on use abbreviated names, for which predicates.StrSpecial and predicates.Ranged are helpful.
>>> from pyfwapi.search import SE, predicates
... # PNGs at least 500px tall, mentioning "banner"
>>> q = SE().fts("banner").eq(predicates.StrSpecial.FileName, "*.png").pixel_height(min=500, max=None)
>>> async for asset in fw.match_assets(q):
... print(asset.filename)Previews are prerendered JPEGs, ready to download. Renditions are async, configurable, and include the original file.
>>> async for chunk in await fw.get_preview(asset, asset.previews[0]):
... outfile.write(chunk)
>>> rendition = asset.renditions[0]
>>> async for chunk in await fw.get_rendition(rendition, "/renditions/image"):
... outfile.write(chunk)Changes are staged in a ChangeManager and sent to the server in one go.
Note that these commits are neither atomic nor isolated, so parallel requests may find unmoved files during a commit.
>>> from pyfwapi.change.manager import ChangeManager
>>> cm = ChangeManager(fw.api)
>>> cm.set_value(asset, 305, "Approved") # set field 305
>>> cm.move([asset], destination=other_archive) # move between archives
>>> with open("photo.jpg", "rb") as f:
... cm.upload(f, archive, filename="photo.jpg")
>>> await cm.commit()The API responses are parsed using Pydantic. It's a hefty dependency, but -- for now -- allows easy parsing of the JSON responses. And it also enables easy integration with FastAPI.
Explorations of attrs, cattrs, and msgspec failed to quickly result in satisfactory objects from the API JSON responses.
The name of the library is a portmanteau of Python Fotoware API and I pronounce it as /paɪˈfwɒ.pi/.