From 65c137236bfd7d258797dc387a3b5b1390b373af Mon Sep 17 00:00:00 2001 From: Maaike Zijderveld Date: Thu, 23 Sep 2021 18:46:56 +0200 Subject: [PATCH 1/3] Add retries, get_all function and get all emails of person function --- pipedrive/client.py | 66 +++++++++++++++++++++++++++++++++++++++++++- pipedrive/persons.py | 6 +++- 2 files changed, 70 insertions(+), 2 deletions(-) diff --git a/pipedrive/client.py b/pipedrive/client.py index dfdf2d4..1c962d8 100644 --- a/pipedrive/client.py +++ b/pipedrive/client.py @@ -1,3 +1,4 @@ +import time from urllib.parse import urlencode import requests @@ -79,6 +80,44 @@ def set_api_token(self, api_token): def _get(self, url, params=None, **kwargs): return self._request('get', url, params=params, **kwargs) + def _get_all(self, url, params=None, **kwargs): + more = True + start = 0 + final_response = {} + data = [] + while more: + if not params: + params = {"start": start} + else: + params['start'] = start + response = {} + try: + response = self._get(url, params, **kwargs) + except exceptions.BaseError: + # If something is already in final_response, return that, otherwise return the response. + if final_response: + return final_response + return response + + try: + data.extend(response['data']) + final_response = response + final_response['data'] = data + except KeyError: # No 'data' key found + if final_response: + return final_response + return response + + try: + if response['additional_data']['pagination']['more_items_in_collection']: + start = response['additional_data']['pagination']['next_start'] + else: + more = False + except KeyError: + more = False + + return final_response + def _post(self, url, **kwargs): return self._request('post', url, **kwargs) @@ -99,7 +138,32 @@ def _request(self, method, url, headers=None, params=None, **kwargs): _headers.update(headers) if params: _params.update(params) - return self._parse(requests.request(method, url, headers=_headers, params=_params, **kwargs)) + + if 'number_of_retries' in kwargs: + number_of_retries = kwargs.get('number_of_retries', 0) + intervaltime = kwargs.get('intervaltime', 500) + del kwargs['number_of_retries'] + + if 'intervaltime' in kwargs: + del kwargs['intervaltime'] + + while number_of_retries > 0: + try: + response = self._parse(requests.request(method, url, headers=_headers, params=_params, **kwargs)) + # No except, response is ok, return it. + return response + except (exceptions.BadRequestError, exceptions.UnauthorizedError, exceptions.NotFoundError, + exceptions.UnsupportedMediaTypeError, exceptions.UnprocessableEntityError, + exceptions.NotImplementedError, exceptions.TooManyRequestsError): + # Do not retry, just return the response. + return response + except (exceptions.ForbiddenError, exceptions.InternalServerError, exceptions.ServiceUnavailableError, + exceptions.UnknownError) as e: + # Retry! There is hope. + number_of_retries -= 1 + time.sleep(intervaltime / 1000.0) + else: + return self._parse(requests.request(method, url, headers=_headers, params=_params, **kwargs)) def _parse(self, response): status_code = response.status_code diff --git a/pipedrive/persons.py b/pipedrive/persons.py index 20f3c43..b8002d1 100644 --- a/pipedrive/persons.py +++ b/pipedrive/persons.py @@ -8,7 +8,7 @@ def get_person(self, person_id, **kwargs): def get_all_persons(self, params=None, **kwargs): url = 'persons' - return self._client._get(self._client.BASE_URL + url, params=params, **kwargs) + return self._client._get_all(self._client.BASE_URL + url, params=params, **kwargs) def get_persons_by_name(self, params=None, **kwargs): url = 'persons/find' @@ -33,3 +33,7 @@ def get_person_deals(self, person_id, **kwargs): def get_person_fields(self, params=None, **kwargs): url = 'personFields' return self._client._get(self._client.BASE_URL + url, params=params, **kwargs) + + def get_person_emails(self, person_id, params=None, **kwargs): + url = 'persons/{}/mailMessages'.format(person_id) + return self._client._get_all(self._client.BASE_URL + url, params=params, **kwargs) \ No newline at end of file From 7e57e6fed66b50e66b461af8b425a59153bfb1e5 Mon Sep 17 00:00:00 2001 From: Maaike Zijderveld Date: Fri, 24 Sep 2021 09:46:16 +0200 Subject: [PATCH 2/3] Default retry request 3 times --- pipedrive/client.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/pipedrive/client.py b/pipedrive/client.py index 1c962d8..3130edf 100644 --- a/pipedrive/client.py +++ b/pipedrive/client.py @@ -139,14 +139,16 @@ def _request(self, method, url, headers=None, params=None, **kwargs): if params: _params.update(params) + number_of_retries = kwargs.get('number_of_retries', 3) + intervaltime = kwargs.get('intervaltime', 500) + + # remove number of retries and intervaltime from kwargs, otherwise the requests call will fail. if 'number_of_retries' in kwargs: - number_of_retries = kwargs.get('number_of_retries', 0) - intervaltime = kwargs.get('intervaltime', 500) del kwargs['number_of_retries'] + if 'intervaltime' in kwargs: + del kwargs['intervaltime'] - if 'intervaltime' in kwargs: - del kwargs['intervaltime'] - + if number_of_retries: while number_of_retries > 0: try: response = self._parse(requests.request(method, url, headers=_headers, params=_params, **kwargs)) @@ -158,7 +160,7 @@ def _request(self, method, url, headers=None, params=None, **kwargs): # Do not retry, just return the response. return response except (exceptions.ForbiddenError, exceptions.InternalServerError, exceptions.ServiceUnavailableError, - exceptions.UnknownError) as e: + exceptions.UnknownError): # Retry! There is hope. number_of_retries -= 1 time.sleep(intervaltime / 1000.0) From a602806a21ae040b56a6268dc495255ad7a6660c Mon Sep 17 00:00:00 2001 From: Maaike Zijderveld Date: Fri, 1 Oct 2021 13:24:10 +0200 Subject: [PATCH 3/3] Fix some issues in request --- pipedrive/client.py | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/pipedrive/client.py b/pipedrive/client.py index 3130edf..be6be7b 100644 --- a/pipedrive/client.py +++ b/pipedrive/client.py @@ -100,6 +100,9 @@ def _get_all(self, url, params=None, **kwargs): return response try: + if response['data'] is None: + return response + data.extend(response['data']) final_response = response final_response['data'] = data @@ -156,9 +159,9 @@ def _request(self, method, url, headers=None, params=None, **kwargs): return response except (exceptions.BadRequestError, exceptions.UnauthorizedError, exceptions.NotFoundError, exceptions.UnsupportedMediaTypeError, exceptions.UnprocessableEntityError, - exceptions.NotImplementedError, exceptions.TooManyRequestsError): + exceptions.NotImplementedError, exceptions.TooManyRequestsError) as e: # Do not retry, just return the response. - return response + raise e except (exceptions.ForbiddenError, exceptions.InternalServerError, exceptions.ServiceUnavailableError, exceptions.UnknownError): # Retry! There is hope. @@ -169,14 +172,28 @@ def _request(self, method, url, headers=None, params=None, **kwargs): def _parse(self, response): status_code = response.status_code - if 'Content-Type' in response.headers and 'application/json' in response.headers['Content-Type']: - r = response.json() + + if 'Content-Type' in response.headers: + content_type = response.headers['Content-Type'] + else: + content_type = None + + is_json = False + + if content_type: + if content_type == 'application/json': + r = response.json() + is_json = True + elif 'text' in content_type: + r = response.text + else: + r = response.content else: - return response.text + r = response.text if not response.ok: error = None - if 'error' in r: + if is_json and 'error' in r: error = r['error'] if status_code == 400: raise exceptions.BadRequestError(error, response)