def func_name2dotted_exec (node): logger.debug (ast.dump (node)) complete_name= pprint (node) while type (node) in (Attribute, Subscript): node= node.value return (node.id, complete_name)
def run_tree(self, tree, file_name, argv=None, params=None): logger.debug2('AST: %s', ast.dump(tree)) logger.debug2('code: \n%s', pprint(tree)) if params is not None: # we delay this assignment down to here because run_file(), # run_script() and run_tree() are entry points self.params = params code = compile(tree, file_name, 'exec') return self.run_code(code, file_name, argv)
def run_tree (self, tree, file_name, argv=None, params=None): logger.debug2 ('AST: %s', ast.dump (tree)) logger.debug2 ('code: \n%s', pprint (tree)) if params is not None: # we delay this assignment down to here because run_file(), # run_script() and run_tree() are entry points self.params= params code= compile (tree, file_name, 'exec') return self.run_code (code, file_name, argv)
def func_name2dotted_exec (node): logger.debug (ast.dump (node)) complete_name= str (pprint (node)) while type (node) in (Attribute, Subscript, Call): if type (node) in (Attribute, Subscript): node= node.value elif type (node) in (Call, ): node= node.func if type (node)==Name: return (node.id, complete_name) else: return (None, None)
def func_name2dotted_exec(node): logger.debug(ast.dump(node)) complete_name = str(pprint(node)) while type(node) in (Attribute, Subscript, Call): if type(node) in (Attribute, Subscript): node = node.value elif type(node) in (Call, ): node = node.func if type(node) == Name: return (node.id, complete_name) else: return (None, None)
def visit_Call (self, node): self.generic_visit (node) # Call(func=Name(id='b', ctx=Load()), args=[], keywords=[], starargs=None, # kwargs=None) # Call(func=Attribute(value=Name(id='test', ctx=Load()), attr='py', ctx=Load()), ...) # NOTE: what other things can be the func part? name= None unknown= False if type (node.func)==Name: name= func_name= node.func.id defs= self.known_names[func_name] if defs==0: unknown= True elif type (node.func)==Attribute: name, func_name= func_name2dotted_exec (node.func) # node.func is not completely formed by Names # so leave it alone if name is None: return node defs= self.known_names[name] if defs==0: unknown= True logger.debug2 ("%s: %s", name, unknown) if unknown: if not name in self.environ: # it's not one of the builtin functions # I guess I have no other option but to try to execute # something here... new_node= Call (func=Name (id='Command', ctx=Load ()), args=[Str (s=func_name)], keywords=[]) # check if the first parameter is a Command; if so, redirect # its output, remove it from the args and put it in the _in # kwarg if len (node.args)>0: first_arg= node.args[0] if is_executable (first_arg) and not has_keyword (first_arg, '_err'): out= keyword (arg='_out', value=Name (id='Pipe', ctx=Load ())) update_keyword (first_arg, out) bg= keyword (arg='_bg', value=Name (id='True', ctx=Load ())) update_keyword (first_arg, bg) node.args.pop (0) update_keyword (node, keyword (arg='_in', value=first_arg)) for arg in node.args: if is_option (arg): # ast_pprinter takes care of expressions kw= arg.keywords[0] logger.debug2 ("->>>kw: %s", ast.dump (kw)) kw.arg= str (pprint (kw.arg)) ast.copy_location (new_node, node) node.func= new_node ast.fix_missing_locations (node) else: # this is a normal function call # Call(func=Name(id='foo', ctx=Load()), # args=[Call(func=Name(id='o', ctx=Load()), # args=[], keywords=[keyword(arg='a', value=Num(n=42))], # starargs=None, kwargs=None)], # keywords=[], starargs=None, kwargs=None)) # the parser has converted all the keyword arguments to o(k=v) # we need to convert them back to keywords and apply Python's syntax rules new_args= [] used_keywords= set () first_kw= False for index, arg in enumerate (node.args): # NOTE: maybe o() can be left in its own namespace so it doesn't pollute if is_option (arg): kw_expr= arg.keywords[0].arg if not isinstance (kw_expr, ast.Name) and not isinstance (kw_expr, str): raise SyntaxError (self.file_name, node.lineno, node.col_offset, "keyword can't be an expression") if isinstance (kw_expr, ast.Name): kw_name= kw_expr.id else: kw_name= kw_expr # str if kw_name in used_keywords: raise SyntaxError (self.file_name, node.lineno, node.col_offset, "keyword argument repeated") # convert the expr into a str new_kw= keyword (kw_name, arg.keywords[0].value) node.keywords.append (new_kw) used_keywords.add (kw_name) first_kw= True else: if first_kw: raise SyntaxError (self.file_name, node.lineno, node.col_offset, "non-keyword arg after keyword arg") new_args.append (arg) node.args= new_args return node
def visit_Call(self, node): self.generic_visit(node) # Call(func=Name(id='b', ctx=Load()), args=[], keywords=[], starargs=None, # kwargs=None) # Call(func=Attribute(value=Name(id='test', ctx=Load()), attr='py', ctx=Load()), ...) # NOTE: what other things can be the func part? name = None unknown = False if type(node.func) == Name: name = func_name = node.func.id defs = self.known_names[func_name] if defs == 0: unknown = True elif type(node.func) == Attribute: name, func_name = func_name2dotted_exec(node.func) # node.func is not completely formed by Names # so leave it alone if name is None: return node defs = self.known_names[name] if defs == 0: unknown = True logger.debug2("%s: %s", name, unknown) if unknown: if not name in self.environ: # it's not one of the builtin functions # I guess I have no other option but to try to execute # something here... new_node = Call(func=Name(id='Command', ctx=Load()), args=[Str(s=func_name)], keywords=[]) # check if the first parameter is a Command; if so, redirect # its output, remove it from the args and put it in the _in # kwarg if len(node.args) > 0: first_arg = node.args[0] if is_executable(first_arg) and not has_keyword( first_arg, '_err'): out = keyword(arg='_out', value=Name(id='Pipe', ctx=Load())) update_keyword(first_arg, out) bg = keyword(arg='_bg', value=Name(id='True', ctx=Load())) update_keyword(first_arg, bg) node.args.pop(0) update_keyword(node, keyword(arg='_in', value=first_arg)) for arg in node.args: if is_option(arg): # ast_pprinter takes care of expressions kw = arg.keywords[0] logger.debug2("->>>kw: %s", ast.dump(kw)) kw.arg = str(pprint(kw.arg)) ast.copy_location(new_node, node) node.func = new_node ast.fix_missing_locations(node) else: # this is a normal function call # Call(func=Name(id='foo', ctx=Load()), # args=[Call(func=Name(id='o', ctx=Load()), # args=[], keywords=[keyword(arg='a', value=Num(n=42))], # starargs=None, kwargs=None)], # keywords=[], starargs=None, kwargs=None)) # the parser has converted all the keyword arguments to o(k=v) # we need to convert them back to keywords and apply Python's syntax rules new_args = [] used_keywords = set() first_kw = False for index, arg in enumerate(node.args): # NOTE: maybe o() can be left in its own namespace so it doesn't pollute if is_option(arg): kw_expr = arg.keywords[0].arg if not isinstance(kw_expr, ast.Name) and not isinstance( kw_expr, str): raise SyntaxError( self.file_name, node.lineno, node.col_offset, "keyword can't be an expression") if isinstance(kw_expr, ast.Name): kw_name = kw_expr.id else: kw_name = kw_expr # str if kw_name in used_keywords: raise SyntaxError(self.file_name, node.lineno, node.col_offset, "keyword argument repeated") # convert the expr into a str new_kw = keyword(kw_name, arg.keywords[0].value) node.keywords.append(new_kw) used_keywords.add(kw_name) first_kw = True else: if first_kw: raise SyntaxError( self.file_name, node.lineno, node.col_offset, "non-keyword arg after keyword arg") new_args.append(arg) node.args = new_args return node
def run_tree (self, tree, file_name, argv=None): logger.debug2 ('AST: %s', ast.dump (tree)) logger.debug2 ('code: \n%s', pprint (tree)) return self.run_code (compile (tree, file_name, 'exec'), file_name, argv)