def format_free_text_search(self, **kwargs): """Build the free text search parameter using the search parameters""" query_params = {} for param, operations_config in self.config.free_text_search_operations.items(): union = operations_config["union"] wrapper = operations_config.get("wrapper", "{}") formatted_query = [] for operator, operands in operations_config["operations"].items(): # The Operator string is the operator wrapped with spaces operator = " {} ".format(operator) # Build the operation string by joining the formatted operands together # using the operation string operation_string = operator.join( format_metadata(operand, **kwargs) for operand in operands if any( kw in operand and val is not None for kw, val in kwargs.items() ) ) # Finally wrap the operation string as specified by the wrapper and add # it to the list of queries (only if the operation string is not empty) if operation_string: query = wrapper.format(operation_string) formatted_query.append(query) # Join the formatted query using the "union" config parameter, and then # wrap it with the Python format string specified in the "wrapper" config # parameter final_query = union.join(formatted_query) if len(operations_config["operations"]) > 1 and len(formatted_query) > 1: final_query = wrapper.format(query_params[param]) if final_query: query_params[param] = final_query return query_params
def format_string(key, str_to_format, **format_variables): """Format "{foo}" like string >>> format_string(None, "foo {bar}, {baz} ?", **{"bar": "qux", "baz": "quux"}) 'foo qux, quux ?' :param key: input item key :type key: str :param str_to_format: input item value, to be parsed :type str_to_format: str :returns: parsed value :rtype: str """ if isinstance(str_to_format, str): # eodag mappings function usage, e.g. '{foo#to_bar}' COMPLEX_QS_REGEX = re.compile(r"^(.+=)?([^=]*)({.+})+([^=&]*)$") if COMPLEX_QS_REGEX.match(str_to_format) and "#" in str_to_format: from eodag.api.product.metadata_mapping import format_metadata result = format_metadata(str_to_format, **format_variables) else: # defaultdict usage will return "" for missing keys in format_args try: result = str_to_format.format_map( defaultdict(str, **format_variables)) except TypeError: logger.error("Unable to format str=%s" % str_to_format) raise # try to convert string to python object try: return ast.literal_eval(result) except (SyntaxError, ValueError): return result else: return str_to_format
def build_query_string(self, *args, **kwargs): """Build The query string using the search parameters""" logger.debug("Building the query string that will be used for search") if "raise_errors" in kwargs.keys(): del kwargs["raise_errors"] # . not allowed in eodag_search_key, replaced with %2E kwargs = {k.replace(".", "%2E"): v for k, v in kwargs.items()} queryables = self.get_queryables(kwargs) query_params = {} # Get all the search parameters that are recognised as queryables by the # provider (they appear in the queryables dictionary) for eodag_search_key, provider_search_key in queryables.items(): user_input = kwargs[eodag_search_key] if self.COMPLEX_QS_REGEX.match(provider_search_key): parts = provider_search_key.split("=") if len(parts) == 1: formatted_query_param = format_metadata( provider_search_key, *args, **kwargs ) if "{{" in provider_search_key: # json query string (for POST request) update_nested_dict( query_params, json.loads(formatted_query_param) ) else: query_params[eodag_search_key] = formatted_query_param else: provider_search_key, provider_value = parts query_params.setdefault(provider_search_key, []).append( format_metadata(provider_value, *args, **kwargs) ) else: query_params[provider_search_key] = user_input # Now get all the literal search params (i.e params to be passed "as is" # in the search request) # ignore additional_params if it isn't a dictionary literal_search_params = getattr(self.config, "literal_search_params", {}) if not isinstance(literal_search_params, dict): literal_search_params = {} # Now add formatted free text search parameters (this is for cases where a # complex query through a free text search parameter is available for the # provider and needed for the consumer) literal_search_params.update(self.format_free_text_search(**kwargs)) for provider_search_key, provider_value in literal_search_params.items(): if isinstance(provider_value, list): query_params.setdefault(provider_search_key, []).extend(provider_value) else: query_params.setdefault(provider_search_key, []).append(provider_value) # Build the final query string, in one go without quoting it # (some providers do not operate well with urlencoded and quoted query strings) return ( query_params, urlencode( query_params, doseq=True, quote_via=lambda x, *_args, **_kwargs: x ), )