Source code for httk.core.fetching

"""Fetch URL sources through OPTIMADE or the registered file-reader pipeline."""

from typing import Any
from urllib.parse import urlsplit

from .datastream import TextstreamFileView
from .loading import adapt_result, has_reader_for, load_source, reader_uses_extension
from .optimade.resources import is_optimade_entry_url, optimade_resource_from_url, redact_optimade_url


[docs] def fetch( url: str, *, raw: bool = False, timeout: float | None = None, kind: str | None = None, **kwargs: Any, ) -> Any: r"""Fetch a URL as an OPTIMADE entry or a registered file format. ``kind="optimade"`` forces OPTIMADE handling and ``kind="load"`` forces file-reader handling. With no ``kind``, a reader-claimed extension wins over an OPTIMADE-shaped path; a reader-claimed basename is ambiguous and requires an explicit ``kind``. ``file://`` URLs are supported in either branch. Redirects follow ``urllib`` defaults. As the explicit URL entry point, this function supplies the same network consent represented by :class:`~httk.core.DatastreamURL`; it does not use implicit bare-string network access for the reader branch. :param url: URL to fetch. :param raw: Whether to return a neutral payload without a format adapter. :param timeout: Optional timeout for URL-backed reader access or OPTIMADE requests. :param kind: Optional branch selector: ``"optimade"`` or ``"load"``. :param \**kwargs: Additional options passed to the file reader. :return: The fetched OPTIMADE resource or loaded file value. :raises ValueError: If the URL, ``kind``, or automatic branch selection is invalid. """ split = urlsplit(url) if not split.scheme: raise ValueError(f"fetch requires a URL; use httk.core.load({redact_optimade_url(url)!r}) for local files") if kind not in (None, "optimade", "load"): raise ValueError("fetch kind must be 'optimade' or 'load'") is_entry_url = is_optimade_entry_url(url) reader_claimed = has_reader_for(split.path) if kind == "optimade" or (kind is None and is_entry_url and not reader_claimed): resource = optimade_resource_from_url(url, timeout=timeout) return adapt_result({"format": "optimade-entry", "resource": resource}, raw) if kind == "load" or (kind is None and reader_claimed and (not is_entry_url or reader_uses_extension(split.path))): return load_source(TextstreamFileView(url, kind="url", timeout=timeout), split.path, raw=raw, **kwargs) if kind is None and is_entry_url and reader_claimed: raise ValueError( f"URL {redact_optimade_url(url)!r} is both an OPTIMADE entry and a reader-claimed file; " "pass kind='optimade' or kind='load'" ) raise ValueError( f"Could not fetch {redact_optimade_url(url)!r}: it is neither an OPTIMADE single-entry URL nor a URL with " "a registered reader; " "pass kind='optimade' or kind='load' to choose explicitly" )