diff --git a/common/filter_order_handler.py b/common/filter_order_handler.py index c190e314..dac99a2c 100644 --- a/common/filter_order_handler.py +++ b/common/filter_order_handler.py @@ -1,3 +1,10 @@ +from common.icat.filters import ( + PythonICATLimitFilter, + PythonICATSkipFilter, + PythonICATOrderFilter, +) + + class FilterOrderHandler(object): """ The FilterOrderHandler takes in filters, sorts them according to the order of @@ -32,3 +39,65 @@ def apply_filters(self, query): for filter in self.filters: filter.apply_filter(query) + + def merge_python_icat_limit_skip_filters(self): + """ + When there are both limit and skip filters in a request, merge them into the + limit filter and remove the skip filter from the instance + """ + + if any( + isinstance(icat_filter, PythonICATSkipFilter) + for icat_filter in self.filters + ) and any( + isinstance(icat_filter, PythonICATLimitFilter) + for icat_filter in self.filters + ): + # Merge skip and limit filter into a single limit filter + for icat_filter in self.filters: + if isinstance(icat_filter, PythonICATSkipFilter): + skip_filter = icat_filter + request_skip_value = icat_filter.skip_value + + if isinstance(icat_filter, PythonICATLimitFilter): + limit_filter = icat_filter + + if skip_filter and limit_filter: + log.info("Merging skip filter with limit filter") + limit_filter.skip_value = skip_filter.skip_value + log.info("Removing skip filter from list of filters") + self.remove_filter(skip_filter) + log.debug("Filters: %s", self.filters) + + def clear_python_icat_order_filters(self): + """ + Checks if any order filters have been added to the request and resets the + variable used to manage which attribute(s) to use for sorting results. + + A reset is required because Python ICAT overwrites (as opposed to appending to + it) the query's order list every time one is added to the query. + """ + + if any( + isinstance(icat_filter, PythonICATOrderFilter) + for icat_filter in self.filters + ): + PythonICATOrderFilter.result_order = [] + + def manage_icat_filters(self, filters, query): + """ + Utility function to call other functions in this class, used to manage filters + when using the Python ICAT backend. These steps are the same with the different + types of requests that utilise filters, therefore this function helps to reduce + code duplication + + :param filters: The list of filters that will be applied to the query + :type filters: List of specific implementations :class:`QueryFilter` + :param query: ICAT query which will fetch the data at a later stage + :type query: :class:`icat.query.Query` + """ + + self.add_filters(filters) + self.merge_python_icat_limit_skip_filters() + self.clear_python_icat_order_filters() + self.apply_filters(query) diff --git a/common/icat/helpers.py b/common/icat/helpers.py index 826546c0..1c5c7cb0 100644 --- a/common/icat/helpers.py +++ b/common/icat/helpers.py @@ -24,13 +24,7 @@ from common.filter_order_handler import FilterOrderHandler from common.date_handler import DateHandler from common.constants import Constants -from common.icat.filters import ( - PythonICATLimitFilter, - PythonICATWhereFilter, - PythonICATSkipFilter, - PythonICATOrderFilter, -) - +from common.icat.filters import PythonICATLimitFilter, PythonICATWhereFilter log = logging.getLogger() @@ -621,10 +615,7 @@ def get_entity_with_filters(client, table_name, filters): query = icat_query(client, selected_entity_name) filter_handler = FilterOrderHandler() - filter_handler.add_filters(filters) - merge_limit_skip_filters(filter_handler) - clear_order_filters(filter_handler.filters) - filter_handler.apply_filters(query.query) + filter_handler.manage_icat_filters(filters, query.query) data = query.execute_query(client, True) @@ -634,53 +625,6 @@ def get_entity_with_filters(client, table_name, filters): return data -def merge_limit_skip_filters(filter_handler): - """ - When there are both limit and skip filters in a request, merge them into the limit - filter and remove the skip filter from `filter_handler` - - :param filter_handler: The filter handler to apply the filters - :param filters: The filters to be applied - """ - - if any( - isinstance(filter, PythonICATSkipFilter) for filter in filter_handler.filters - ) and any( - isinstance(filter, PythonICATLimitFilter) for filter in filter_handler.filters - ): - # Merge skip and limit filter into a single limit filter - for filter in filter_handler.filters: - if isinstance(filter, PythonICATSkipFilter): - skip_filter = filter - request_skip_value = filter.skip_value - - if isinstance(filter, PythonICATLimitFilter): - limit_filter = filter - - if skip_filter and limit_filter: - log.info("Merging skip filter with limit filter") - limit_filter.skip_value = skip_filter.skip_value - log.info("Removing skip filter from list of filters") - filter_handler.remove_filter(skip_filter) - log.debug("Filters: %s", filter_handler.filters) - - -def clear_order_filters(filters): - """ - Checks if any order filters have been added to the request and resets the variable - used to manage which attribute(s) to use for sorting results. - - A reset is required because Python ICAT overwrites (as opposed to appending to it) - the query's order list every time one is added to the query. - - :param filters: The list of filters to be applied to the request - :type filters: List of specific implementations :class:`QueryFilter` - """ - - if any(isinstance(filter, PythonICATOrderFilter) for filter in filters): - PythonICATOrderFilter.result_order = [] - - def get_count_with_filters(client, table_name, filters): """ Get the number of results of a given entity, based on the filters provided in the @@ -705,10 +649,7 @@ def get_count_with_filters(client, table_name, filters): query = icat_query(client, selected_entity_name, aggregate="COUNT") filter_handler = FilterOrderHandler() - filter_handler.add_filters(filters) - merge_limit_skip_filters(filter_handler) - clear_order_filters(filter_handler.filters) - filter_handler.apply_filters(query.query) + filter_handler.manage_icat_filters(filters, query.query) data = query.execute_query(client, True)