Ejemplo n.º 1
0
 def _value_expression(self, inventory):
     results = {}
     path = DictPath(self._delimiter, self._expr[0][1]).drop_first()
     for node, items in inventory.iteritems():
         if path.exists_in(items):
             results[node] = copy.deepcopy(self._resolve(path, items))
     return results
Ejemplo n.º 2
0
class InvItem(item.Item):

    type = item.ItemTypes.INV_QUERY

    def __init__(self, newitem, settings):
        super(InvItem, self).__init__(newitem.render(None, None), settings)
        self.needs_all_envs = False
        self.has_inv_query = True
        self.ignore_failed_render = (
            self._settings.inventory_ignore_failed_render)
        self._parse_expression(self.contents)

    def _parse_expression(self, expr):
        parser = parser_funcs.get_expression_parser()
        try:
            tokens = parser.parseString(expr).asList()
        except pp.ParseException as e:
            raise ParseError(e.msg, e.line, e.col, e.lineno)

        if len(tokens) == 2:  # options are set
            passed_opts = [x[1] for x in tokens.pop(0)]
            self.ignore_failed_render = parser_funcs.IGNORE_ERRORS in passed_opts
            self.needs_all_envs = parser_funcs.ALL_ENVS in passed_opts
        elif len(tokens) > 2:
            raise ExpressionError('Failed to parse %s' % str(tokens),
                                  tbFlag=False)
        self._expr_type = tokens[0][0]
        self._expr = list(tokens[0][1])

        if self._expr_type == parser_funcs.VALUE:
            self._value_path = DictPath(self._settings.delimiter,
                                        self._expr[0][1]).drop_first()
            self._question = LogicTest([], self._settings.delimiter)
            self.refs = []
            self.inv_refs = [self._value_path]
        elif self._expr_type == parser_funcs.TEST:
            self._value_path = DictPath(self._settings.delimiter,
                                        self._expr[0][1]).drop_first()
            self._question = LogicTest(self._expr[2:],
                                       self._settings.delimiter)
            self.refs = self._question.refs
            self.inv_refs = self._question.inv_refs
            self.inv_refs.append(self._value_path)
        elif self._expr_type == parser_funcs.LIST_TEST:
            self._value_path = None
            self._question = LogicTest(self._expr[1:],
                                       self._settings.delimiter)
            self.refs = self._question.refs
            self.inv_refs = self._question.inv_refs
        else:
            msg = 'Unknown expression type: %s'
            raise ExpressionError(msg % self._expr_type, tbFlag=False)

    @property
    def has_references(self):
        return len(self._question.refs) > 0

    def get_references(self):
        return self._question.refs

    def assembleRefs(self, context):
        return

    def get_inv_references(self):
        return self.inv_refs

    def _resolve(self, path, dictionary):
        try:
            return path.get_value(dictionary)
        except KeyError as e:
            raise ResolveError(str(path))

    def _value_expression(self, inventory):
        results = {}
        for name, node in iteritems(inventory):
            if self.needs_all_envs or node.env_matches:
                if self._value_path.exists_in(node.items):
                    answer = self._resolve(self._value_path, node.items)
                    results[name] = copy.deepcopy(answer)
        return results

    def _test_expression(self, context, inventory):
        if self._value_path is None:
            msg = 'Failed to render %s'
            raise ExpressionError(msg % str(self), tbFlag=False)

        results = {}
        for name, node in iteritems(inventory):
            if self.needs_all_envs or node.env_matches:
                if (self._question.value(context, node.items)
                        and self._value_path.exists_in(node.items)):
                    answer = self._resolve(self._value_path, node.items)
                    results[name] = copy.deepcopy(answer)
        return results

    def _list_test_expression(self, context, inventory):
        results = []
        for name, node in iteritems(inventory):
            if self.needs_all_envs or node.env_matches:
                if self._question.value(context, node.items):
                    results.append(name)
        results.sort()
        return results

    def render(self, context, inventory):
        if self._expr_type == parser_funcs.VALUE:
            return self._value_expression(inventory)
        elif self._expr_type == parser_funcs.TEST:
            return self._test_expression(context, inventory)
        elif self._expr_type == parser_funcs.LIST_TEST:
            return self._list_test_expression(context, inventory)
        raise ExpressionError('Failed to render %s' % str(self), tbFlag=False)

    def __str__(self):
        return ' '.join(str(j) for i, j in self._expr)

    def __repr__(self):
        # had to leave it here for now as the behaviour differs from basic
        return 'InvItem(%r)' % self._expr
