Skip to content

ratings_client

Definitions to help interact with the Ratings API.

RatingsAPIClient

Bases: GenericHordeAPIManualClient

Represent a client specifically configured for the Ratings APi.

Source code in horde_sdk/ratings_api/ratings_client.py
class RatingsAPIClient(GenericHordeAPIManualClient):
    """Represent a client specifically configured for the Ratings APi."""

    def __init__(self) -> None:
        """Create a new instance of the RatingsAPIClient."""
        super().__init__(
            path_fields=RatingsAPIPathFields,
            query_fields=RatingsAPIQueryFields,
        )

retry_config instance-attribute

retry_config: RetryConfiguration = retry_config

__init__

__init__() -> None

Create a new instance of the RatingsAPIClient.

Source code in horde_sdk/ratings_api/ratings_client.py
def __init__(self) -> None:
    """Create a new instance of the RatingsAPIClient."""
    super().__init__(
        path_fields=RatingsAPIPathFields,
        query_fields=RatingsAPIQueryFields,
    )

should_retry

should_retry(
    status_code: int,
    current_error_count: int,
    retry_after: float,
) -> bool

Determine if a request should be retried based on the status code and retry configuration.

Parameters:

  • status_code (int) –

    The HTTP status code returned by the request.

  • current_error_count (int) –

    The current number of errors encountered.

  • retry_after (float) –

    The time to wait before retrying the request.

Returns:

  • bool ( bool ) –

    True if the request should be retried, False otherwise.

Source code in horde_sdk/generic_api/generic_clients.py
def should_retry(
    self,
    status_code: int,
    current_error_count: int,
    retry_after: float,
) -> bool:
    """Determine if a request should be retried based on the status code and retry configuration.

    Args:
        status_code (int): The HTTP status code returned by the request.
        current_error_count (int): The current number of errors encountered.
        retry_after (float): The time to wait before retrying the request.

    Returns:
        bool: True if the request should be retried, False otherwise.
    """
    if not self._retry_by_default:
        return False

    if current_error_count >= self.retry_config.max_retries:
        return False

    if status_code not in self.retry_config.retry_status_codes:
        return False

    jitter = (self.retry_config.jitter_factor * retry_after) if self.retry_config.jitter_factor else 0

    retry_delay = (
        min(
            self.retry_config.initial_delay_seconds * (self.retry_config.backoff_factor**current_error_count),
            self.retry_config.max_delay_seconds,
        )
        + jitter
    )

    time.sleep(retry_delay)
    return True

submit_request

submit_request(
    api_request: HordeRequest,
    expected_response_type: type[HordeResponseTypeVar],
) -> HordeResponseTypeVar | RequestErrorResponse

Submit a request to the API and return the response.

If you are wondering why expected_response_type is a parameter, it is because the API may return different responses depending on the payload or other factors. It is up to you to determine which response type you expect, and pass it in here.

Parameters:

  • api_request (HordeRequest) –

    The request to submit.

  • expected_response_type (type[HordeResponse]) –

    The expected response type.

Returns:

Source code in horde_sdk/generic_api/generic_clients.py
def submit_request(
    self,
    api_request: HordeRequest,
    expected_response_type: type[HordeResponseTypeVar],
) -> HordeResponseTypeVar | RequestErrorResponse:
    """Submit a request to the API and return the response.

    If you are wondering why `expected_response_type` is a parameter, it is because the API may return different
    responses depending on the payload or other factors. It is up to you to determine which response type you
    expect, and pass it in here.

    Args:
        api_request (HordeRequest): The request to submit.
        expected_response_type (type[HordeResponse]): The expected response type.

    Returns:
        HordeResponseTypeVar | RequestErrorResponse: The response from the API.
    """
    http_method_name = api_request.get_http_method()

    if expected_response_type not in api_request.get_success_status_response_pairs().values():
        logger.warning(
            "The expected response type is not in the list of success status response pairs! This may result in "
            "unexpected behavior.",
        )
        logger.warning(f"Passed expected_response_type: {expected_response_type}")
        logger.warning(f"Allowable pairs defined in the SDK : {api_request.get_success_status_response_pairs()}")

    with logfire.span(
        self._msg_format_submit_request.format(
            sync_async="sync",
            http_method_name=http_method_name,
            api_request_type=type(api_request).__name__,
            expected_response_type=expected_response_type.__name__,
        ),
        sync_async="sync",
        http_method_name=http_method_name,
        api_request_type=type(api_request).__name__,
        expected_response_type=expected_response_type.__name__,
    ):
        parsed_request = self._validate_and_prepare_request(api_request)

        raw_response: requests.Response | None = None

        if http_method_name == HTTPMethod.GET:
            if parsed_request.request_body is not None:
                raise RuntimeError(
                    "GET requests cannot have a body! This may mean you forgot to override `get_header_fields()` "
                    "or perhaps you may need to define a `metadata.py` module or entry in it for your API.",
                )
            raw_response = requests.get(
                parsed_request.endpoint_no_query,
                headers=parsed_request.request_headers,
                params=parsed_request.request_queries,
                allow_redirects=True,
            )
        else:
            raw_response = requests.request(
                method=http_method_name,
                url=parsed_request.endpoint_no_query,
                headers=parsed_request.request_headers,
                params=parsed_request.request_queries,
                json=parsed_request.request_body,
                allow_redirects=True,
            )

        return self._after_request_handling(
            raw_response_json=raw_response.json(),
            returned_status_code=raw_response.status_code,
            expected_response_type=expected_response_type,
        )