Tolerance & diagnostics¶
Real-world IIIF is imperfect. iiisight’s core promise is that normalization
never raises on a spec-imperfect document — it repairs what it can and records
each repair as a Diagnostic. (This is distinct from transport
failures like a 404 or non-JSON body, which do raise FetchError.)
Diagnostics¶
Every normalized document carries a diagnostics tuple:
manifest = iiisight.normalize(document)
for d in manifest.diagnostics:
print(d.severity, d.code, d.path, d.message, d.recovered)
Each Diagnostic has:
code— a stable machine code (e.g."coerced-language-map","upgraded-v2-to-v3").severity— aSeverity:INFO— spec-sanctioned normalization (a default the spec allows, or a v2→v3 upgrade).WARNING— a deviation repaired without losing information (missing recommended field, coerced type).ERROR— something that could not be represented and was dropped/skipped; the model is lossy atpathbut still usable — and it still did not raise.
path— a JSON pointer to the offending node.recovered— what was assumed, coerced, or skipped.
For example, a manifest whose label is a bare string instead of a language map
is coerced ({"none": ["…"]}) and flagged with a coerced-language-map warning —
you get a usable label and a record that the source was non-conforming.
The lint¶
The lint is a reporting view over those diagnostics — “what did a real client have to guess or fix to read this document?” It is client-compatibility feedback, not a strict spec-conformance check.
report = iiisight.lint(manifest) # accepts a Manifest/Collection or a raw dict
report.ok # True if nothing beyond INFO occurred
report.summary() # "1 error(s), 2 warning(s), 3 info"
for problem in report.errors: # also .warnings, .infos
print(problem.code, problem.path, problem.message)
report.counts() # {Severity.ERROR: 1, ...}
You can lint a document you have not fetched yet by passing a URL through a client first:
async with iiisight.AsyncClient() as client:
manifest = await client.fetch_manifest(url)
report = iiisight.lint(manifest)
print(report.summary())
with iiisight.Client() as client:
manifest = client.fetch_manifest(url)
report = iiisight.lint(manifest)
print(report.summary())
Why tolerance matters¶
Running iiisight against production manifests (Wellcome, the Bodleian) surfaces
real deviations — e.g. a search service with a bare-string label where v3
requires a language map. A stricter parser would reject those documents outright;
iiisight reads them and tells you what it had to repair.