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
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
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