From d88fc69e8e74e3a558933c4f1f305c56298b2099 Mon Sep 17 00:00:00 2001 From: Nilesh Pant Date: Tue, 5 Dec 2023 20:46:22 +0530 Subject: [PATCH 1/2] add support for travelperk sdk --- travelperksdk/__init__.py | 0 travelperksdk/apis/__init__.py | 0 travelperksdk/apis/invoices.py | 0 travelperksdk/core/__init__.py | 0 travelperksdk/core/client.py | 0 travelperksdk/core/helpers.py | 0 travelperksdk/core/schema/read_only.py | 0 travelperksdk/exceptions/__init__.py | 0 travelperksdk/exceptions/travekperk_exceptions.py | 0 travelperksdk/travelperksdk.py | 0 10 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 travelperksdk/__init__.py create mode 100644 travelperksdk/apis/__init__.py create mode 100644 travelperksdk/apis/invoices.py create mode 100644 travelperksdk/core/__init__.py create mode 100644 travelperksdk/core/client.py create mode 100644 travelperksdk/core/helpers.py create mode 100644 travelperksdk/core/schema/read_only.py create mode 100644 travelperksdk/exceptions/__init__.py create mode 100644 travelperksdk/exceptions/travekperk_exceptions.py create mode 100644 travelperksdk/travelperksdk.py diff --git a/travelperksdk/__init__.py b/travelperksdk/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/apis/__init__.py b/travelperksdk/apis/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/apis/invoices.py b/travelperksdk/apis/invoices.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/core/__init__.py b/travelperksdk/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/core/client.py b/travelperksdk/core/client.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/core/helpers.py b/travelperksdk/core/helpers.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/core/schema/read_only.py b/travelperksdk/core/schema/read_only.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/exceptions/__init__.py b/travelperksdk/exceptions/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/exceptions/travekperk_exceptions.py b/travelperksdk/exceptions/travekperk_exceptions.py new file mode 100644 index 00000000..e69de29b diff --git a/travelperksdk/travelperksdk.py b/travelperksdk/travelperksdk.py new file mode 100644 index 00000000..e69de29b From fe343b88503e6704f86ed74024128054b9fad20e Mon Sep 17 00:00:00 2001 From: Nilesh Pant <58652823+NileshPant1999@users.noreply.github.com> Date: Wed, 6 Dec 2023 15:31:56 +0530 Subject: [PATCH 2/2] add exceptions for travelperk (#93) --- travelperk/__init__.py | 5 + travelperk/apis/__init__.py | 5 + travelperk/apis/api_base.py | 67 ++++++++++++ travelperk/apis/invoice_profiles.py | 18 ++++ .../core}/__init__.py | 0 travelperk/core/client.py | 100 ++++++++++++++++++ {travelperksdk => travelperk}/core/helpers.py | 0 .../core/schema/read_only.py | 0 travelperk/exceptions.py | 44 ++++++++ travelperksdk/apis/__init__.py | 0 travelperksdk/apis/invoices.py | 0 travelperksdk/core/__init__.py | 0 travelperksdk/core/client.py | 0 travelperksdk/exceptions/__init__.py | 0 .../exceptions/travekperk_exceptions.py | 0 travelperksdk/travelperksdk.py | 0 16 files changed, 239 insertions(+) create mode 100644 travelperk/__init__.py create mode 100644 travelperk/apis/__init__.py create mode 100644 travelperk/apis/api_base.py create mode 100644 travelperk/apis/invoice_profiles.py rename {travelperksdk => travelperk/core}/__init__.py (100%) create mode 100644 travelperk/core/client.py rename {travelperksdk => travelperk}/core/helpers.py (100%) rename {travelperksdk => travelperk}/core/schema/read_only.py (100%) create mode 100644 travelperk/exceptions.py delete mode 100644 travelperksdk/apis/__init__.py delete mode 100644 travelperksdk/apis/invoices.py delete mode 100644 travelperksdk/core/__init__.py delete mode 100644 travelperksdk/core/client.py delete mode 100644 travelperksdk/exceptions/__init__.py delete mode 100644 travelperksdk/exceptions/travekperk_exceptions.py delete mode 100644 travelperksdk/travelperksdk.py diff --git a/travelperk/__init__.py b/travelperk/__init__.py new file mode 100644 index 00000000..fd7ed79e --- /dev/null +++ b/travelperk/__init__.py @@ -0,0 +1,5 @@ +from travelperk.core.client import Travelperk + +__all__ = [ + 'Travelperk' +] diff --git a/travelperk/apis/__init__.py b/travelperk/apis/__init__.py new file mode 100644 index 00000000..bc554169 --- /dev/null +++ b/travelperk/apis/__init__.py @@ -0,0 +1,5 @@ +from .invoice_profiles import InvoiceProfiles + +__all__ = [ + 'InvoiceProfiles' +] diff --git a/travelperk/apis/api_base.py b/travelperk/apis/api_base.py new file mode 100644 index 00000000..1d11b994 --- /dev/null +++ b/travelperk/apis/api_base.py @@ -0,0 +1,67 @@ +from typing import List, Dict +import requests +import json + +from travelperk.exceptions import * + +class ApiBase: + """The base class for all API classes.""" + + def __init__(self): + self.__access_token = None + self.__server_url = None + + def change_access_token(self, access_token): + """Change the old access token with the new one. + + Parameters: + access_token (str): The new access token. + """ + self.__access_token = access_token + + def set_server_url(self, server_url): + """Set the server URL dynamically upon creating a connection + + Parameters: + server_url(str): The current server URL + """ + self.__server_url = server_url + + def _get_request(self, object_type: str, api_url: str) -> List[Dict] or Dict: + """Create a HTTP GET request. + + Parameters: + api_url (str): Url for the wanted API. + + Returns: + A response from the request (dict). + """ + + api_headers = { + 'Authorization': 'Bearer {0}'.format(self.__access_token), + 'Accept': 'application/json', + 'Api-Version': '1' + } + + response = requests.get( + '{0}{1}'.format(self.__server_url, api_url), + headers=api_headers + ) + if response.status_code == 200: + result = json.loads(response.text) + return result[object_type] + + elif response.status_code == 400: + raise BadRequestError('Something wrong with the request body', response.text) + + elif response.status_code == 401: + raise UnauthorizedClientError('Wrong client secret or/and refresh token', response.text) + + elif response.status_code == 404: + raise NotFoundError('Client ID doesn\'t exist', response.text) + + elif response.status_code == 500: + raise InternalServerError('Internal server error', response.text) + + else: + raise TravelperkError('Error: {0}'.format(response.status_code), response.text) diff --git a/travelperk/apis/invoice_profiles.py b/travelperk/apis/invoice_profiles.py new file mode 100644 index 00000000..573d73e5 --- /dev/null +++ b/travelperk/apis/invoice_profiles.py @@ -0,0 +1,18 @@ +""" +Travelperk Invoices +""" +from .api_base import ApiBase + + +class InvoiceProfiles(ApiBase): + """Class for Invoice Profiles APIs.""" + + GET_INVOICE_PROFILES = '/profiles' + + def get_all(self): + """Get a list of the existing Invoice Profiles in the Organization. + + Returns: + List with dicts in Invoice Profile schema. + """ + return self._get_request('profiles', InvoiceProfiles.GET_INVOICE_PROFILES) diff --git a/travelperksdk/__init__.py b/travelperk/core/__init__.py similarity index 100% rename from travelperksdk/__init__.py rename to travelperk/core/__init__.py diff --git a/travelperk/core/client.py b/travelperk/core/client.py new file mode 100644 index 00000000..4f06cb6e --- /dev/null +++ b/travelperk/core/client.py @@ -0,0 +1,100 @@ +""" +Travelperk Python Class +""" +import json +import requests +from future.moves.urllib.parse import urlencode + +from travelperk.exceptions import * +from travelperk.apis.invoice_profiles import InvoiceProfiles + +class Travelperk: + """ + Travelperk Python Class + """ + + def __init__(self, client_id: str, client_secret: str, + refresh_token: str, environment: str): + """ + Initialize connection to Travelperk + :param client_id: Travelperk client_Id + :param client_secret: Travelperk client_secret + :param refresh_token: Travelperk refresh_token + :param environment: production or sandbox + """ + # Initializing variables + self.__client_id = client_id + self.__client_secret = client_secret + self.refresh_token = refresh_token + + if environment.lower() == 'sandbox': + self.__base_url = 'https://api.sandbox-travelperk.com' + self.__token_url = 'https://app.sandbox-travelperk.com/accounts/oauth2/token/' + elif environment.lower() == 'production': + self.__base_url = 'https://api.travelperk.com' + self.__token_url = 'https://app.travelperk.com/accounts/oauth2/token/' + else: + raise ValueError('environment can only be prodcution / sandbox') + + self.__access_token = None + + self.invoice_profiles = InvoiceProfiles() + + self.update_access_token() + self.update_server_url() + + def update_server_url(self): + """ + Update the server url in all API objects. + """ + base_url = self.__base_url + + self.invoice_profiles.set_server_url(base_url) + + def update_access_token(self): + """ + Update the access token and change it in all API objects. + """ + self.__get_access_token() + access_token = self.__access_token + + self.invoice_profiles.change_access_token(access_token) + + def __get_access_token(self): + """Get the access token using a HTTP post. + + Returns: + A new access token. + """ + + api_data = { + 'grant_type': 'refresh_token', + 'refresh_token': self.refresh_token, + 'client_id': self.__client_id, + 'client_secret': self.__client_secret + } + + headers = { + 'Content-Type': 'application/x-www-form-urlencoded' + } + + response = requests.post(url=self.__token_url, data=urlencode(api_data), headers=headers) + if response.status_code == 200: + auth = json.loads(response.text) + self.__access_token = auth['access_token'] + self.refresh_token = auth['refresh_token'] + + elif response.status_code == 400: + raise BadRequestError('Something wrong with the request body', response.text) + + elif response.status_code == 401: + raise UnauthorizedClientError('Wrong client secret or/and refresh token', response.text) + + elif response.status_code == 404: + raise NotFoundError('Client ID doesn\'t exist', response.text) + + elif response.status_code == 500: + raise InternalServerError('Internal server error', response.text) + + else: + raise TravelperkError('Error: {0}'.format(response.status_code), response.text) diff --git a/travelperksdk/core/helpers.py b/travelperk/core/helpers.py similarity index 100% rename from travelperksdk/core/helpers.py rename to travelperk/core/helpers.py diff --git a/travelperksdk/core/schema/read_only.py b/travelperk/core/schema/read_only.py similarity index 100% rename from travelperksdk/core/schema/read_only.py rename to travelperk/core/schema/read_only.py diff --git a/travelperk/exceptions.py b/travelperk/exceptions.py new file mode 100644 index 00000000..e741a970 --- /dev/null +++ b/travelperk/exceptions.py @@ -0,0 +1,44 @@ +""" +TravelPerk Exceptions +""" + + +class TravelperkError(Exception): + """The base exception class for Travelperk. + + Parameters: + msg (str): Short description of the error. + response: Error response from the API call. + """ + + def __init__(self, msg, response=None): + super(TravelperkError, self).__init__(msg) + self.message = msg + self.response = response + + def __str__(self): + return repr(self.message) + + +class UnauthorizedClientError(TravelperkError): + """Wrong client secret and/or refresh token, 401 error.""" + + +class ForbiddenClientError(TravelperkError): + """The user has insufficient privilege, 403 error.""" + + +class BadRequestError(TravelperkError): + """Some of the parameters are wrong, 400 error.""" + + +class NotFoundError(TravelperkError): + """Not found the item from URL, 404 error.""" + + +class InternalServerError(TravelperkError): + """The rest Travelperk errors, 500 error.""" + + +class RateLimitError(TravelperkError): + """To many requests, 429 error.""" diff --git a/travelperksdk/apis/__init__.py b/travelperksdk/apis/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/travelperksdk/apis/invoices.py b/travelperksdk/apis/invoices.py deleted file mode 100644 index e69de29b..00000000 diff --git a/travelperksdk/core/__init__.py b/travelperksdk/core/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/travelperksdk/core/client.py b/travelperksdk/core/client.py deleted file mode 100644 index e69de29b..00000000 diff --git a/travelperksdk/exceptions/__init__.py b/travelperksdk/exceptions/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/travelperksdk/exceptions/travekperk_exceptions.py b/travelperksdk/exceptions/travekperk_exceptions.py deleted file mode 100644 index e69de29b..00000000 diff --git a/travelperksdk/travelperksdk.py b/travelperksdk/travelperksdk.py deleted file mode 100644 index e69de29b..00000000