我们从Python开源项目中,提取了以下48个代码示例,用于说明如何使用ast.keyword()。
def formatList(node, field): if type(node) != list: return None s = "" nameMap = { "body" : "line", "targets" : "value", "values" : "value", "orelse" : "line", "names" : "name", "keys" : "key", "elts" : "value", "ops" : "operator", "comparators" : "value", "args" : "argument", "keywords" : "keyword" } # Find what type this is itemType = nameMap[field] if field in nameMap else "line" if len(node) > 1: s = "the " + itemType + "s: " for line in node: s += formatNode(line) + ", " elif len(node) == 1: s = "the " + itemType + " " f = formatNode(node[0]) if itemType == "line": f = "[" + f + "]" s += f return s
def channel_history(self, call): if isinstance(call.func, ast.Attribute): if call.func.attr == 'logs_from': if self.interactive and not prompt_change( 'A possible change was found to change logs_from to history.' ): return call dest = call.args[0] call.args = call.args[1:] if call.args: limit = call.args[0] call.keywords.append(ast.keyword(arg='limit', value=limit)) call.args = [] call.func.value = dest call.func.attr = 'history' stats_counter['call_changes'] += 1 return call
def stateful_wait_for(self, call): if isinstance(call.func, ast.Attribute): if call.func.attr in ['wait_for_message', 'wait_for_reaction']: if self.interactive and not prompt_change( 'A possible change was found to change {} into wait_for.'.format(call.func.attr) ): return call event = call.func.attr.split('_')[2] event = 'message' if event == 'message' else 'reaction_add' call.func.attr = 'wait_for' if call.args: timeout = call.args[0] call.args = [] call.keywords.append(ast.keyword(arg='timeout', value=timeout)) call.args.insert(0, ast.Str(s=event)) for kw in list(call.keywords): if kw.arg != 'check' and kw.arg != 'timeout': call.keywords.remove(kw) warnings.warn('wait_for change detected. Rewrite removes the author, channel, and content ' 'keyword arguments from this method.') stats_counter['call_changes'] += 1 return call
def test_classdef(self): def cls(bases=None, keywords=None, starargs=None, kwargs=None, body=None, decorator_list=None): if bases is None: bases = [] if keywords is None: keywords = [] if body is None: body = [ast.Pass()] if decorator_list is None: decorator_list = [] return ast.ClassDef("myclass", bases, keywords, starargs, kwargs, body, decorator_list) self.stmt(cls(bases=[ast.Name("x", ast.Store())]), "must have Load context") self.stmt(cls(keywords=[ast.keyword("x", ast.Name("x", ast.Store()))]), "must have Load context") self.stmt(cls(starargs=ast.Name("x", ast.Store())), "must have Load context") self.stmt(cls(kwargs=ast.Name("x", ast.Store())), "must have Load context") self.stmt(cls(body=[]), "empty body on ClassDef") self.stmt(cls(body=[None]), "None disallowed") self.stmt(cls(decorator_list=[ast.Name("x", ast.Store())]), "must have Load context")
def test_call(self): func = ast.Name("x", ast.Load()) args = [ast.Name("y", ast.Load())] keywords = [ast.keyword("w", ast.Name("z", ast.Load()))] stararg = ast.Name("p", ast.Load()) kwarg = ast.Name("q", ast.Load()) call = ast.Call(ast.Name("x", ast.Store()), args, keywords, stararg, kwarg) self.expr(call, "must have Load context") call = ast.Call(func, [None], keywords, stararg, kwarg) self.expr(call, "None disallowed") bad_keywords = [ast.keyword("w", ast.Name("z", ast.Store()))] call = ast.Call(func, args, bad_keywords, stararg, kwarg) self.expr(call, "must have Load context") call = ast.Call(func, args, keywords, ast.Name("z", ast.Store()), kwarg) self.expr(call, "must have Load context") call = ast.Call(func, args, keywords, stararg, ast.Name("w", ast.Store())) self.expr(call, "must have Load context")
def test_get_keywords(self): tree = compile_ast('func()') keywords = fatoptimizer.tools.get_keywords(tree.body[0].value) self.assertFalse(keywords) tree = compile_ast('func(x=1, y=2)') keywords = fatoptimizer.tools.get_keywords(tree.body[0].value) self.assertEqual(len(keywords), 2) self.assertIsInstance(keywords[0], ast.keyword) self.assertEqual(keywords[0].arg, 'x') self.assertIsInstance(keywords[1], ast.keyword) self.assertEqual(keywords[1].arg, 'y') tree = compile_ast('func(arg, *varargs, **kwargs)') keywords = fatoptimizer.tools.get_keywords(tree.body[0].value) self.assertEqual(len(keywords), 1) self.assertIsInstance(keywords[0], ast.keyword) self.assertIsNone(keywords[0].arg) tree = compile_ast('func()') with self.assertRaises(ValueError): fatoptimizer.tools.get_keywords(tree)
def to_source_any(n): """ Convert AST node to string, handling all node types, without fixing comments. """ try: return astor.to_source(n) except AttributeError: pass cls = n.__class__ if cls in astor.misc.all_symbols: return astor.misc.all_symbols[cls] def wrap(s): return '___' + s + '___' extra_d = {ast.Load: wrap('load'), ast.Store: wrap('store'), ast.Del: wrap('del'), ast.AugLoad: wrap('augload'), ast.AugStore: wrap('augstore'), ast.Param: wrap('param'), ast.keyword: wrap('keyword')} if cls in extra_d: return extra_d[cls] raise AttributeError('unknown node type {}'.format(cls))
def make_jinja_call(render_function_name, used_variables, string_value, ctx): used_defined_variables = ctx & used_variables undefined_variables = used_variables - ctx if len(undefined_variables) > 0: translation_error("Undefined variables: " + ", ".join(undefined_variables), string_value) used_parsers = used_defined_variables & set(FavaCode.get_known_parsers().keys()) used_user_variables = used_defined_variables - used_parsers keyword_arguments = [keyword(arg=key, value=Name(id=key, ctx=Load())) for key in used_user_variables] + \ [keyword(arg=key, value=_build_subscript(Name(id='shared', ctx=Load()), Name(id=key, ctx=Load()))) for key in used_parsers] return FavaCode( Call(func=Name(id=render_function_name, ctx=Load()), args=[Str(s=string_value)], keywords=keyword_arguments, starargs=None, kwargs=None), [], parsers=used_parsers)
def ast(self): """Create Python AST of this predicate. :return: AST representation of predicate """ # we could directly use db[task] in predicates, but predicates should not handle database errors, # so leave them on higher level (selinon) and index database before predicate is being called kwargs = [] # we want to avoid querying to database if possible, if a predicate does not require message, do not ask for it if self.requires_message(): # this can raise an exception if check was not run, since we are accessing storage that can be None kwargs.append(ast.keyword(arg='message', value=ast.Call(func=ast.Attribute(value=ast.Name(id='db', ctx=ast.Load()), attr='get', ctx=ast.Load()), args=[ast.Str(s=self._task_str_name())], keywords=[], starargs=None, kwargs=None))) if self.requires_node_args(): kwargs.append(ast.keyword(arg='node_args', value=ast.Name(id='node_args', ctx=ast.Load()))) kwargs.extend([ast.keyword(arg=k, value=ast.Str(s=v)) for k, v in self._args.items()]) return ast.Call(func=ast.Name(id=self._func.__name__, ctx=ast.Load()), args=[], starargs=None, kwargs=None, keywords=kwargs)
def get_sink_args(cfg_node): if type(cfg_node) == AssignmentNode: return get_sink_args(cfg_node.ast_node.value) elif type(cfg_node) == ReturnNode: return get_sink_args(cfg_node.ast_node.value) elif isinstance(cfg_node, Node): return get_sink_args(cfg_node.ast_node) elif isinstance(cfg_node, ast.Call): args = list() for arg in cfg_node.args + cfg_node.keywords: if isinstance(arg, ast.Name): args.append(arg.id) elif isinstance(arg, ast.Str): args.append(arg.s) elif isinstance(arg, ast.Call): args.extend(get_sink_args(arg)) elif isinstance(arg, ast.keyword): args.append(arg.value) elif isinstance(arg, ast.Attribute): import ast_helper args.append(ast_helper.get_call_names_as_string(arg)) else: raise Exception('Unexpected argument type:', type(arg)) return args elif isinstance(cfg_node, ast.Str): return None else: raise Exception('Unexpected node type:', type(cfg_node))
def visit_Call_35(self, call): """ visit `ast.Call` nodes on Python3.5 and after """ new_func, func_expl = self.visit(call.func) arg_expls = [] new_args = [] new_kwargs = [] for arg in call.args: res, expl = self.visit(arg) arg_expls.append(expl) new_args.append(res) for keyword in call.keywords: res, expl = self.visit(keyword.value) new_kwargs.append(ast.keyword(keyword.arg, res)) if keyword.arg: arg_expls.append(keyword.arg + "=" + expl) else: ## **args have `arg` keywords with an .arg of None arg_expls.append("**" + expl) expl = "%s(%s)" % (func_expl, ', '.join(arg_expls)) new_call = ast.Call(new_func, new_args, new_kwargs) res = self.assign(new_call) res_expl = self.explanation_param(self.display(res)) outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl) return res, outer_expl
def visit_Call_legacy(self, call): """ visit `ast.Call nodes on 3.4 and below` """ new_func, func_expl = self.visit(call.func) arg_expls = [] new_args = [] new_kwargs = [] new_star = new_kwarg = None for arg in call.args: res, expl = self.visit(arg) new_args.append(res) arg_expls.append(expl) for keyword in call.keywords: res, expl = self.visit(keyword.value) new_kwargs.append(ast.keyword(keyword.arg, res)) arg_expls.append(keyword.arg + "=" + expl) if call.starargs: new_star, expl = self.visit(call.starargs) arg_expls.append("*" + expl) if call.kwargs: new_kwarg, expl = self.visit(call.kwargs) arg_expls.append("**" + expl) expl = "%s(%s)" % (func_expl, ', '.join(arg_expls)) new_call = ast.Call(new_func, new_args, new_kwargs, new_star, new_kwarg) res = self.assign(new_call) res_expl = self.explanation_param(self.display(res)) outer_expl = "%s\n{%s = %s\n}" % (res_expl, res_expl, expl) return res, outer_expl # ast.Call signature changed on 3.5, # conditionally change which methods is named # visit_Call depending on Python version
def visit_Print(self, node): if node.__class__ != ast.Print: return node dummy_func = ast.Name(id="print", ctx=ast.Load()) keywords = [] if not node.nl: end = ast.keyword(arg="end", value=ast.Str(s="")) keywords.append(end) dummy_call = ast.Call(func=dummy_func, args=node.values, keywords=keywords, starargs=None, kwargs=None) return ast.Expr(value=dummy_call)
def stateful_send_file(self, call): if isinstance(call.func, ast.Attribute): if call.func.attr == 'send_file': if self.interactive and not prompt_change( 'A possible change was found to change send_file to send.' ): return call dest = call.args[0] send_as = call.args[1] content = None filename = None for kw in list(call.keywords): if kw.arg == 'filename': filename = kw if kw.arg == 'content': content = kw if filename is None: filename = ast.keyword(arg='filename', value=send_as) call.func.value = dest call.func.attr = 'send' call.args = [] if content: call.args.append(content.value) call.keywords = [] file_kw = ast.keyword() file_kw.arg = 'file' discord_file_call = ast.Call() discord_file_call.func = ast.Attribute(value=ast.Name(id='discord', ctx=ast.Load()), attr='File', ctx=ast.Load()) discord_file_call.args = [send_as, filename.value] discord_file_call.keywords = [] file_kw.value = discord_file_call call.keywords.append(file_kw) stats_counter['call_changes'] += 1 return call
def stateful_change_nickname(self, call): if isinstance(call.func, ast.Attribute): if call.func.attr == 'change_nickname': if self.interactive and not prompt_change( 'A possible change was found to make change_nickname into edit.' ): return call member = call.args[0] call.func.value = member call.func.attr = 'edit' nick = call.args[1] call.args = [] call.keywords = [ast.keyword(arg='nick', value=nick)] stats_counter['call_changes'] += 1 return call
def stateful_edit_message(self, call): if isinstance(call.func, ast.Attribute): if call.func.attr == 'edit_message': if self.interactive and not prompt_change( 'A possible change was found to make {} stateful.'.format(call.func.attr) ): return call call.func.attr = 'edit' message = call.args[0] call.func.value = message content = call.args[1] call.args = call.args[2:] call.keywords.append(ast.keyword(arg='content', value=content)) stats_counter['call_changes'] += 1 return call
def auto_symbol(tokens, local_dict, global_dict): """Inserts calls to ``Symbol`` for undefined variables.""" result = [] prevTok = (None, None) tokens.append((None, None)) # so zip traverses all tokens for tok, nextTok in zip(tokens, tokens[1:]): tokNum, tokVal = tok nextTokNum, nextTokVal = nextTok if tokNum == NAME: name = tokVal if (name in ['True', 'False', 'None'] or iskeyword(name) or name in local_dict # Don't convert attribute access or (prevTok[0] == OP and prevTok[1] == '.') # Don't convert keyword arguments or (prevTok[0] == OP and prevTok[1] in ('(', ',') and nextTokNum == OP and nextTokVal == '=')): result.append((NAME, name)) continue elif name in global_dict: obj = global_dict[name] if isinstance(obj, (Basic, type)) or callable(obj): result.append((NAME, name)) continue result.extend([ (NAME, 'Symbol'), (OP, '('), (NAME, repr(str(name))), (OP, ')'), ]) else: result.append((tokNum, tokVal)) prevTok = (tokNum, tokVal) return result
def visit_BinOp(self, node): if node.op.__class__ in self.operators: sympy_class = self.operators[node.op.__class__] right = self.visit(node.right) if isinstance(node.op, ast.Sub): right = ast.UnaryOp(op=ast.USub(), operand=right) elif isinstance(node.op, ast.Div): right = ast.Call( func=ast.Name(id='Pow', ctx=ast.Load()), args=[right, ast.UnaryOp(op=ast.USub(), operand=ast.Num(1))], keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))], starargs=None, kwargs=None ) new_node = ast.Call( func=ast.Name(id=sympy_class, ctx=ast.Load()), args=[self.visit(node.left), right], keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))], starargs=None, kwargs=None ) if sympy_class in ('Add', 'Mul'): # Denest Add or Mul as appropriate new_node.args = self.flatten(new_node.args, sympy_class) return new_node return node
def _is_star_star_kwarg(node): return isinstance(node, ast.keyword) and node.arg is None
def make_keywords(self, kwarg_nodes): if kwarg_nodes is None: kwarg_nodes = {} assert isinstance(kwarg_nodes, dict) return [ast.keyword(arg=name, value=value) for name, value in kwarg_nodes.items()]
def test_iter_child_nodes(self): node = ast.parse("spam(23, 42, eggs='leek')", mode='eval') self.assertEqual(len(list(ast.iter_child_nodes(node.body))), 4) iterator = ast.iter_child_nodes(node.body) self.assertEqual(next(iterator).id, 'spam') self.assertEqual(next(iterator).n, 23) self.assertEqual(next(iterator).n, 42) self.assertEqual(ast.dump(next(iterator)), "keyword(arg='eggs', value=Str(s='leek'))" )
def get_keywords(callsite): if not isinstance(callsite, ast.Call): raise ValueError("ast.Call expected, got %s" % type(callsite)) keywords = callsite.keywords if sys.version_info < (3, 5) and callsite.kwargs is not None: keywords = keywords.copy() keywords.append(ast.keyword(arg=None, value=callsite.kwargs)) return keywords
def apply_functions_xform(self, root): class Transformer(self.MyTransformer): def visit_FunctionDef(self_t, node): """ Don't recurse into user defined functions """ return node def visit_Module(self_t, node): class Visitor(ast.NodeVisitor): def visit_Module(self_v, node): self_v.defined_function_names = [] self_v.generic_visit(node) def visit_FunctionDef(self_v, node): self_v.defined_function_names.append(node.name) v = Visitor() v.visit(node) self_t.defined_function_names = v.defined_function_names self_t.generic_visit(node) return node def visit_Expr(self_t, node): if u.is_set_to_user_defined_function(node): var_name = node.value.func.value.id call_node = node.value.args[0] function_name = call_node.func.id assert function_name in self_t.defined_function_names, \ "Attempting to use undefined function: %s" % function_name call_node.args.insert(0, ast.Name(id="%s_tensor" % function_name)) call_node.func = ast.Attribute(value=ast.Name(id="tpt"), attr="apply_factor") scope = "%s_apply_factor" % var_name call_node.keywords = [ast.keyword(arg="scope", value=ast.Str(s=scope))] return node return Transformer().visit(root)
def __init__(self, operators=None, functions=None, names=None): """ Create the evaluator instance. Set up valid operators (+,-, etc) functions (add, random, get_val, whatever) and names. """ if not operators: operators = DEFAULT_OPERATORS if not functions: functions = DEFAULT_FUNCTIONS if not names: names = DEFAULT_NAMES self.operators = operators self.functions = functions self.names = names self.nodes = { ast.Num: self._eval_num, ast.Str: self._eval_str, ast.Name: self._eval_name, ast.UnaryOp: self._eval_unaryop, ast.BinOp: self._eval_binop, ast.BoolOp: self._eval_boolop, ast.Compare: self._eval_compare, ast.IfExp: self._eval_ifexp, ast.Call: self._eval_call, ast.keyword: self._eval_keyword, ast.Subscript: self._eval_subscript, ast.Attribute: self._eval_attribute, ast.Index: self._eval_index, ast.Slice: self._eval_slice, } # py3k stuff: if hasattr(ast, 'NameConstant'): self.nodes[ast.NameConstant] = self._eval_nameconstant elif isinstance(self.names, dict) and "None" not in self.names: self.names["None"] = None
def make_pydata_entry(key, value): return FavaCode( keyword(arg=key, value=value.get_ast()), [value])
def create_super_call(self, node): super_call = utils.create_ast('super().{}()'.format(node.name)).body[0] for arg in node.args.args[1:-len(node.args.defaults) or None]: super_call.value.args.append(ast.Name(id=arg.arg, ctx=ast.Load())) for arg, default in zip(node.args.args[-len(node.args.defaults):], node.args.defaults): super_call.value.keywords.append(ast.keyword(arg=arg.arg, value=default)) for arg, default in zip(node.args.kwonlyargs, node.args.kw_defaults): super_call.value.keywords.append(ast.keyword(arg=arg.arg, value=default)) if node.args.vararg: self.add_vararg_to_super_call(super_call, node.args.vararg) if node.args.kwarg: self.add_kwarg_to_super_call(super_call, node.args.kwarg) return super_call
def add_kwarg_to_super_call(super_call, kwarg): super_call.value.keywords.append(ast.keyword(arg=None, value=ast.Name(id=kwarg.arg, ctx=ast.Load())))
def peval_call(state, ctx, func, args=[], keywords=[]): assert all(type(arg) != ast.Starred for arg in args) assert all(kw.arg is not None for kw in keywords) keyword_expressions = [kw.value for kw in keywords] state, results = map_peval_expression( state, dict(func=func, args=args, keywords=keyword_expressions), ctx) if all_known_values_or_none(results): values = map_get_value(results) kwds = {kw.arg: value for kw, value in zip(keywords, values['keywords'])} success, value = try_eval_call( values['func'], args=values['args'], keywords=kwds) if success: return state, KnownValue(value=value) state, nodes = map_reify(state, results) # restoring the keyword list nodes['keywords'] = [ ast.keyword(arg=kw.arg, value=expr) for kw, expr in zip(keywords, nodes['keywords'])] return state, ast.Call(**nodes)
def jinja2_autoescape_false(context): # check type just to be safe if isinstance(context.call_function_name_qual, str): qualname_list = context.call_function_name_qual.split('.') func = qualname_list[-1] if 'jinja2' in qualname_list and func == 'Environment': for node in ast.walk(context.node): if isinstance(node, ast.keyword): # definite autoescape = False if (getattr(node, 'arg', None) == 'autoescape' and (getattr(node.value, 'id', None) == 'False' or getattr(node.value, 'value', None) is False)): return bandit.Issue( severity=bandit.HIGH, confidence=bandit.HIGH, text="Using jinja2 templates with autoescape=" "False is dangerous and can lead to XSS. " "Use autoescape=True or use the " "select_autoescape function to mitigate XSS " "vulnerabilities." ) # found autoescape if getattr(node, 'arg', None) == 'autoescape': value = getattr(node, 'value', None) if (getattr(value, 'id', None) == 'True' or getattr(value, 'value', None) is True): return # Check if select_autoescape function is used. elif isinstance(value, ast.Call) and getattr( value.func, 'id', None) == 'select_autoescape': return else: return bandit.Issue( severity=bandit.HIGH, confidence=bandit.MEDIUM, text="Using jinja2 templates with autoescape=" "False is dangerous and can lead to XSS. " "Ensure autoescape=True or use the " "select_autoescape function to mitigate " "XSS vulnerabilities." ) # We haven't found a keyword named autoescape, indicating default # behavior return bandit.Issue( severity=bandit.HIGH, confidence=bandit.HIGH, text="By default, jinja2 sets autoescape to False. Consider " "using autoescape=True or use the select_autoescape " "function to mitigate XSS vulnerabilities." )
def visit_Call_35(self, node, side=None, **kwargs): """ in 3.5 the starargs attribute was changed to be more flexible, #11097 """ if isinstance(node.func, ast.Attribute): res = self.visit_Attribute(node.func) elif not isinstance(node.func, ast.Name): raise TypeError("Only named functions are supported") else: try: res = self.visit(node.func) except UndefinedVariableError: # Check if this is a supported function name try: res = FuncNode(node.func.id) except ValueError: # Raise original error raise if res is None: raise ValueError("Invalid function call {0}".format(node.func.id)) if hasattr(res, 'value'): res = res.value if isinstance(res, FuncNode): new_args = [self.visit(arg) for arg in node.args] if node.keywords: raise TypeError("Function \"{0}\" does not support keyword " "arguments".format(res.name)) return res(*new_args, **kwargs) else: new_args = [self.visit(arg).value for arg in node.args] for key in node.keywords: if not isinstance(key, ast.keyword): raise ValueError("keyword error in function call " "'{0}'".format(node.func.id)) if key.arg: # TODO: bug? kwargs.append(ast.keyword( keyword.arg, self.visit(keyword.value))) # noqa return self.const_type(res(*new_args, **kwargs), self.env)
def visit_Call_legacy(self, node, side=None, **kwargs): # this can happen with: datetime.datetime if isinstance(node.func, ast.Attribute): res = self.visit_Attribute(node.func) elif not isinstance(node.func, ast.Name): raise TypeError("Only named functions are supported") else: try: res = self.visit(node.func) except UndefinedVariableError: # Check if this is a supported function name try: res = FuncNode(node.func.id) except ValueError: # Raise original error raise if res is None: raise ValueError("Invalid function call {0}".format(node.func.id)) if hasattr(res, 'value'): res = res.value if isinstance(res, FuncNode): args = [self.visit(targ) for targ in node.args] if node.starargs is not None: args += self.visit(node.starargs) if node.keywords or node.kwargs: raise TypeError("Function \"{0}\" does not support keyword " "arguments".format(res.name)) return res(*args, **kwargs) else: args = [self.visit(targ).value for targ in node.args] if node.starargs is not None: args += self.visit(node.starargs).value keywords = {} for key in node.keywords: if not isinstance(key, ast.keyword): raise ValueError("keyword error in function call " "'{0}'".format(node.func.id)) keywords[key.arg] = self.visit(key.value).value if node.kwargs is not None: keywords.update(self.visit(node.kwargs).value) return self.const_type(res(*args, **keywords), self.env)
def visit_BinOp(self, node): if node.op.__class__ in self.operators: sympy_class = self.operators[node.op.__class__] right = self.visit(node.right) left = self.visit(node.left) if isinstance(node.left, ast.UnaryOp) and (isinstance(node.right, ast.UnaryOp) == 0) and sympy_class in ('Mul',): left, right = right, left if isinstance(node.op, ast.Sub): right = ast.UnaryOp(op=ast.USub(), operand=right) if isinstance(node.op, ast.Div): if isinstance(node.left, ast.UnaryOp): if isinstance(node.right,ast.UnaryOp): left, right = right, left left = ast.Call( func=ast.Name(id='Pow', ctx=ast.Load()), args=[left, ast.UnaryOp(op=ast.USub(), operand=ast.Num(1))], keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))], starargs=None, kwargs=None ) else: right = ast.Call( func=ast.Name(id='Pow', ctx=ast.Load()), args=[right, ast.UnaryOp(op=ast.USub(), operand=ast.Num(1))], keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))], starargs=None, kwargs=None ) new_node = ast.Call( func=ast.Name(id=sympy_class, ctx=ast.Load()), args=[left, right], keywords=[ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load()))], starargs=None, kwargs=None ) if sympy_class in ('Add', 'Mul'): # Denest Add or Mul as appropriate new_node.args = self.flatten(new_node.args, sympy_class) return new_node return node