From 8627e8b6d7f1e94926dedcd286fcc5cc2fe6b20c Mon Sep 17 00:00:00 2001 From: Matthew Richards Date: Fri, 17 Jul 2020 10:12:01 +0000 Subject: [PATCH] #136: Allow get_entity_by_id() to return data in different formats - A flag is used to determine whether the data will be returned in a manner ready to be converted to JSON, or whether to leave it in a Python ICAT state ready to be edited/changed --- common/python_icat_backend.py | 2 +- common/python_icat_helpers.py | 50 ++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/common/python_icat_backend.py b/common/python_icat_backend.py index 295f3882..303bf2de 100644 --- a/common/python_icat_backend.py +++ b/common/python_icat_backend.py @@ -80,7 +80,7 @@ def count_with_filters(self, session_id, table, filters): @requires_session_id @queries_records def get_with_id(self, session_id, table, id): - return get_entity_by_id(self.client, table.__name__, id) + return get_entity_by_id(self.client, table.__name__, id, True) @requires_session_id @queries_records diff --git a/common/python_icat_helpers.py b/common/python_icat_helpers.py index 01ac5908..929bcd61 100644 --- a/common/python_icat_helpers.py +++ b/common/python_icat_helpers.py @@ -24,7 +24,7 @@ def wrapper_requires_session(*args, **kwargs): client = args[0].client # Find out if session has expired session_time = client.getRemainingMinutes() - log.info("Session time: {}".format(session_time)) + log.info(f"Session time: {session_time}") if session_time < 0: raise AuthenticationError("Forbidden") else: @@ -83,19 +83,26 @@ def construct_icat_query(client, entity_name, conditions=None, aggregate=None): return Query(client, entity_name, conditions=conditions, aggregate=aggregate) -def execute_icat_query(client, query): +def execute_icat_query(client, query, return_json_formattable=False): """ - Execute a previously created ICAT Query object + Execute a previously created ICAT Query object and return in the format specified by the + return_json_formattable flag :param client: ICAT client containing an authenticated user :type client: :class:`icat.client.Client` :param query: ICAT Query object to execute within Python ICAT :type query: :class:`icat.query.Query` - :return: Data (of type list) from the executed query in a format that can be converted - straight to JSON + :param return_json_formattable: Flag to determine whether the data from the query should be + returned as a list of data ready to be converted straight to JSON (i.e. if the data will be + used as a response for an API call) or whether to leave the data in a Python ICAT format + (i.e. if it's going to be manipulated at some point) + :type return_json_formattable_data: :class:`bool` + :return: Data (of type list) from the executed query """ + query_result = client.search(query) + if return_json_formattable: data = [] for result in query_result: dict_result = result.as_dict() @@ -105,8 +112,9 @@ def execute_icat_query(client, query): dict_result[key] = str(dict_result[key]) data.append(dict_result) - return data + else: + return query_result def get_python_icat_entity_name(client, database_table_name): @@ -141,9 +149,24 @@ def get_python_icat_entity_name(client, database_table_name): return python_icat_entity_name -def get_entity_by_id(client, table_name, id): +def create_condition(attribute_name, operator, value): + """ + Construct and return a Python dictionary containing a condition to be used in a Query object + + This currently only allows a single condition to be entered, this should be increased to allow + multiple conditions to be stored in the same dictionary + """ + + # TODO - Could this be turned into a class/done more elegantly? + condition = {} + condition[attribute_name] = f"{operator} '{value}'" + + return condition + + +def get_entity_by_id(client, table_name, id, return_json_formattable_data): """ - Gets a record of a given ID of the specified entity + Gets a record of a given ID from the specified entity :param client: ICAT client containing an authenticated user :type client: :class:`icat.client.Client` @@ -151,19 +174,20 @@ def get_entity_by_id(client, table_name, id): :type table_name: TODO :param id: ID number of the entity to retrieve :type id: :class:`int` + :param return_json_formattable_data: Flag to determine whether the data should be returned as a + list of data ready to be converted straight to JSON (i.e. if the data will be used as a + response for an API call) or whether to leave the data in a Python ICAT format + :type return_json_formattable_data: :class:`bool` :return: The record of the specified ID from the given entity """ # Set query condition for the selected ID - # TODO - Could this be moved out of this function for more generic conditions that'll be implemented later on? - id_condition = {} - operator = '=' - id_condition[attribute_name] = f"{operator} '{id}'" + id_condition = create_condition('id', '=', id) selected_entity_name = get_python_icat_entity_name(client, table_name) id_query = construct_icat_query(client, selected_entity_name, id_condition) - entity_by_id_data = execute_icat_query(client, id_query) + entity_by_id_data = execute_icat_query(client, id_query, return_json_formattable_data) return entity_by_id_data