Source code for httk.optimade.model.request
from dataclasses import dataclass, field
from typing import Any
@dataclass(slots=True)
[docs]
class RawRequest:
"""An incoming OPTIMADE request, as handed over by the web layer.
Only ``baseurl`` and ``representation`` are mandatory; missing information
is derived from ``representation`` during validation.
"""
[docs]
relurl: str | None = None
[docs]
querystr: str | None = None
[docs]
query: dict[str, str] | None = None
[docs]
endpoint: str | None = None
[docs]
request_id: str | None = None
[docs]
version: str | None = None
@dataclass(slots=True)
[docs]
class RequestedSlice:
"""A slice requested via the ``dimension_slices`` query parameter.
The values are stored exactly as given (a ``None`` component means the
client omitted it and the default applies). Per the OPTIMADE specification,
``stop`` is *inclusive*.
"""
[docs]
start: int | None = None
[docs]
stop: int | None = None
[docs]
step: int | None = None
@dataclass(slots=True)
[docs]
class ValidatedParameters:
"""Validated URL query parameters of an OPTIMADE request."""
[docs]
page_limit: int = 50
[docs]
page_offset: int = 0
[docs]
response_fields: str | None = None
[docs]
filter: str | None = None
[docs]
sort: str | None = None
[docs]
include: str | None = None
[docs]
dimension_slices: dict[str, RequestedSlice] = field(default_factory=dict)
[docs]
def as_query_dict(self) -> dict[str, str]:
"""Return the parameters as a URL query dict, omitting unset values."""
query: dict[str, str] = {
'response_format': self.response_format,
'page_limit': str(self.page_limit),
'page_offset': str(self.page_offset),
}
if self.response_fields is not None:
query['response_fields'] = self.response_fields
if self.filter is not None:
query['filter'] = self.filter
if self.sort is not None:
query['sort'] = self.sort
if self.include is not None:
query['include'] = self.include
if self.dimension_slices:
parts = []
for name, requested in self.dimension_slices.items():
start = "" if requested.start is None else str(requested.start)
stop = "" if requested.stop is None else str(requested.stop)
step = "" if requested.step is None else str(requested.step)
parts.append(f"{name}[{start}:{stop}:{step}]")
query['dimension_slices'] = ",".join(parts)
return query
@dataclass(slots=True)
[docs]
class ValidatedRequest:
"""The result of validating a :class:`RawRequest`."""
[docs]
query: ValidatedParameters
[docs]
url_version: str | None = None
[docs]
request_id: str | None = None
[docs]
recognized_response_fields: list[str] = field(default_factory=list)
[docs]
unrecognized_response_fields: list[str] = field(default_factory=list)
[docs]
sort_fields: list[tuple[str, bool]] = field(default_factory=list)
[docs]
include_paths: list[str] = field(default_factory=list)
[docs]
partial_data_parts: tuple[str, str, str] | None = None
[docs]
partial_data_offset: int = 0
[docs]
warnings: list[dict[str, Any]] = field(default_factory=list)
@dataclass(slots=True)
[docs]
class EndpointResponse:
"""A response produced by an endpoint, to be serialized by the web layer.
Either ``json_response`` (a JSON:API document) or ``content`` (a raw body)
is set.
"""
[docs]
response_code: int = 200
[docs]
response_msg: str = 'OK'
[docs]
content_type: str = 'application/vnd.api+json'
[docs]
encoding: str = 'utf-8'
[docs]
content: str | None = None
[docs]
json_response: dict[str, Any] | None = None