httk.optimade.backend.protocols =============================== .. py:module:: httk.optimade.backend.protocols .. autoapi-nested-parse:: Typed protocols for the store/searcher contract the OPTIMADE backend uses. The store/searcher protocols are defined in :mod:`httk.data.query` (httk-data is where httk's data stores live, and this backend programs against their shared query contract); this module re-exports them for the backend's use, together with the OPTIMADE-specific query-callable types from the result model. Classes ------- .. autoapisummary:: httk.optimade.backend.protocols.Searcher httk.optimade.backend.protocols.SearchExpression httk.optimade.backend.protocols.SearchField httk.optimade.backend.protocols.SearchResult httk.optimade.backend.protocols.SearchVariable httk.optimade.backend.protocols.Store httk.optimade.backend.protocols.QueryFunction httk.optimade.backend.protocols.QueryResults Module Contents --------------- .. py:class:: Searcher Bases: :py:obj:`Protocol` A single query under construction, and its results once iterated. Iteration yields one :class:`SearchResult` per match, so ``item[0][0]`` is the first declared output of the match (typically the matched row object). The expressions received by ``add`` are always ones produced by this same backend's search variables, so implementations may type them as their own expression class; a backend that needs a second (post-filter) evaluation position decides that from the expression itself, not from the caller. .. py:attribute:: offset :type: int .. py:method:: variable(target: Any) -> Any .. py:method:: output(variable: Any, name: str) -> None .. py:method:: add(expression: Any) -> None .. py:method:: count() -> int .. py:method:: set_limit(limit: int) -> None .. py:method:: add_offset(offset: int) -> None .. py:method:: add_sort(field: Any, descending: bool) -> None .. py:class:: SearchExpression Bases: :py:obj:`Protocol` Base class for protocol classes. Protocol classes are defined as:: class Proto(Protocol): def meth(self) -> int: ... Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing). For example:: class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check See PEP 544 for details. Protocol classes decorated with @typing.runtime_checkable act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. Protocol classes can be generic, they are defined as:: class GenProto[T](Protocol): def meth(self) -> T: ... .. py:class:: SearchField Bases: :py:obj:`Protocol` A queryable field of a search variable. In addition to the methods below, fields support the rich comparison operators (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``), returning :class:`SearchExpression`. The handlers invoke those via ``getattr(field, '__eq__')(value)`` since the comparison dunders cannot be typed as expression-returning. The three string-matching methods take **literal** text: no wildcard or pattern syntax whatsoever crosses this contract, so ``%`` and ``_`` (and any other metacharacter) match themselves. A backend is therefore free to implement them with SQL ``LIKE`` over an escaped pattern, with a regular expression, or with a full-text index — the choice is invisible here. .. py:method:: has_any(*values: Any) -> SearchExpression .. py:method:: has_only(*values: Any) -> SearchExpression .. py:method:: contains(text: str) -> SearchExpression Match values containing ``text`` as a literal substring. .. py:method:: startswith(prefix: str) -> SearchExpression Match values beginning with the literal ``prefix``. .. py:method:: endswith(suffix: str) -> SearchExpression Match values ending with the literal ``suffix``. .. py:class:: SearchResult Bases: :py:obj:`NamedTuple` One match: the declared output values, and the names they were declared under. ``values`` holds one entry per :meth:`Searcher.output` call in declaration order; it is a tuple, so ``values, names = result`` and ``result[0][0]`` both work. .. py:attribute:: values :type: tuple[Any, Ellipsis] .. py:attribute:: names :type: tuple[str, Ellipsis] .. py:class:: SearchVariable Bases: :py:obj:`Protocol` A query variable bound to a target type; attribute access yields fields. ``always_true``/``always_false`` are reserved names: they are real methods of the variable, never stored fields resolved through ``__getattr__``. They exist so a translation layer can express a constant truth value without inventing a probe field. A ``field == field`` probe is NULL-unsound, since it yields NULL (not true) for a NULL field. .. py:method:: always_true() -> SearchExpression An expression that matches every row. .. py:method:: always_false() -> SearchExpression An expression that matches no row. .. py:class:: Store Bases: :py:obj:`Protocol` Base class for protocol classes. Protocol classes are defined as:: class Proto(Protocol): def meth(self) -> int: ... Such classes are primarily used with static type checkers that recognize structural subtyping (static duck-typing). For example:: class C: def meth(self) -> int: return 0 def func(x: Proto) -> int: return x.meth() func(C()) # Passes static type check See PEP 544 for details. Protocol classes decorated with @typing.runtime_checkable act as simple-minded runtime protocols that check only the presence of given attributes, ignoring their type signatures. Protocol classes can be generic, they are defined as:: class GenProto[T](Protocol): def meth(self) -> T: ... .. py:method:: searcher() -> Searcher .. py:class:: QueryFunction Bases: :py:obj:`Protocol` The callback seam through which the request engine runs queries on a backend. .. py:class:: QueryResults Bases: :py:obj:`Protocol` The results of a query against a backend, as consumed by the entry endpoints. Iteration yields one :class:`~httk.optimade.model.results.ResultRow` per entry; its ``values`` map OPTIMADE response-field names to values, and the ``id`` and ``type`` keys are always present. .. py:attribute:: more_data_available :type: bool .. py:method:: count() -> int