def test_setcomp(self):
self._simple_comp(ast.SetComp)
python类SetComp()的实例源码
def test_setcomp(self):
self._simple_comp(ast.SetComp)
def resolve_attr_id(node):
if isinstance(node, (ast.Attribute, ast.Subscript)):
value_id = None
if isinstance(node.value, (ast.Name, ast.Attribute, ast.Subscript)):
value_id = resolve_attr_id(node.value)
elif isinstance(node.value, ast.Call):
value_id = resolve_attr_id(node.value)
elif isinstance(node.value, ast.Str):
value_id = 'str'
elif isinstance(node.value, ast.Bytes):
value_id = 'bytes'
elif isinstance(node.value, (ast.List, ast.ListComp)):
value_id = 'list'
elif isinstance(node.value, ast.Tuple):
value_id = 'tuple'
elif isinstance(node.value, (ast.Set, ast.SetComp)):
value_id = 'set'
elif isinstance(node.value, (ast.Dict, ast.DictComp)):
value_id = 'dict'
else:
raise SyntaxError(
'unsupport type: {}'.format(ast.dump(node.value))
)
if isinstance(node, ast.Attribute):
return '{}.{}'.format(value_id, node.attr)
elif isinstance(node, ast.Subscript):
slice = None
if isinstance(node.slice.value, ast.Str):
slice = node.slice.value.s
elif isinstance(node.slice.value, ast.Num):
slice = node.slice.value.n
elif isinstance(node.slice.value, ast.Name):
slice = resolve_attr_id(node.slice.value)
return '{}[{}]'.format(value_id, slice)
elif isinstance(node, ast.Call):
return '{}()'.format(resolve_attr_id(node.func))
return node.id
def test_setcomp(self):
self._simple_comp(ast.SetComp)
def node_defines_name(node, name):
"""
Check if the specified statement node defines symbol *name*.
:param node: The node to check.
:param name: The symbol name to check.
:return: Whether or not the node defines the symbole specified.
:rtype: bool
"""
if isinstance(name, ast.Name):
name = name.id
if isinstance(node, ast.Assign):
if node_targets_name(node, name):
return True
if isinstance(node.value, (ast.DictComp, ast.ListComp, ast.SetComp)):
return node_defines_name(node.value, name)
elif isinstance(node, ast.ClassDef):
return node.name == name
# these ones all assume the iterable will be executed at least once
elif isinstance(node, (ast.DictComp, ast.GeneratorExp, ast.ListComp, ast.SetComp)):
for generator in node.generators:
target = generator.target
if isinstance(target, ast.Name):
if target.id == name:
return True
continue
for child_node in iter_child_expr_nodes(target):
if isinstance(child_node, ast.Name) and child_node.id == name:
return True
return False
elif isinstance(node, ast.ExceptHandler):
if isinstance(node.name, ast.Name):
return node.name.id == name
elif isinstance(node.name, str):
return node.name == name
elif isinstance(node, ast.Expr):
if isinstance(node.value, (ast.DictComp, ast.GeneratorExp, ast.ListComp, ast.SetComp)):
return node_defines_name(node.value, name)
elif isinstance(node, ast.For):
return isinstance(node.target, ast.Name) and node.target.id == name
elif isinstance(node, ast.FunctionDef):
return node.name == name
elif isinstance(node, (ast.Import, ast.ImportFrom)):
return next((alias for alias in node.names if (alias.asname or alias.name) == name), None) is not None
return False
def infer(node, context, solver, from_call=False):
"""Infer the type of a given AST node"""
if isinstance(node, ast.Num):
return infer_numeric(node, solver)
elif isinstance(node, ast.Str):
return solver.z3_types.string
elif (sys.version_info[0] >= 3 and sys.version_info[1] >= 6 and
(isinstance(node, ast.FormattedValue) or isinstance(node, ast.JoinedStr))):
# Formatted strings were introduced in Python 3.6
return solver.z3_types.string
elif isinstance(node, ast.Bytes):
return solver.z3_types.bytes
elif isinstance(node, ast.List):
return infer_list(node, context, solver)
elif isinstance(node, ast.Dict):
return infer_dict(node, context, solver)
elif isinstance(node, ast.Tuple):
return infer_tuple(node, context, solver)
elif isinstance(node, ast.NameConstant):
return infer_name_constant(node, solver)
elif isinstance(node, ast.Set):
return infer_set(node, context, solver)
elif isinstance(node, ast.BinOp):
return infer_binary_operation(node, context, solver)
elif isinstance(node, ast.BoolOp):
return infer_boolean_operation(node, context, solver)
elif isinstance(node, ast.UnaryOp):
return infer_unary_operation(node, context, solver)
elif isinstance(node, ast.IfExp):
return infer_if_expression(node, context, solver)
elif isinstance(node, ast.Subscript):
return infer_subscript(node, context, solver)
elif sys.version_info[0] >= 3 and sys.version_info[1] >= 5 and isinstance(node, ast.Await):
# Await and Async were introduced in Python 3.5
return infer(node.value, context, solver)
elif isinstance(node, ast.Yield):
return infer(node.value, context, solver)
elif isinstance(node, ast.Compare):
return infer_compare(node, context, solver)
elif isinstance(node, ast.Name):
return infer_name(node, context)
elif isinstance(node, ast.ListComp):
return infer_sequence_comprehension(node, solver.z3_types.list, context, solver)
elif isinstance(node, ast.SetComp):
return infer_sequence_comprehension(node, solver.z3_types.set, context, solver)
elif isinstance(node, ast.DictComp):
return infer_dict_comprehension(node, context, solver)
elif isinstance(node, ast.Call):
return infer_func_call(node, context, solver)
elif isinstance(node, ast.Attribute):
return infer_attribute(node, context, from_call, solver)
elif isinstance(node, ast.Lambda):
return _infer_lambda(node, context, solver)
raise NotImplementedError("Inference for expression {} is not implemented yet.".format(type(node).__name__))
def peval_comprehension(state, node, ctx):
accum_cls = {
ast.ListComp: ListAccumulator,
ast.GeneratorExp: GeneratorExpAccumulator,
ast.SetComp: SetAccumulator,
ast.DictComp: DictAccumulator,
}
# variables from generators temporary mask bindings
target_names = set()
for generator in node.generators:
if type(generator.target) == ast.Name:
target_names.add(generator.target.id)
else:
target_names.update([elt.id for elt in generator.target.elts])
# pre-evaluate the expression
elt_bindings = dict(ctx.bindings)
for name in target_names:
if name in elt_bindings:
del elt_bindings[name]
elt_ctx = ctx.update(bindings=elt_bindings)
if type(node) == ast.DictComp:
elt = ast.Tuple(elts=[node.key, node.value])
else:
elt = node.elt
state, new_elt = _peval_expression(state, elt, elt_ctx)
try:
state, container = _peval_comprehension(
state, accum_cls[type(node)], new_elt, node.generators, ctx)
evaluated = True
except CannotEvaluateComprehension:
evaluated = False
if evaluated:
return state, KnownValue(value=container)
else:
state, new_elt = map_reify(state, new_elt)
state, new_generators = _peval_comprehension_generators(state, node.generators, ctx)
if type(node) == ast.DictComp:
key, value = new_elt.elts
return state, replace_fields(node, key=key, value=value, generators=new_generators)
else:
return state, replace_fields(node, elt=new_elt, generators=new_generators)