From cbe37ab18684fa456a4fb369cf89a460550a390a Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 15 Nov 2024 16:37:47 +0100 Subject: [PATCH] Added pagination to fetch_all --- .gitignore | 3 +++ gazu/client.py | 57 +++++++++++++++++++++++++++++++++++--------------- 2 files changed, 43 insertions(+), 17 deletions(-) diff --git a/.gitignore b/.gitignore index 72364f99..3db1597b 100644 --- a/.gitignore +++ b/.gitignore @@ -87,3 +87,6 @@ ENV/ # Rope project settings .ropeproject + +# PyCharm settings +.idea diff --git a/gazu/client.py b/gazu/client.py index 03de8d57..8e819650 100644 --- a/gazu/client.py +++ b/gazu/client.py @@ -192,7 +192,7 @@ def get_full_url(path, client=default_client): def build_path_with_params(path, params): """ - Add params to a path using urllib encoding + Add params to a path using urllib encoding. Args: path (str): The url base path @@ -204,10 +204,14 @@ def build_path_with_params(path, params): if not params: return path - if hasattr(urllib, "urlencode"): - path = "%s?%s" % (path, urllib.urlencode(params)) - else: - path = "%s?%s" % (path, urllib.parse.urlencode(params)) + urlencode = urllib.urlencode if hasattr(urllib, "urlencode") else urllib.parse.urlencode + query_string = urlencode(params) + + if query_string: + # Support base paths that already contain query parameters. + path += '&' if '?' in path else '?' + path += query_string + return path @@ -303,9 +307,7 @@ def delete(path, params=None, client=default_client): return response.text -def get_message_from_response( - response, default_message="No additional information" -): +def get_message_from_response(response, default_message="No additional information"): """ A utility function that handles Zou's inconsistent message keys. For a given request, checks if any error messages or regular messages were given and returns their value. @@ -321,7 +323,7 @@ def get_message_from_response( message = default_message message_json = response.json() - for key in ["error", "message"]: + for key in ['error', 'message']: if message_json.get(key): message = message_json[key] break @@ -384,15 +386,13 @@ def check_status(request, path, client=None): raise elif status_code in [500, 502]: try: - print("A server error occured!\n") stacktrace = request.json().get( "stacktrace", "No stacktrace sent by the server" ) + message = get_message_from_response(response=request, + default_message="No message sent by the server") + print("A server error occured!\n") print("Server stacktrace:\n%s" % stacktrace) - message = get_message_from_response( - response=request, - default_message="No message sent by the server", - ) print("Error message:\n%s\n" % message) except Exception: print(request.text) @@ -400,16 +400,39 @@ def check_status(request, path, client=None): return status_code, False -def fetch_all(path, params=None, client=default_client): +def fetch_all(path, params=None, client=default_client, paginated=False): """ Args: path (str): The path for which we want to retrieve all entries. + paginated (bool): Will query the database in subsequently in batches of 100 entries at a time. Returns: list: All entries stored in database for a given model. You can add a filter to the model name like this: "tasks?project_id=project-id" """ - return get(url_path_join("data", path), params=params, client=client) + + if not params: + params = {} + if paginated: + params['page'] = 1 + + response = get(url_path_join("data", path), params=params, client=client) + + # Return non-paginated responses. + if not isinstance(response, dict) or not response.get('data', None): + return response + + total_pages = response.get('nb_pages', 1) + current_page = response.get('page', 1) + results = response.get('data', []) + + if current_page != total_pages: + for page in range(2, total_pages + 1): + response = get(url_path_join("data", path), params={'page': page}, client=client) + offset = response.get('offset', len(results)) + results = results[:offset] + [r for r in response.get('data', [])] + + return results def fetch_first(path, params=None, client=default_client): @@ -501,7 +524,7 @@ def upload(path, file_path, data={}, extra_files=[], client=default_client): print(response.text) raise - result_message = get_message_from_response(response, default_message="") + result_message = get_message_from_response(response, default_message='') if result_message: raise UploadFailedException(result_message)