Source code for iiisight.search
"""IIIF Content Search: discover a resource's search service and parse results.
A manifest (or canvas) advertises a Content Search service in its ``service``
block; :func:`find_search_service` locates it. :func:`search_url` builds the
query URL, and :func:`parse_search_response` normalizes the response — a v3
``AnnotationPage`` or a v2 ``sc:AnnotationList`` — into an
:class:`~iiisight.model.AnnotationPage` of hit annotations. ``client.search()``
ties these together.
"""
from collections.abc import Mapping
from typing import Any
from urllib.parse import urlencode
from .errors import UnexpectedDocumentError
from .model import AnnotationPage, Described, Service
from .normalize import parse_annotation_page
_SEARCH_TYPES = {"SearchService2", "SearchService1", "SearchService"}
_SEARCH_PROFILE_HINTS = ("search/2/search", "search/1/search")
[docs]
def find_search_service(resource: Described) -> Service | None:
"""Return the Content Search service on a resource, or ``None``."""
for service in resource.services:
if service.type in _SEARCH_TYPES:
return service
if service.profile and any(hint in service.profile for hint in _SEARCH_PROFILE_HINTS):
return service
return None
[docs]
def search_url(
target: Described | Service | str, query: str, params: Mapping[str, Any] | None = None
) -> str:
"""Build a Content Search query URL for a resource, service, or base URL."""
base = _base_url(target)
query_params = {"q": query}
if params:
query_params.update(params)
separator = "&" if "?" in base else "?"
return f"{base}{separator}{urlencode(query_params)}"
[docs]
def parse_search_response(document: Mapping[str, Any]) -> AnnotationPage:
"""Parse a Content Search response into an :class:`AnnotationPage` of hits."""
return parse_annotation_page(document)
def _base_url(target: Described | Service | str) -> str:
if isinstance(target, str):
return target
if isinstance(target, Service):
return target.id
service = find_search_service(target)
if service is None:
raise UnexpectedDocumentError("no Content Search service found on the resource")
return service.id