Beispiel #1
0
def get_info_entry(request: Request, entry: str):
    from optimade.models import EntryInfoResource

    valid_entry_info_endpoints = ENTRY_INFO_SCHEMAS.keys()
    if entry not in valid_entry_info_endpoints:
        raise HTTPException(
            status_code=404,
            detail=
            f"Entry info not found for {entry}, valid entry info endpoints are:"
            f" {valid_entry_info_endpoints}",
        )

    schema = ENTRY_INFO_SCHEMAS[entry]()
    queryable_properties = {"id", "type", "attributes"}
    properties, _ = retrieve_queryable_properties(schema, queryable_properties)

    output_fields_by_format = {"json": list(properties.keys())}

    return EntryInfoResponse(
        meta=meta_values(str(request.url), 1, 1, more_data_available=False),
        data=EntryInfoResource(
            formats=list(output_fields_by_format.keys()),
            description=schema.get(
                "description",
                "Endpoint to represent AiiDA Nodes in the OPTiMaDe format",
            ),
            properties=properties,
            output_fields_by_format=output_fields_by_format,
        ),
    )
    def _parse_params(self, params: EntryListingQueryParams) -> dict:
        """Parse query parameters and transform them into AiiDA QueryBuilder concepts"""
        cursor_kwargs = {}

        # filter
        if getattr(params, "filter", False):
            aiida_filter = self.transformer.transform(
                self.parser.parse(params.filter))
            self._filter_fields = set()
            cursor_kwargs["filters"] = self._alias_filter(aiida_filter)

        # response_format
        if (getattr(params, "response_format", False)
                and params.response_format != "json"):
            raise HTTPException(status_code=400,
                                detail="Only 'json' response_format supported")

        # page_limit
        if getattr(params, "page_limit", False):
            limit = self.page_limit
            if params.page_limit != self.page_limit:
                limit = params.page_limit
            if limit > self.db_page_limit:
                raise HTTPException(
                    status_code=403,
                    detail=
                    f"Max allowed page_limit is {self.db_page_limit}, you requested {limit}",
                )
            if limit == 0:
                limit = self.page_limit
            cursor_kwargs["limit"] = limit

        # response_fields
        # All OPTiMaDe fields
        fields = {"id", "type"}
        fields |= self.get_attribute_fields()
        # All provider-specific fields
        fields |= {self.provider + _ for _ in self.provider_fields}
        cursor_kwargs["fields"] = fields
        cursor_kwargs["project"] = list(
            {self.resource_mapper.alias_for(f)
             for f in fields})

        # sort
        # NOTE: sorting only works for extras fields for the nodes already with calculated extras.
        #       To calculate all extras, make a single filter query using any extra field.
        if getattr(params, "sort", False):
            sort_spec = []
            for entity_property in params.sort.split(","):
                field = entity_property
                sort_direction = "asc"
                if entity_property.startswith("-"):
                    field = field[1:]
                    sort_direction = "desc"
                aliased_field = self.resource_mapper.alias_for(field)

                _, properties = retrieve_queryable_properties(
                    self.resource_cls.schema(), {"id", "type", "attributes"})
                field_type = properties[field].get(
                    "format", properties[field].get("type", ""))
                if field_type == "array":
                    raise TypeError(
                        "Cannot sort on a field with a list value type")

                sort_spec.append({
                    aliased_field: {
                        "order": sort_direction,
                        "cast": self.CAST_MAPPING[field_type],
                    }
                })
            cursor_kwargs["order_by"] = sort_spec

        # page_offset
        if getattr(params, "page_offset", False):
            cursor_kwargs["offset"] = params.page_offset

        return cursor_kwargs