Skip to content

prepare

get_query_params(query_parameters, database_id, filter_mapping) async

Construct the parsed URL query parameters

Source code in optimade_gateway/queries/prepare.py
async def get_query_params(
    query_parameters: OptimadeQueryParameters,
    database_id: str,
    filter_mapping: Dict[str, Union[str, None]],
) -> str:
    """Construct the parsed URL query parameters"""
    query_params = {
        param: value for param, value in query_parameters.dict().items() if value
    }
    if filter_mapping[database_id]:
        query_params.update({"filter": filter_mapping[database_id]})
    return urllib.parse.urlencode(query_params)

get_response_model(endpoint_model) async

Import and return response model based on endpoint_model.

Parameters:

Name Type Description Default
endpoint_model Tuple[str, str]

The endpoint_model from the QueryResource attributes.

required

Returns:

Type Description
Union[optimade.models.responses.EntryResponseMany, optimade.models.responses.EntryResponseOne]

The imported response model class, e.g., StructureResponseMany.

Source code in optimade_gateway/queries/prepare.py
async def get_response_model(
    endpoint_model: Tuple[str, str]
) -> Union[EntryResponseMany, EntryResponseOne]:
    """Import and return response model based on `endpoint_model`.

    Parameters:
        endpoint_model: The
            [`endpoint_model`][optimade_gateway.models.queries.QueryResourceAttributes.endpoint_model]
            from the
            [`QueryResource` attributes][optimade_gateway.models.queries.QueryResourceAttributes].

    Returns:
        The imported response model class, e.g., `StructureResponseMany`.

    """
    module, name = endpoint_model
    return getattr(importlib.import_module(module), name)

prepare_query(database_ids, endpoint_model, filter_query) async

Prepare a query by returning necessary variables.

Source code in optimade_gateway/queries/prepare.py
async def prepare_query(
    database_ids: List[str],
    endpoint_model: Tuple[str, str],
    filter_query: Union[str, None],
) -> Tuple[Dict[str, Union[str, None]], Union[EntryResponseMany, EntryResponseOne]]:
    """Prepare a query by returning necessary variables."""
    return (
        await update_query_filter(database_ids, filter_query),
        await get_response_model(endpoint_model),
    )

update_query_filter(database_ids, filter_query) async

Update the query parameter filter value to be database-specific

This is needed due to the served change of id values. If someone searches for a gateway-changed id, it needs to be reverted to be database-specific.

Parameters:

Name Type Description Default
database_ids List[str]

List of the databases to create updated filter values for. These values are part of the gateway-changed id values and are essential.

required
filter_query Optional[str]

The submitted filter query parameter value. Can be None if not supplied.

required

Returns:

Type Description
Dict[str, Optional[str]]

A mapping for database IDs to database-specific filter query parameter values.

Source code in optimade_gateway/queries/prepare.py
async def update_query_filter(
    database_ids: List[str], filter_query: Union[str, None]
) -> Dict[str, Union[str, None]]:
    """Update the query parameter `filter` value to be database-specific

    This is needed due to the served change of `id` values.
    If someone searches for a gateway-changed `id`, it needs to be reverted to be
    database-specific.

    Parameters:
        database_ids: List of the databases to create updated filter values for.
            These values are part of the gateway-changed `id` values and are essential.
        filter_query: The submitted `filter` query parameter value. Can be `None` if not supplied.

    Returns:
        A mapping for database IDs to database-specific `filter` query parameter values.

    """
    updated_filter = {}.fromkeys(database_ids, filter_query)

    if not filter_query:
        return updated_filter

    for id_match in re.finditer(
        r'"(?P<id_value_l>[^\s]*)"[\s]*(<|>|<=|>=|=|!=|CONTAINS|STARTS WITH|ENDS WITH|STARTS|ENDS)'
        r'[\s]*id|[^_]+id[\s]*(<|>|<=|>=|=|!=|CONTAINS|STARTS WITH|ENDS WITH|STARTS|ENDS)[\s]*"'
        r'(?P<id_value_r>[^\s]*)"',
        f"={filter_query}" if filter_query else "",
    ):
        matched_id = id_match.group("id_value_l") or id_match.group("id_value_r")
        for database_id in database_ids:
            if matched_id.startswith(f"{database_id}/"):
                # Database found
                updated_filter[database_id] = updated_filter[database_id].replace(
                    f"{database_id}/", "", 1
                )
                break
            # TODO: Remove `id="value"` sections here for queries to databases that doesn't match the id value!
        else:
            raise BadRequest(
                detail=(
                    f"Structures entry <id={matched_id}> not found. To get a specific structures "
                    "entry one needs to prepend the ID with a database ID belonging to the gateway,"
                    f" e.g., '{database_ids[0]}/<local_database_ID>'. Available"
                    f"databases for this gateway: {database_ids}"
                )
            )
    return updated_filter
Back to top