Ejemplo n.º 3
0
class InvItem(Item):

    def _get_parser():

        def _object(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_OBJ, token)

        def _integer(string, location, tokens):
            try:
                token = int(tokens[0])
            except ValueError:
                token = tokens[0]
            tokens[0] = (_OBJ, token)

        def _number(string, location, tokens):
            try:
                token = float(tokens[0])
            except ValueError:
                token = tokens[0]
            tokens[0] = (_OBJ, token)

        def _option(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_OPTION, token)

        def _test(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_TEST, token)

        def _logical(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_LOGICAL, token)

        def _if(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_IF, token)

        def _expr_var(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_VALUE, token)

        def _expr_test(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_TEST, token)

        def _expr_list_test(string, location, tokens):
            token = tokens[0]
            tokens[0] = (_LIST_TEST, token)

        white_space = pp.White().suppress()
        end = pp.StringEnd()
        ignore_errors = pp.CaselessLiteral(_IGNORE_ERRORS)
        all_envs = pp.CaselessLiteral(_ALL_ENVS)
        option = (ignore_errors | all_envs).setParseAction(_option)
        options = pp.Group(pp.ZeroOrMore(option + white_space))
        operator_test = (pp.Literal(_EQUAL) | pp.Literal(_NOT_EQUAL)).setParseAction(_test)
        operator_logical = (pp.CaselessLiteral(_AND) | pp.CaselessLiteral(_OR)).setParseAction(_logical)
        begin_if = pp.CaselessLiteral(_IF, ).setParseAction(_if)
        obj = pp.Word(pp.printables).setParseAction(_object)
        integer = pp.Word('0123456789-').setParseAction(_integer)
        number = pp.Word('0123456789-.').setParseAction(_number)
        item = integer | number | obj
        single_test = white_space + item + white_space + operator_test + white_space + item
        additional_test = white_space + operator_logical + single_test
        expr_var = pp.Group(obj + pp.Optional(white_space) + end).setParseAction(_expr_var)
        expr_test = pp.Group(obj + white_space + begin_if + single_test + pp.ZeroOrMore(additional_test) + end).setParseAction(_expr_test)
        expr_list_test = pp.Group(begin_if + single_test + pp.ZeroOrMore(additional_test) + end).setParseAction(_expr_list_test)
        expr = (expr_test | expr_var | expr_list_test)
        line = options + expr + end
        return line

    _parser = _get_parser()

    def __init__(self, item, settings):
        self.type = Item.INV_QUERY
        self._settings = settings
        self._needs_all_envs = False
        self._ignore_failed_render = self._settings.inventory_ignore_failed_render
        self._expr_text = item.render(None, None)
        self._parse_expression(self._expr_text)

    def _parse_expression(self, expr):
        try:
            tokens = InvItem._parser.parseString(expr).asList()
        except pp.ParseException as e:
            raise ParseError(e.msg, e.line, e.col, e.lineno)

        if len(tokens) == 1:
            self._expr_type = tokens[0][0]
            self._expr = list(tokens[0][1])
        elif len(tokens) == 2:
            for opt in tokens[0]:
                if opt[1] == _IGNORE_ERRORS:
                    self._ignore_failed_render = True
                elif opt[1] == _ALL_ENVS:
                    self._needs_all_envs = True
            self._expr_type = tokens[1][0]
            self._expr = list(tokens[1][1])
        else:
            raise ExpressionError('Failed to parse %s' % str(tokens), tbFlag=False)

        if self._expr_type == _VALUE:
            self._value_path = DictPath(self._settings.delimiter, self._expr[0][1]).drop_first()
            self._question = Question([], self._settings.delimiter)
            self._refs = []
            self._inv_refs = [ self._value_path ]
        elif self._expr_type == _TEST:
            self._value_path = DictPath(self._settings.delimiter, self._expr[0][1]).drop_first()
            self._question = Question(self._expr[2:], self._settings.delimiter)
            self._refs = self._question.refs()
            self._inv_refs = self._question.inv_refs()
            self._inv_refs.append(self._value_path)
        elif self._expr_type == _LIST_TEST:
            self._value_path = None
            self._question = Question(self._expr[1:], self._settings.delimiter)
            self._refs = self._question.refs()
            self._inv_refs = self._question.inv_refs()
        else:
            raise ExpressionError('Unknown expression type: %s' % self._expr_type, tbFlag=False)

    def assembleRefs(self, context):
        return

    def contents(self):
        return self._expr_text

    def has_inv_query(self):
        return True

    def has_references(self):
        return len(self._question.refs()) > 0

    def get_references(self):
        return self._question.refs()

    def get_inv_references(self):
        return self._inv_refs

    def needs_all_envs(self):
        return self._needs_all_envs

    def ignore_failed_render(self):
        return self._ignore_failed_render

    def _resolve(self, path, dictionary):
        try:
            return path.get_value(dictionary)
        except KeyError as e:
            raise ResolveError(str(path))

    def _value_expression(self, inventory):
        results = {}
        for (node, items) in iteritems(inventory):
            if self._value_path.exists_in(items):
                results[node] = copy.deepcopy(self._resolve(self._value_path, items))
        return results

    def _test_expression(self, context, inventory):
        if self._value_path is None:
            ExpressionError('Failed to render %s' % str(self), tbFlag=False)

        results = {}
        for (node, items) in iteritems(inventory):
            if self._question.value(context, items) and self._value_path.exists_in(items):
                results[node] = copy.deepcopy(self._resolve(self._value_path, items))
        return results

    def _list_test_expression(self, context, inventory):
        results = []
        for (node, items) in iteritems(inventory):
            if self._question.value(context, items):
                results.append(node)
        return results

    def render(self, context, inventory):
        if self._expr_type == _VALUE:
            return self._value_expression(inventory)
        elif self._expr_type == _TEST:
            return self._test_expression(context, inventory)
        elif self._expr_type == _LIST_TEST:
            return self._list_test_expression(context, inventory)
        raise ExpressionError('Failed to render %s' % str(self), tbFlag=False)

    def __str__(self):
        return ' '.join(str(j) for i,j in self._expr)

    def __repr__(self):
        return 'InvItem(%r)' % self._expr