diff --git a/re2oapi/client.py b/re2oapi/client.py index d067bb7..b4b9567 100644 --- a/re2oapi/client.py +++ b/re2oapi/client.py @@ -9,13 +9,33 @@ import stat from . import endpoints from . import exceptions +# Number of seconds before expiration where renewing the token is done TIME_FOR_RENEW = 60 +# Default name of the file to store tokens DEFAULT_TOKEN_FILENAME = '.re2o.token' class Re2oAPIClient: + """ + Object to handle the requests to Re2o API in a seemless way. + You must first initialize the client and then you can access + the API with dedicated functions that handle the authentication + process + """ def __init__(self, hostname, username, password, token_file=None, use_tls=True): + """ + Create an API client. + + :param hostname: (str) The hostname of the Re2o server to use + :param username: (str) The username to use + :param password: (str) The password to use + :param token_file: (str) A path to a file where re2o tokens are stored + If `None`, then `$HOME/DEFAULT_TOKEN_FILENAME` is used. + (Default: None) + :param use_tls: (bool) Should the client used TLS (recommended for + production). (Default: True) + """ self.use_tls = use_tls self.token_file = token_file or Path.home() / DEFAULT_TOKEN_FILENAME self.hostname = hostname @@ -34,6 +54,10 @@ class Re2oAPIClient: @property def need_renew_token(self): + """ + True is the token expiration time is within less than `TIME_FOR_RENEW` + seconds + """ return self.token['expiration'] > \ datetime.datetime.now(datetime.timezone.utc) + \ datetime.timedelta(seconds=TIME_FOR_RENEW) @@ -91,12 +115,23 @@ class Re2oAPIClient: } def get_token(self): + """ + Returns the token for the current connection + """ if self.need_renew_token: self.token = self._get_token_from_server() return self.token['token'] def get(self, url, headers={}, params={}, *args, **kwargs): - headers = kwargs.pop('headers', {}) + """ + GET requests on a given URL that acts like `requests.get` except that + authentication to the API is automatically done and JSON response is + decoded + + :param url: (str) URL of the requests + :param: See `requests.get` params + :returns: (dict) The JSON-decoded result of the request + """ headers.update({ 'Authorization': 'Token {}'.format(self.get_token()) }) @@ -107,7 +142,15 @@ class Re2oAPIClient: return response.json() def post(self, url, headers={}, params={}, *args, **kwargs): - headers = kwargs.pop('headers', {}) + """ + POST requests on a given URL that acts like `requests.past` except + that authentication to the API is automatically done and JSON response + is decoded + + :param url: (str) URL of the requests + :param: See `requests.post` params + :returns: (dict) The JSON-decoded result of the request + """ headers.update({ 'Authorization': 'Token {}'.format(self.get_token()) }) @@ -118,6 +161,14 @@ class Re2oAPIClient: return response.json() def get_url_for(self, name, **kwargs): + """ + Retrieve the complete URL to use for a given endpoint's name + + :param name: The name of the endpoint to look for. + `re2oapi.exception.NameNotExists` is raised of the name does not + correspond to any endpoint + :param kwargs: A dict with the parameters to use to format the URL + """ return '{proto}://{host}{endpoint}'.format( proto=('https' if self.use_tls else 'http'), host=self.hostname,