def visit_bin_op_node(self, node: BinOpNode): left_operand = Ref() with self.consumer(lambda v: left_operand.set(v)): node.left_node.accept(self) right_operand = Ref() with self.consumer(lambda v: right_operand.set(v)): node.right_node.accept(self) op_func = self._bin_op_funcs.get(node.op_token.value, None) if op_func is None: raise PeekError( f'Unknown binary operator: {node.op_token.value!r}') self.consume(op_func(left_operand.get(), right_operand.get()))
def visit_let_node(self, node: LetNode): for kv_node in node.assignments_node.kv_nodes: lhs_chain = [] with self.consumer(lambda v: lhs_chain.append(v)): self._unwind_lhs(kv_node.key_node) rhs = Ref() with self.consumer(lambda v: rhs.set(v)): kv_node.value_node.accept(self) if len(lhs_chain) == 1: self.context[lhs_chain[0]] = rhs.get() else: if not lhs_chain[0] in self.context: raise PeekError(f'Unknown name: {lhs_chain[0]!r}') lhs = self.context[lhs_chain[0]] for x in lhs_chain[1:-1]: if isinstance(lhs, dict) or (isinstance(lhs, list) and isinstance(x, int)): lhs = lhs[x] else: raise PeekError( f'Invalid lhs for assignment: {lhs_chain}') x = lhs_chain[-1] if isinstance(lhs, dict) or (isinstance(lhs, list) and isinstance(x, int)): lhs[x] = rhs.get() else: raise PeekError(f'Invalid lhs for assignment: {lhs_chain}')
def visit_unary_op_node(self, node: UnaryOpNode): operand = Ref() with self.consumer(lambda v: operand.set(v)): node.operand_node.accept(self) op_func = self._unary_op_funcs.get(node.op_token.value, None) if op_func is None: raise PeekError(f'Unknown unary operator: {node.op_token.value!r}') self.consume(op_func(operand.get()))
def _map(app, values, ret): ret_nodes = app.parser.parse('return ' + ret['return'], log_level='WARNING') results = [] for value in values: app.vm.context['s'] = value v_ref = Ref() with app.vm.consumer(lambda v: v_ref.set(v)): ret_nodes[0].args_node.value_nodes[0].accept(app.vm) results.append(v_ref.get()) return results
def visit_dict_node(self, node: DictNode): d_ref = Ref() with self.consumer(lambda v: d_ref.set(v)): self._do_visit_dict_node(node, resolve_key_name=False) d = d_ref.get() if d.get('...', None) is not None: splat = d.pop('...') assert isinstance(splat, dict), f'Cannot splat type other than dict, got: {splat!r}' d.update(splat) self.consume(d)
def visit_func_call_node(self, node: FuncCallNode): if isinstance(node.name_node, NameNode): func = self.get_value(node.name_node.token.value) else: func_ref = Ref() with self.consumer(lambda v: func_ref.set(v)): node.name_node.accept(self) func = func_ref.get() if not callable(func): raise PeekError( f'{node.name_node!r} is not a callable, but {func!r}') func_symbols = Ref() with self.consumer(lambda v: func_symbols.set(v)): node.symbols_node.accept(self) func_args = Ref() with self.consumer(lambda v: func_args.set(v)): node.args_node.accept(self) for kv_node in node.kwargs_node.kv_nodes: assert isinstance(kv_node.key_node, NameNode), f'{kv_node.key_node!r}' func_kwargs = Ref() with self.consumer(lambda v: func_kwargs.set(v)): self._do_visit_dict_node(node.kwargs_node, resolve_key_name=False) kwargs = func_kwargs.get() if func_symbols.get(): kwargs['@'] = func_symbols.get() try: result = func(self.app, *func_args.get(), **kwargs) if node.is_stmt: self.app.display.info(result) else: self.consume(result) except Exception as e: _logger.exception( f'Error on invoking function: {node.name_node!r}') self.app.display.error(e)
def visit_for_in_node(self, node: ForInNode): var_name = node.item.token.value items_ref = Ref() with self.consumer(lambda v: items_ref.set(v)): node.items.accept(self) items = items_ref.get() if not isinstance(items, list): raise PeekError( f'For in loop must operator over a list, got {items!r}') for i in items: self.context[var_name] = i for n in node.suite: n.accept(self)
def visit_es_api_call_node(self, node: EsApiCallNode): if isinstance(node.path_node, TextNode): path = node.path else: path_ref = Ref() with self.consumer(lambda v: path_ref.set(v)): node.path_node.accept(self) path = path_ref.get() path = path if path.startswith('/') else ('/' + path) options = Ref() with self.consumer(lambda v: options.set(v)): self._do_visit_dict_node(node.options_node) options = options.get() if isinstance(node, EsApiCallInlinePayloadNode): dicts = [] with self.consumer(lambda v: dicts.append(v)): for dict_node in node.dict_nodes: dict_node.accept(self) lines = [json.dumps(d) for d in dicts] payload = ('\n'.join(lines) + '\n') if lines else None elif isinstance(node, EsApiCallFilePayloadNode): f_ref = Ref() with self.consumer(lambda v: f_ref.set(v)): node.file_node.accept(self) with open(os.path.expanduser(f_ref.get().strip())) as ins: payload = ins.read() if self.app.config.as_bool('parse_payload_file'): dicts = [] with self.consumer(lambda v: dicts.append(v)): # NOTE this reuses the parser from the main app. It is not a problem # because parser always finishes its job before returning. So in a # single thread execution model, we won't corrupt the internals. for pnode in self.app.parser.parse(payload, payload_only=True): self.execute_node(pnode) lines = [json.dumps(d) for d in dicts] payload = ('\n'.join(lines) + '\n') if lines else None elif not payload.endswith('\n'): payload += '\n' else: raise ValueError(f'Unknown node: {node!r}') conn = options.pop('conn') if 'conn' in options else None headers = options.pop('headers') if 'headers' in options else {} xoid = options.pop('xoid') if 'xoid' in options else None if xoid: headers['x-opaque-id'] = str(xoid) runas = options.pop('runas') if 'runas' in options else None if runas is not None: headers['es-security-runas-user'] = runas if conn is not None: es_client = self.app.es_client_manager.get_client(conn) else: es_client = self.app.es_client_manager.current quiet = options.pop('quiet', False) if options: self.app.display.error(f'Unknown options: {options}') return try: with warnings.catch_warnings(record=True) as ws: response = es_client.perform_request( node.method, _maybe_encode_date_math(path), payload, headers=headers if headers else None) for w in ws: if not quiet and self._should_show_warnings(w): self.app.display.warn(str(w.message)) self.context['_'] = _maybe_decode_json(response) if not quiet: self.app.display.info(response, header_text=self._get_header_text( conn, runas)) except Exception as e: if getattr(e, 'info', None) is not None and isinstance( getattr(e, 'status_code', None), int): self.context['_'] = _maybe_decode_json(e.info) if isinstance( e.info, str) else e.info self.app.display.info(e.info, header_text=self._get_header_text( conn, runas)) else: self.app.display.error(e, header_text=self._get_header_text( conn, runas)) _logger.exception(f'Error on ES API call: {node!r}')