Example #1
0
def dataset_query(request, app, data):
    try:
        if 'filters' not in data or not isinstance(data['filters'], dict):
            raise SuspiciousOperation('Filters must be a dictionary')
        filters = {}
        for attr, filter_obj in data['filters'].items():
            filters[attr] = BaseFilter.deserialize(filter_obj)

        # Empty list means query all attributes to the older versions of
        # the adminapi.
        if not data.get('restrict'):
            restrict = None
        else:
            restrict = data['restrict']

        order_by = data.get('order_by')

        return {
            'status': 'success',
            'result': execute_query(filters, restrict, order_by),
        }
    except (FilterValueError, ValidationError) as error:
        return {
            'status': 'error',
            'type': 'ValueError',
            'message': str(error),
        }
Example #2
0
    def __init__(self, filters=None, restrict=['hostname'], order_by=None):
        if filters is None:
            self._filters = None
            self._restrict = None
            self._order_by = None
            self._results = []
            return

        self._filters = {
            a: f if isinstance(f, BaseFilter) else BaseFilter(f)
            for a, f in filters.items()
        }

        self._restrict = restrict
        self._order_by = order_by
        self._results = None
Example #3
0
def parse_query(term, hostname=None):  # NOQA: C901
    parsed_args = parse_function_string(term, strict=True)
    if not parsed_args:
        return {}

    # If first token is not a key, we assume that a hostname is meant
    token, value = parsed_args[0]
    if token != 'key':
        if hostname:
            # We already parsed a hostname, so we don't expect another one
            raise DatatypeError("Garbled hostname: {0}".format(hostname))

        term_parts = term.split(None, 1)
        if len(term_parts) == 2:
            hostname_part, remaining_part = term_parts
            query_args = parse_query(remaining_part, hostname_part)
        else:
            hostname_part = term
            query_args = {}

        if any(x in hostname_part for x in _trigger_re_chars):
            hostname = Regexp(hostname_part)
        else:
            hostname = BaseFilter(hostname_part)

        if 'hostname' in query_args:
            query_args['hostname'] = Any(query_args['hostname'], hostname)
        else:
            query_args['hostname'] = hostname

        return query_args

    # Otherwise just parse all attributes
    query_args = {}
    stack = []
    call_depth = 0
    for arg in parsed_args:
        token, value = arg

        if token == 'key':
            if stack:
                query_args[stack[0][1]] = stack[1][1]
                stack = []
            stack.append(arg)

        elif token == 'func':
            # Do not allow functions without preceding key
            # if they are on top level (e.g. call_depth = 0)
            if not stack or (call_depth == 0 and stack[-1][0] != 'key'):
                raise DatatypeError(
                    'Invalid term: top level function requires '
                    'preceding attribute'
                )
            call_depth += 1
            stack.append(arg)

        elif token == 'endfunc':
            call_depth -= 1
            fn_args = []
            while True:
                s_token, s_value = stack.pop()
                if s_token == 'func':
                    break
                else:
                    fn_args.append(s_value)
            fn_args.reverse()

            for filter_class in filter_classes:
                if filter_class.__name__.lower() == s_value.lower():
                    try:
                        instance = filter_class(*fn_args)
                    except TypeError:
                        raise DatatypeError(
                            'Invalid function args ' + filter_class.__name__
                        )
                    break
            else:
                raise DatatypeError('Invalid function ' + s_value)
            stack.append(('instance', instance))

        elif token == 'literal':
            # Do not allow literals without key or function context
            if not stack or (call_depth == 0 and stack[-1][0] != 'key'):
                raise DatatypeError(
                    'Invalid term: Top level literals are not '
                    'allowed when attributes are used'
                )
            if call_depth == 0:
                stack.append(('literal', BaseFilter(value)))
            else:
                stack.append(('literal', value))

    if stack and stack[0][0] == 'key':
        if len(stack) != 2:
            raise DatatypeError(
                'Invalid term: Attribute requires one argument'
            )
        query_args[stack[0][1]] = stack[1][1]

    return query_args