def visit_If(self, node):
node = self.generic_visit(node)
if (node.orelse
and len(node.orelse) == 1
and isinstance(node.orelse[0], ast.Pass)
):
node.orelse = []
if (len(node.body) == 1
and isinstance(node.body[0], ast.Pass)
):
if node.orelse:
node_test = ast.UnaryOp(op=ast.Not(), operand=node.test)
if (len(node.orelse) == 1
and isinstance(node.orelse[0], ast.If)
):
node_test = ast.BoolOp\
( op = ast.And()
, values = [node_test, node.orelse[0].test]
)
node.test = ast.copy_location(node_test, node.orelse[0].test)
node.body = node.orelse[0].body
node.orelse = node.orelse[0].orelse
else:
node.test = ast.copy_location(node_test, node.test)
node.body = node.orelse
node.orelse = []
else:
node = None
return node
python类copy_location()的实例源码
def visit_Attribute(self, node: ast.Attribute):
if isinstance(node.value, ast.Name):
if isinstance(node.ctx, ast.Load):
name = '{}.{}'.format(node.value.id, node.attr)
if name in self._values:
node = ast.copy_location(self._values[name], node)
return self.generic_visit(node)
def visit_For(self, node: ast.For):
node = self.generic_visit(node)
if self._is_for_yield(node):
yield_node = ast.YieldFrom(value = node.iter)
expr_node = ast.Expr(value = yield_node)
node = ast.copy_location(expr_node, node)
node = ast.fix_missing_locations(node)
return node
def visit_BinOp(self, node: ast.BinOp):
node = self.generic_visit(node)
if self._is_numeric_pow(node):
left, right = node.left, node.right
degree = ( right.n if isinstance(right, ast.Num)
else -right.operand.n if isinstance(right.op, ast.USub)
else right.operand.n )
degree = int(degree)
if abs(degree) == 0:
node = ast.copy_location(ast.Num(n = 1), node)
elif abs(degree) == 1:
node = node.left
elif 2 <= abs(degree) <= self.MAX_DEGREE:
for _ in range(1, abs(degree)):
new_node = ast.BinOp\
( left = left
, op = ast.Mult()
, right = copy(node.left)
)
left = new_node = ast.copy_location(new_node, node)
node = new_node
else:
return node
if degree < 0:
new_node = ast.BinOp\
( left = ast.Num(n = 1)
, op = ast.Div()
, right = node
)
node = ast.copy_location(new_node, node)
return node
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def to_messageable(self, call):
if not isinstance(call.func, ast.Attribute):
return call
if call.func.attr == 'say':
if self.interactive and not prompt_change(
'A possible change was found to change say to send.'
):
return call
call.func.value = ast.Name(id='ctx', ctx=ast.Load())
call.func.attr = 'send'
stats_counter['call_changes'] += 1
elif call.func.attr == 'send_message':
if self.interactive and not prompt_change(
'A possible change was found to change send_message to send.'
):
return call
destination = call.args[0]
wrap_attr = ast.Attribute()
wrap_attr.value = destination
wrap_attr.attr = 'send'
wrap_attr.ctx = ast.Load()
newcall = ast.Call()
newcall.func = wrap_attr
newcall.args = call.args[1:]
newcall.keywords = call.keywords
newcall = ast.copy_location(newcall, call)
stats_counter['call_changes'] += 1
return newcall
return call
def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))'
)
def visit_Expr(self, node):
if type(node.value) is ast.Call:
call = node.value
if self.is_concurrent_call(call):
self.encounter_call(call)
return node
elif any([self.is_concurrent_call(arg) for arg in call.args]):
conc_args = [(i, arg) for i, arg in enumerate(call.args) if self.is_concurrent_call(arg)]
if len(conc_args) > 1:
raise self.not_implemented_error(call, "Functions with multiple @concurrent parameters are unsupported")
conc_call = conc_args[0][1]
self.encounter_call(conc_call)
call.args[conc_args[0][0]] = ast.Name("__value__", ast.Load())
if sys.version_info >= (3, 0):
args = [ast.arg("__value__", None)]
else:
args = [ast.Name("__value__", ast.Param())]
call_lambda = ast.Lambda(ast.arguments(args = args, defaults = [], kwonlyargs = [], kw_defaults = []), call)
copy_location_kwargs = {
"func": ast.Attribute(conc_call.func, 'call', ast.Load()),
"args": [call_lambda] + conc_call.args,
"keywords": conc_call.keywords
}
if(sys.version_info < (3, 0)):
copy_location_kwargs["kwargs"] = conc_call.kwargs
return copy_location(ast.Expr(ast.Call(**copy_location_kwargs)), node)
return self.generic_visit(node)
def visit_Assign(self, node):
if self.is_valid_assignment(node):
call = node.value
self.encounter_call(call)
name = node.targets[0].value
self.arguments.add(SchedulerRewriter.top_level_name(name))
index = node.targets[0].slice.value
call.func = ast.Attribute(call.func, 'assign', ast.Load())
call.args = [ast.Tuple([name, index], ast.Load())] + call.args
return copy_location(ast.Expr(call), node)
return self.generic_visit(node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))'
)
def test_copy_location(self):
src = ast.parse('1 + 1', mode='eval')
src.body.right = ast.copy_location(ast.Num(2), src.body.right)
self.assertEqual(ast.dump(src, include_attributes=True),
'Expression(body=BinOp(left=Num(n=1, lineno=1, col_offset=0), '
'op=Add(), right=Num(n=2, lineno=1, col_offset=4), lineno=1, '
'col_offset=0))'
)
def visit_Num(self, node):
"""
WARNING: you cannot directly write constants in list. It will throw obscure
error like "TypeError: required field "lineno" missing from expr"
You MUST wrap all constants in ast_demo types, like ast_demo.Num(n=42) instead of raw 42
"""
n = node.n
if isinstance(n, int):
new_node = ast.Call(func=ast.Name(id='Fraction', ctx=ast.Load()),
args=[node, ast.Num(n=1)], keywords=[])
ast.copy_location(new_node, node)
# ast_demo.fix_missing_locations(new_node)
return new_node
return node
def visit_Assert(self, node):
if isinstance(node.test, ast.Compare) and \
len(node.test.ops) == 1 and \
isinstance(node.test.ops[0], ast.Eq):
call = ast.Call(func=ast.Name(id='assert_equal', ctx=ast.Load()),
args=[node.test.left, node.test.comparators[0]],
keywords=[])
# Wrap the call in an Expr node, because the return value isn't used.
newnode = ast.Expr(value=call)
ast.copy_location(newnode, node)
ast.fix_missing_locations(newnode)
return newnode
# Return the original node if we don't want to change it.
return node