예제 #1
0
 def _subtype_check(self, current, allowed_subtypes, types, function_name):
     if len(allowed_subtypes) == 1:
         # The easy case, we know up front what type
         # we need to validate.
         allowed_subtypes = allowed_subtypes[0]
         for element in current:
             actual_typename = type(element).__name__
             if actual_typename not in allowed_subtypes:
                 raise exceptions.JMESPathTypeError(
                     function_name, element, actual_typename, types)
     elif len(allowed_subtypes) > 1 and current:
         # Dynamic type validation.  Based on the first
         # type we see, we validate that the remaining types
         # match.
         first = type(current[0]).__name__
         for subtypes in allowed_subtypes:
             if first in subtypes:
                 allowed = subtypes
                 break
         else:
             raise exceptions.JMESPathTypeError(
                 function_name, current[0], first, types)
         for element in current:
             actual_typename = type(element).__name__
             if actual_typename not in allowed:
                 raise exceptions.JMESPathTypeError(
                     function_name, element, actual_typename, types)
 def keyfunc(x):
     result = interpreter.visit(expr_node, x)
     jmespath_type = self._convert_to_jmespath_type(result)
     if jmespath_type not in allowed_types:
         raise exceptions.JMESPathTypeError(function_name, result,
                                            jmespath_type,
                                            allowed_types)
     return result
예제 #3
0
 def keyfunc(x):
     result = expref.visit(expref.expression, x)
     actual_typename = type(result).__name__
     jmespath_type = self._convert_to_jmespath_type(actual_typename)
     # allowed_types is in term of jmespath types, not python types.
     if jmespath_type not in allowed_types:
         raise exceptions.JMESPathTypeError(
             function_name, result, jmespath_type, allowed_types)
     return result
예제 #4
0
 def _func_sort_by(self, array, expref):
     if not array:
         return array
     # sort_by allows for the expref to be either a number of
     # a string, so we have some special logic to handle this.
     # We evaluate the first array element and verify that it's
     # either a string of a number.  We then create a key function
     # that validates that type, which requires that remaining array
     # elements resolve to the same type as the first element.
     required_type = self._convert_to_jmespath_type(
         type(expref.visit(expref.expression, array[0])).__name__)
     if required_type not in ['number', 'string']:
         raise exceptions.JMESPathTypeError('sort_by', array[0],
                                            required_type,
                                            ['string', 'number'])
     keyfunc = self._create_key_func(expref, [required_type], 'sort_by')
     return list(sorted(array, key=keyfunc))
예제 #5
0
 def _type_check_single(self, current, types, function_name):
     # Type checking involves checking the top level type,
     # and in the case of arrays, potentially checking the types
     # of each element.
     allowed_types, allowed_subtypes = self._get_allowed_pytypes(types)
     # We're not using isinstance() on purpose.
     # The type model for jmespath does not map
     # 1-1 with python types (booleans are considered
     # integers in python for example).
     actual_typename = type(current).__name__
     if actual_typename not in allowed_types:
         raise exceptions.JMESPathTypeError(
             function_name, current,
             self._convert_to_jmespath_type(actual_typename), types)
     # If we're dealing with a list type, we can have
     # additional restrictions on the type of the list
     # elements (for example a function can require a
     # list of numbers or a list of strings).
     # Arrays are the only types that can have subtypes.
     if allowed_subtypes:
         self._subtype_check(current, allowed_subtypes,
                             types, function_name)
예제 #6
0
 def _func_group_dict_by(self, arg, expref):
     if not arg:
         return arg
     # group_dict_by allows for the expref to be either a number of
     # a string, so we have some special logic to handle this.
     # We evaluate the first array element and verify that it's
     # either a string of a number.  We then create a key function
     # that validates that type, which requires that remaining array
     # elements resolve to the same type as the first element.
     lookup = list(list(arg.items())[0])
     required_type = self._convert_to_jmespath_type(
         type(expref.visit(expref.expression, lookup)).__name__)
     if required_type not in ['number', 'string']:
         raise exceptions.JMESPathTypeError(
             'group_by', lookup, required_type, ['string', 'number'])
     keyfunc = self._create_key_func(expref, [required_type], 'group_by')
     # Jmespath works only on lists, not tuples:
     unpacked_dict = [[k, v] for k, v in arg.items()]
     return {
         grouper: {k: v for k, v in list(grouping)}
         for grouper, grouping in groupby(unpacked_dict, key=keyfunc)
     }