Source code for jelastic.api.abstract

import json
import requests
from abc import ABC
from datetime import date, datetime
from typing import Any, Literal, Optional
from urllib.parse import urlencode

from .exceptions import *

RequestData = dict[Any, Any]
VALID_METHODS = Literal["get", "post"]

__all__ = ["ClientAbstract"]


[docs] class ClientAbstract(ABC): """ Abstract class representing a Jelastic API client. :param session: HTTPX session :param token: Jelastic API token :param debug: enable debug mode :cvar _endpoint1: first part of the endpoint :cvar _endpoint2: second part of the endpoint :cvar _required_permission: required permission for the endpoint :return: Jelastic API client """ _endpoint1: str _endpoint2: str _required_permission: str
[docs] def __init__( self, session: requests.Session, token: str, debug: bool = False, ruk: str = None, ) -> None: """ Initialize the client with the given session and token. :param session: HTTPX session :param token: Jelastic API token :param debug: enable debug mode :param ruk: Jelastic RUK (random unique key) """ self._session = session self._token = token self._debug = debug self._ruk = ruk
[docs] def _log_debug( self, method: VALID_METHODS, path: str, params: Optional[dict[str, Any]] = None ) -> None: """ Prints `debug` information about the request. :param method: HTTP method :param path: endpoint path :param params: endpoint params """ endpoint = self._endpoint(path=path, params=params) prefix = f"[Jelastic] [{method.upper()}] [{self._ruk}]" message = f"{prefix}, Path: {endpoint}, Params: {params}" print(message)
[docs] def _serialize_params( self, params: dict[str, Any], delimiter: str = None, datetime_format: str = None ) -> str: """ Serialize params for endpoint URL :param params: endpoint params :return: serialized params for endpoint URL (e.g. `appid=cluster&session=token`) """ if params is None: params = {} params.setdefault("appid", "cluster") params.setdefault("session", self._token) params.setdefault("ruk", self._ruk) # Remove None values and serialize params serialized_params = {} for key, value in params.items(): if value is None: continue # pragma: no cover if isinstance(value, (date, datetime)): if datetime_format: serialized_params[key] = value.strftime(datetime_format) else: serialized_params[key] = value.isoformat() elif ( isinstance(value, list) and all(isinstance(item, str) for item in value) and delimiter ): serialized_params[key] = f"{delimiter}".join(value) elif isinstance(value, dict): serialized_params[key] = json.dumps(value) else: serialized_params[key] = value # Sort params and return serialized params serialized_params = dict( sorted(serialized_params.items(), key=lambda item: item[0]) ) return urlencode(serialized_params)
[docs] def _endpoint( self, path: str, params: Optional[dict[str, Any]] = None, delimiter: str = None, datetime_format: str = None, ) -> str: """ Returns the endpoint for the request. :param path: endpoint path :param params: endpoint params :return: endpoint for the request (e.g. `/endpoint1/endpoint2/rest/path?appid=cluster&session=token`) """ # Build the required permissions self._required_permission = f"{self._endpoint1}.{self._endpoint2}.{path}" serialized_params = self._serialize_params( params, delimiter=delimiter, datetime_format=datetime_format ) return f"{self._endpoint1}/{self._endpoint2}/rest/{path.lower()}?{serialized_params}"
[docs] def _handle_response(self, response: dict[str, Any]) -> dict[str, Any]: """ Handle the response from the API. :param response: response from the API """ result_code = response.get("result", 0) error = response.get("error", "Unknown API error") if result_code == 8202: raise JelasticPermissionError( f"Permission denied, required permissions: {self._required_permission}" ) if result_code == 2223: raise JelasticExternBillingRejected(error) if result_code == 2207: raise JelasticExternBillingError(error) if result_code == 5: raise JelasticResourceNotFound(error) if result_code != 0: raise JelasticApiError(error) return response
def _get( self, *args: str, params: dict[str, Any] = None, delimiter: str = None, datetime_format: str = None, ) -> dict[str, Any]: if self._debug: self._log_debug("get", *args, params=params) url = self._endpoint( *args, params=params, delimiter=delimiter, datetime_format=datetime_format ) # Get the X-Base-Url header and remove it from the session base_url = self._session.headers.get("X-Base-Url", None) assert base_url is not None url = f"{base_url}{url}" response = self._session.get(url) if not response.ok: if response.status_code == 404: raise JelasticResourceNotFound(f"API endpoint not found: {url}") raise JelasticApiError(response.text) return self._handle_response(response.json())