def get_object_name(obj):
"""
Return the name of a given object
"""
name_dispatch = {
ast.Name: "id",
ast.Attribute: "attr",
ast.Call: "func",
ast.FunctionDef: "name",
ast.ClassDef: "name",
ast.Subscript: "value",
}
# This is a new ast type in Python 3
if hasattr(ast, "arg"):
name_dispatch[ast.arg] = "arg"
while not isinstance(obj, str):
assert type(obj) in name_dispatch
obj = getattr(obj, name_dispatch[type(obj)])
return obj
python类ClassDef()的实例源码
def updateVariableNames(a, varMap, scopeName, randomCounter, imports):
if not isinstance(a, ast.AST):
return
if type(a) in [ast.FunctionDef, ast.ClassDef]:
if a.name in varMap:
if not hasattr(a, "originalId"):
a.originalId = a.name
a.name = varMap[a.name]
anonymizeStatementNames(a, varMap, "_" + a.name, imports)
elif type(a) == ast.arg:
if a.arg not in varMap and not (builtInName(a.arg) or importedName(a.arg, imports)):
log("Can't assign to arg?", "bug")
if a.arg in varMap:
if not hasattr(a, "originalId"):
a.originalId = a.arg
if varMap[a.arg][0] == "r":
a.randomVar = True # so we know it can crash
if a.arg == varMap[a.arg]:
# Check whether this is a given name
if not isAnonVariable(varMap[a.arg]):
a.dontChangeName = True
a.arg = varMap[a.arg]
elif type(a) == ast.Name:
if a.id not in varMap and not (builtInName(a.id) or importedName(a.id, imports)):
varMap[a.id] = "r" + str(randomCounter[0]) + scopeName
randomCounter[0] += 1
if a.id in varMap:
if not hasattr(a, "originalId"):
a.originalId = a.id
if varMap[a.id][0] == "r":
a.randomVar = True # so we know it can crash
if a.id == varMap[a.id]:
# Check whether this is a given name
if not isAnonVariable(varMap[a.id]):
a.dontChangeName = True
a.id = varMap[a.id]
else:
for child in ast.iter_child_nodes(a):
updateVariableNames(child, varMap, scopeName, randomCounter, imports)
def staticVars(l, vars):
"""Determines whether the given lines change the given variables"""
# First, if one of the variables can be modified, there might be a problem
mutableVars = []
for var in vars:
if (not (hasattr(var, "type") and (var.type in [int, float, str, bool]))):
mutableVars.append(var)
for i in range(len(l)):
if type(l[i]) == ast.Assign:
for var in vars:
if var.id in allVariableNamesUsed(l[i].targets[0]):
return False
elif type(l[i]) == ast.AugAssign:
for var in vars:
if var.id in allVariableNamesUsed(l[i].target):
return False
elif type(l[i]) in [ast.If, ast.While]:
if not (staticVars(l[i].body, vars) and staticVars(l[i].orelse, vars)):
return False
elif type(l[i]) == ast.For:
for var in vars:
if var.id in allVariableNamesUsed(l[i].target):
return False
if not (staticVars(l[i].body, vars) and staticVars(l[i].orelse, vars)):
return False
elif type(l[i]) in [ast.FunctionDef, ast.ClassDef, ast.Try, ast.With]:
log("transformations\tstaticVars\tMissing type: " + str(type(l[i])), "bug")
# If a mutable variable is used, we can't trust it
for var in mutableVars:
if var.id in allVariableNamesUsed(l[i]):
return False
return True
def isStatement(a):
"""Determine whether the given node is a statement (vs an expression)"""
return type(a) in [ ast.Module, ast.Interactive, ast.Expression, ast.Suite,
ast.FunctionDef, ast.ClassDef, ast.Return, ast.Delete,
ast.Assign, ast.AugAssign, ast.For, ast.While,
ast.If, ast.With, ast.Raise, ast.Try,
ast.Assert, ast.Import, ast.ImportFrom, ast.Global,
ast.Expr, ast.Pass, ast.Break, ast.Continue ]
def applyVariableMap(a, variableMap):
if not isinstance(a, ast.AST):
return a
if type(a) == ast.Name:
if a.id in variableMap:
a.id = variableMap[a.id]
elif type(a) in [ast.FunctionDef, ast.ClassDef]:
if a.name in variableMap:
a.name = variableMap[a.name]
return applyToChildren(a, lambda x : applyVariableMap(x, variableMap))
def class_check(node, kw=False):
'''
Class specific check
Action - check private method, move to utils
check docstring
scan for class - recursive class check
scan for function - function check
'''
status = True
for child in ast.iter_child_nodes(node):
if isinstance(child, ast.FunctionDef):
if kw and child.name.startswith("_") and child.name != "__init__":
print node.name, child.name, "should move to utils"
status = False
tmp_status = func_check(child, kw)
status &= tmp_status
elif isinstance(child, ast.ClassDef):
tmp_status = class_check(child, kw)
status &= tmp_status
if ast.get_docstring(node) is None:
# check for docstring
print node.name, "doesn't contain any docstring"
status = False
return status
def visit_Call(self, node):
_id = get_call_names_as_string(node.func)
local_definitions = self.module_definitions_stack[-1]
alias = handle_aliases_in_calls(_id, local_definitions.import_alias_mapping)
if alias:
definition = local_definitions.get_definition(alias)
else:
definition = local_definitions.get_definition(_id)
# e.g. "request.args.get" -> "get"
last_attribute = _id.rpartition('.')[-1]
if definition:
if isinstance(definition.node, ast.ClassDef):
self.add_blackbox_or_builtin_call(node, blackbox=False)
elif isinstance(definition.node, ast.FunctionDef):
self.undecided = False
self.function_return_stack.append(_id)
return self.process_function(node, definition)
else:
raise Exception('Definition was neither FunctionDef or ' +
'ClassDef, cannot add the function ')
elif last_attribute not in BUILTINS:
# Mark the call as a blackbox because we don't have the definition
return self.add_blackbox_or_builtin_call(node, blackbox=True)
return self.add_blackbox_or_builtin_call(node, blackbox=False)
def get_vars(node):
vv = VarsVisitor()
if isinstance(node.ast_node, ast.While)\
or isinstance(node.ast_node, ast.If):
vv.visit(node.ast_node.test)
elif isinstance(node.ast_node, ast.FunctionDef) or\
isinstance(node.ast_node, ast.ClassDef):
return list()
else:
try:
vv.visit(node.ast_node)
except AttributeError: # If no ast_node
vv.result = list()
# remove duplicates:
vv.result = set(vv.result)
# Filter out lvars:
for var in vv.result:
try: # if assignment node
# print('r', node.right_hand_side_variables)
# if var not in node.left_hand_side:
if var in node.right_hand_side_variables:
yield var
except AttributeError:
yield var
def top_level_classes(body):
return (f for f in body if isinstance(f, ast.ClassDef))
def test_classes(self):
matches = list(self.m.match('class', self.filepath('classes.py')))
self.assertEqual(len(matches), 4)
# check instances
self.assertIsInstance(matches[0][0], ast.ClassDef)
self.assertIsInstance(matches[1][0], ast.ClassDef)
self.assertIsInstance(matches[2][0], ast.ClassDef)
self.assertIsInstance(matches[3][0], ast.ClassDef)
# check lines
self.assertEqual(matches[0][1], 1)
self.assertEqual(matches[1][1], 9)
self.assertEqual(matches[2][1], 13)
self.assertEqual(matches[3][1], 14)
def match(self, selector, filename):
module = astor.parsefile(filename)
for match in super(ASTMatchEngine, self).match(selector, module.body):
lineno = match.lineno
if isinstance(match, (ast.ClassDef, ast.FunctionDef)):
for d in match.decorator_list:
lineno += 1
yield match, lineno
def pseudo_extends(matcher, node, value):
if not isinstance(node, ast.ClassDef):
return False
if not value:
return node.bases == []
bases = node.bases
selectors = value.split(',')
for selector in selectors:
matches = matcher.match_data(
matcher.parse_selector(selector)[0], bases)
if any(matches):
return True
def visit_ClassDef(self, node):
# type: (ast.ClassDef) -> None
# Not implemented yet. We want to ensure we don't
# traverse into the class body for now.
return
def top_level_classes(body):
# return (node for node in ast.walk(body) if isinstance(node, ast.ClassDef))
return (f for f in body if isinstance(f, ast.ClassDef))
def visit_ClassDef(self, node, phase):
'''Visitor for AST ClassDef node
Add class name to current namespace for all descendants.
:param node: Node being inspected
:return: -
'''
# For all child nodes, add this class name to current namespace
self.namespace = b_utils.namespace_path_join(self.namespace, node.name)
def post_visit(self, node):
self.depth -= 1
LOG.debug("%s\texiting : %s", self.depth, hex(id(node)))
# HACK(tkelsey): this is needed to clean up post-recursion stuff that
# gets setup in the visit methods for these node types.
if isinstance(node, ast.FunctionDef) or isinstance(node, ast.ClassDef):
self.namespace = b_utils.namespace_path_split(self.namespace)[0]
def check_size(example, size):
tree = ast.parse(example)
for node in tree.body:
if isinstance(node, ast.ClassDef) and node.name == 'Foo':
assert count_lines(node) == size
break
else:
assert False, 'Failed to find top-level class "Foo" in code'
def parse_struct(node: ast.ClassDef) -> pysl.Struct:
struct = pysl.Struct()
struct.set_location(node)
struct.name = node.name
struct.elements = []
struct.set_location(node)
for decl_node in node.body:
if isinstance(decl_node, ast.AnnAssign):
assignment = parse_assignment(decl_node)
struct.elements.append((str_to_pysl_type(loc(node), assignment.type), assignment.name))
else:
error(loc(decl_node), "Unrecognized node inside structure: {0}".format(struct.name))
return struct
def parse_stage_input(node: ast.ClassDef, stages: str) -> pysl.StageInput:
si = pysl.StageInput()
si.set_location(node)
si.name = node.name
si.elements = []
si.stages = stages
conditions = []
for decl_node in node.body:
if isinstance(decl_node, ast.AnnAssign):
assignment = parse_assignment(decl_node)
element = pysl.InputElement()
element.set_location(decl_node)
element.name = assignment.name
element.type = str_to_pysl_type(loc(decl_node), assignment.type)
element.semantic = assignment.value
element.conditions = list(conditions)
conditions[:] = [] # Copy
si.elements.append(element)
elif (isinstance(decl_node, ast.Expr) and
isinstance(decl_node.value, ast.Call)):
if decl_node.value.func.id is '_':
conditions.append(parse_preprocessor(decl_node.value))
else:
error(loc(decl_node), "Unsupported function call: {0} inside StageInput: {1}".format(decl_node.value.func.id, si.name))
else:
error(loc(decl_node), "Unrecognized node inside StageInput: {0}".format(si.name))
si.post_conditions = list(conditions)
return si
def parse_constant_buffer(node: ast.ClassDef) -> pysl.ConstantBuffer:
cbuffer = pysl.ConstantBuffer()
cbuffer.set_location(node)
cbuffer.name = node.name
cbuffer.constants = []
for decl_node in node.body:
if isinstance(decl_node, ast.AnnAssign):
assignment = parse_assignment(decl_node)
constant = pysl.Constant()
constant.set_location(decl_node)
constant.name = assignment.name
if assignment.value:
try:
constant.offset = int(assignment.value)
except ValueError:
error(loc(decl_node), "Expected numberic offset as argument")
assignment.value
constant.type = str_to_pysl_type(loc(decl_node), assignment.type)
cbuffer.constants.append(constant)
else:
error(loc(decl_node), "Unrecognized node inside ConstantBuffer: {0}".format(cbuffer.name))
for d in node.decorator_list:
decorator = parse_decorator(d)
if decorator.args:
try:
cbuffer.enforced_size = int(decorator.args[0])
except ValueError:
error(loc(d), "Expected integer argument to constructor indicating enforced size(in constants), but evaluated: {0}".format(decorator.args[0]))
return cbuffer