def get_qual_attr(node, aliases):
prefix = ""
if isinstance(node, _ast.Attribute):
try:
val = deepgetattr(node, 'value.id')
if val in aliases:
prefix = aliases[val]
else:
prefix = deepgetattr(node, 'value.id')
except Exception:
# NOTE(tkelsey): degrade gracefully when we can't get the fully
# qualified name for an attr, just return its base name.
pass
return "%s.%s" % (prefix, node.attr)
else:
return "" # TODO(tkelsey): process other node types
python类Attribute()的实例源码
def _get_attr_qual_name(node, aliases):
'''Get a the full name for the attribute node.
This will resolve a pseudo-qualified name for the attribute
rooted at node as long as all the deeper nodes are Names or
Attributes. This will give you how the code referenced the name but
will not tell you what the name actually refers to. If we
encounter a node without a static name we punt with an
empty string. If this encounters something more complex, such as
foo.mylist[0](a,b) we just return empty string.
:param node: AST Name or Attribute node
:param aliases: Import aliases dictionary
:returns: Qualified name referred to by the attribute or name.
'''
if isinstance(node, _ast.Name):
if node.id in aliases:
return aliases[node.id]
return node.id
elif isinstance(node, _ast.Attribute):
name = '%s.%s' % (_get_attr_qual_name(node.value, aliases), node.attr)
if name in aliases:
return aliases[name]
return name
else:
return ""
def get_call_name(node, aliases):
if isinstance(node.func, _ast.Name):
if deepgetattr(node, 'func.id') in aliases:
return aliases[deepgetattr(node, 'func.id')]
return deepgetattr(node, 'func.id')
elif isinstance(node.func, _ast.Attribute):
return _get_attr_qual_name(node.func, aliases)
else:
return ""
def get_called_name(node):
'''Get a function name from an ast.Call node.
An ast.Call node representing a method call with present differently to one
wrapping a function call: thing.call() vs call(). This helper will grab the
unqualified call name correctly in either case.
:param node: (ast.Call) the call node
:returns: (String) the function name
'''
func = node.func
try:
return func.attr if isinstance(func, ast.Attribute) else func.id
except AttributeError:
return ""
def LOAD_ATTR(self, instr):
name = self.ast_stack.pop()
attr = instr.arg
get_attr = _ast.Attribute(value=name, attr=attr, ctx=_ast.Load(), lineno=instr.lineno, col_offset=0)
self.ast_stack.append(get_attr)
def STORE_ATTR(self, instr):
attrname = instr.arg
node = self.ast_stack.pop()
expr = self.ast_stack.pop()
expr = self.process_ifexpr(expr)
assattr = _ast.Attribute(value=node, attr=attrname, ctx=_ast.Store(), lineno=instr.lineno, col_offset=0)
set_attr = _ast.Assign(targets=[assattr], value=expr, lineno=instr.lineno, col_offset=0)
self.ast_stack.append(set_attr)
def DELETE_ATTR(self, instr):
expr = self.ast_stack.pop()
attr = _ast.Attribute(value=expr, attr=instr.arg, ctx=_ast.Del(), lineno=instr.lineno, col_offset=0)
delete = _ast.Delete(targets=[attr], lineno=instr.lineno, col_offset=0)
self.ast_stack.append(delete)
def visit_FunctionDef(self, node):
"""
:type node: _ast.FunctionDef
"""
children = node.body
lambda_assign_children = [child for child in children
if type(child) == _ast.Assign
and len(child.targets) == 1
and type(child.value) == _ast.Compare
and (type(child.value.left) == _ast.Tuple or type(child.value.left) == _ast.Name)
and all(map(lambda t: type(t) == _ast.Name, getattr(child.value.left, 'elts', [])))]
# Support single line lambdas outside of assigns
other_children = [child for child in children if child not in lambda_assign_children]
for child in other_children:
CompareNodeVisitor().visit(child)
for assign_type_child in lambda_assign_children:
arguments = _transform_function_arguments(assign_type_child.value.left)
function_body = assign_type_child.value.comparators[0]
if _is_multiline_lambda(function_body):
all_statements = function_body.elts
return_statement = all_statements[-1]
statements = all_statements[0:len(all_statements) - 1]
statements = _transform_multiline_assignment_statements(statements)
return_statement = _transform_multiline_return_statement(return_statement)
assign_target = assign_type_child.targets[0]
if type(assign_target) is _ast.Attribute:
function_name = assign_target.attr
else:
function_name = assign_target.id
all_transformed_statements = statements + [return_statement]
functiondef_object = ast.FunctionDef(args = arguments,
body=all_transformed_statements,
lineno=assign_type_child.lineno,
name=function_name,
col_offset=assign_type_child.col_offset,
decorator_list=[])
children.insert(0, functiondef_object)
assign_type_child.value = ast.Name(id=functiondef_object.name,
col_offset=functiondef_object.col_offset,
lineno=functiondef_object.lineno,
ctx=ast.Load())
else:
lambda_ast_transform = ast.Lambda(args=arguments,
body=function_body,
lineno=assign_type_child.lineno,
col_offset = assign_type_child.col_offset)
assign_type_child.value = lambda_ast_transform
return node
def STORE_NAME(self, instr):
value = self.ast_stack.pop()
value = self.process_ifexpr(value)
if isinstance(value, _ast.Import):
if value.from_:
assert isinstance(self.ast_stack[-1], _ast.ImportFrom)
from_ = self.ast_stack.pop()
as_name = instr.arg
name = from_.names[0].name
if as_name != name:
from_.names[0].asname = as_name
self.ast_stack.append(from_)
else:
as_name = instr.arg
if value.names[0].asname is None:
base_name = value.names[0].name.split('.')[0]
if base_name != as_name:
value.names[0].asname = as_name
self.ast_stack.append(value)
elif isinstance(value, (_ast.Attribute)) and isinstance(value.value, (_ast.Import)):
asname = instr.arg
value = value.value
value.names[0].asname = asname
self.ast_stack.append(value)
elif isinstance(value, (_ast.ClassDef, _ast.FunctionDef)):
as_name = instr.arg
value.name = as_name
self.ast_stack.append(value)
elif isinstance(value, _ast.AugAssign):
self.ast_stack.append(value)
elif isinstance(value, _ast.Assign):
_ = self.ast_stack.pop()
assname = _ast.Name(instr.arg, _ast.Store(), lineno=instr.lineno, col_offset=0)
value.targets.append(assname)
self.ast_stack.append(value)
else:
assname = _ast.Name(instr.arg, _ast.Store(), lineno=instr.lineno, col_offset=0)
assign = _ast.Assign(targets=[assname], value=value, lineno=instr.lineno, col_offset=0)
self.ast_stack.append(assign)