Skip to main content

python-fotoware-client

tests pre-commit

A thin, read-only Python client for the FotoWare API (FotoWeb). It does what the API does and shows what that costs; it knows nothing about any particular archive's fields.

Not affiliated with or endorsed by FotoWare AS. "FotoWare" and "FotoWeb" are their trademarks.

What it does

  • One method per API call, one request each. FotoWareClient mirrors FotoWare's REST API: get_api_descriptor, get_archives, get_archive, get_metadata_editor, search (one page), get_page, get_asset, request_rendition, get_rendition_task. Nothing is batched or asked again behind the caller's back.
  • Extensions for what takes several calls. fotoware_client.extensions builds on those methods alone: list_archives, field_labels, iter_search over every page, and Rendition for a file from request to download.
  • Refuses a query FotoWare would answer wrongly. Over FotoWare's size limit a search comes back as a 500 or, worse, as an empty list that looks exactly like "no hits". search estimates the query first and raises QueryTooLargeError over the budget, without sending it. estimate_query_size is public, so callers can batch to stay under it.
  • Retries what is transient. urllib3's Retry on the session retries 429 (honouring Retry-After) and 502/503/504, twice by default. A 500 is not retried: it was always caused by the query. The waits double from 1 s and carry jitter, so parallel callers do not all ask again at the same moment; a Retry-After is kept as sent.
  • Counts the cost. cost_snapshot() reports requests, retries, errors, search pages and empty search pages. A 410 Gone counts as gone, not as an error: it is how a rendition task FotoWare cleaned up answers, and Rendition requests such a rendition anew.
  • OAuth client credentials with automatic token refresh; context manager.
  • Takes hrefs as FotoWare gives them. Answers carry paths on the tenant; every call that takes an href accepts a path or a full URL.

FotoWare's limits

Measured on 2026-10-23 against FotoWeb 8.1.1223.0; details and edges in fotoware_client/limits.py.

Limit Value
Assets per search answer 25, with pageSize ignored. FotoWare guarantees no page size, so the client follows paging.next and counts nothing
Cost of an answer ~0.4 s with hits whether 1 or 25 assets; 130–220 ms empty
Search size about 2,000 by estimate_query_size; budget 1,500

So the cheapest search asks for as many terms as fit the budget and fills whole pages.

Two search settings of an installation (Site Configuration › Searching) are out of the client's sight:

  • Maximum number of hits caps a result set. A search with more hits ends early, without saying so.
  • Search string modification decides how plain words without an operator are combined (AND, OR or as a phrase). Write AND/OR explicitly, and the setting does not matter.

Settings of an installation

What a FotoWare installation may set differently, the client takes as ServerSettings; the defaults are FotoWeb's:

from fotoware_client import FotoWareClient, ServerSettings

settings = ServerSettings(
    original_rendition_name="Originaldatei",  # display names are configurable
    download_timeout=300,  # seconds per download or rendition
    rendition_poll_interval=0.5,  # first wait while a rendition is made
    query_size_budget=1200,  # if the installation's limit is lower
)
client = FotoWareClient.from_env(settings=settings)

Also: oauth_token_path, api_descriptor_path, rendition_poll_interval_max and term_overhead. See fotoware_client/settings.py.

Credentials

Pass them to the constructor, or let FotoWareClient.from_env() find them:

  1. the environment: FOTOWARE_TENANT_URL, FOTOWARE_CLIENT_ID, FOTOWARE_CLIENT_SECRET;
  2. else the credentials file ~/.config/fotoware/credentials ($XDG_CONFIG_HOME/fotoware/credentials), one NAME=value per line, refused unless only its owner may read it (chmod 600).

Never on a command line, where a secret lands in the process list and the shell history.

Usage

from fotoware_client import FotoWareClient
from fotoware_client.extensions import Rendition, iter_search, list_archives

with FotoWareClient.from_env() as client:
    archive = next(a for a in list_archives(client) if a.href.startswith("/fotoweb/archives/5000-"))
    query = "(631:4000000000001 OR 631:4000000000002) AND (dt:image OR dt:graphic)"
    for page in iter_search(client, archive.href, query):
        for asset in page.assets:
            print(asset.filename)

    Rendition(client, asset.href).save("original.jpg")
    data = Rendition(client, asset.href, "Medium (JPG, 3000px)").read()
    print(client.cost_snapshot())

Rendition(client, href, name=None) asks FotoWare to prepare the original, or the rendition with that display name, polls the task, and downloads the file in the poll that finds it ready: .save(path), .read(), .write_to(file), or .url() for the prepared address alone. A task FotoWare has already cleaned up (410 Gone) is requested anew, once.

Errors

All derive from FotoWareError:

Error When
QueryTooLargeError the query is over the size budget; nothing sent
RateLimitError a 429 outlasted the retries
RetryExhaustedError a 502/503/504, connection error or timeout outlasted the retries
NotFoundError a 404
APIError any other error status, a 500 among them
AuthenticationError the token could not be fetched
ConfigurationError the client was set up wrongly

Install

pip install python-fotoware-client

Development

make venv
make lint type test

Pre-commit hooks: pip install pre-commit && pre-commit install.

License

MIT, see LICENSE.

Metadata

Release files for python-fotoware-client 0.3.2

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

Source distribution (sdist)

Source distribution for python-fotoware-client 0.3.2
File Size Uploaded Provenance
python_fotoware_client-0.3.2.tar.gz 37.5 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for python-fotoware-client 0.3.2
File Interpreter ABI Platform
python_fotoware_client-0.3.2-py3-none-any.whl Python 3 none any Details

Total release size: 65.3 kB

Release files / python_fotoware_client-0.3.2.tar.gz

Download URL python_fotoware_client-0.3.2.tar.gz
Size 37.5 kB
Tags Source
SHA-256 checksum
How to use checksums
47ed866f4c5419cca38106359aaf454a0205524f98e38c8210615541755f3bea
BLAKE2b-256 checksum
How to use checksums
099d867aab694967595db368282d59ca2f405abd6be67009f3f9a59561278541
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 25, 2026.

Transparency log

Release files / python_fotoware_client-0.3.2-py3-none-any.whl

Download URL python_fotoware_client-0.3.2-py3-none-any.whl
Size 27.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4b6910f568eaf1ee8fe6ab646e34e92cabc34d2f7d499c58aabdf0cc0cc0418f
BLAKE2b-256 checksum
How to use checksums
7ac938ac793c11da108cf391409a0abf5f60fff03069a6fffba344697a874730
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 25, 2026.

Transparency log

Security for python-fotoware-client 0.3.2

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 python_fotoware_client-0.3.2.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 25, 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