def _get_ast_name_node(node):
while True:
# only accept '*var'
if isinstance(node, ast.Starred):
# '*var = value' => 'var'
node = node.value
elif isinstance(node, ast.Subscript):
# 'obj[slice] = value' => 'obj'
node = node.value
elif isinstance(node, ast.Attribute):
# 'obj.attr = value' => 'obj'
node = node.value
elif (isinstance(node, ast.Call)
and isinstance(node.func, ast.Attribute)):
# 'obj.method().attr = value' => 'obj.method'
node = node.func
else:
return node
python类Starred()的实例源码
def TUPLE(self, node):
if not PY2 and isinstance(node.ctx, ast.Store):
# Python 3 advanced tuple unpacking: a, *b, c = d.
# Only one starred expression is allowed, and no more than 1<<8
# assignments are allowed before a stared expression. There is
# also a limit of 1<<24 expressions after the starred expression,
# which is impossible to test due to memory restrictions, but we
# add it here anyway
has_starred = False
star_loc = -1
for i, n in enumerate(node.elts):
if isinstance(n, ast.Starred):
if has_starred:
self.report(messages.TwoStarredExpressions, node)
# The SyntaxError doesn't distinguish two from more
# than two.
break
has_starred = True
star_loc = i
if star_loc >= 1 << 8 or len(node.elts) - star_loc - 1 >= 1 << 24:
self.report(messages.TooManyExpressionsInStarredAssignment, node)
self.handleChildren(node)
def TUPLE(self, node):
if not PY2 and isinstance(node.ctx, ast.Store):
# Python 3 advanced tuple unpacking: a, *b, c = d.
# Only one starred expression is allowed, and no more than 1<<8
# assignments are allowed before a stared expression. There is
# also a limit of 1<<24 expressions after the starred expression,
# which is impossible to test due to memory restrictions, but we
# add it here anyway
has_starred = False
star_loc = -1
for i, n in enumerate(node.elts):
if isinstance(n, ast.Starred):
if has_starred:
self.report(messages.TwoStarredExpressions, node)
# The SyntaxError doesn't distinguish two from more
# than two.
break
has_starred = True
star_loc = i
if star_loc >= 1 << 8 or len(node.elts) - star_loc - 1 >= 1 << 24:
self.report(messages.TooManyExpressionsInStarredAssignment, node)
self.handleChildren(node)
def _is_star_arg(node):
return isinstance(node, ast.Starred)
def test_starred(self):
left = ast.List([ast.Starred(ast.Name("x", ast.Load()), ast.Store())],
ast.Store())
assign = ast.Assign([left], ast.Num(4))
self.stmt(assign, "must have Store context")
def get_starargs(callsite):
if not isinstance(callsite, ast.Call):
raise ValueError("ast.Call expected, got %s" % type(callsite))
if sys.version_info >= (3, 5):
for arg in callsite.args:
if isinstance(arg, ast.Starred):
return arg.value
return None
else:
return callsite.starargs
def getParent(self, node):
# Lookup the first parent which is not Tuple, List or Starred
while True:
node = node.parent
if not hasattr(node, 'elts') and not hasattr(node, 'ctx'):
return node
def _build_call35(self, o):
"""
Workaround for python 3.5 _ast.Call signature, docs found here
https://greentreesnakes.readthedocs.org/en/latest/nodes.html
"""
import ast
callee = self.build(o.func)
args = []
if o.args is not None:
for a in o.args:
if isinstance(a, ast.Starred):
args.append(self.build(a.value))
else:
args.append(self.build(a))
kwargs = {}
for kw in o.keywords:
if kw.arg is None: # double asterix `**`
rst = self.build(kw.value)
if not isinstance(rst, dict):
raise TypeError('Invalid argument for call.'
'Must be a mapping object.')
# give preference to the keys set directly from arg=value
for k, v in rst.items():
if k not in kwargs:
kwargs[k] = v
else: # defined on the call as: arg=value
kwargs[kw.arg] = self.build(kw.value)
return callee(*args, **kwargs)
def _check_string_formatting(self, node):
[lhs, rhs] = [node.left, node.right]
if isinstance(lhs, ast.Str):
lhs = lhs.s
else:
return
if isinstance(rhs, ast.Tuple):
if sys.version_info >= (3, 5):
if any(isinstance(elt, ast.Starred) for elt in rhs.elts): # pylint: disable=no-member
return
rhs = tuple(
elt.s if isinstance(elt, ast.Str) else 0
for elt in rhs.elts
)
elif isinstance(rhs, ast.Dict):
new_rhs = {}
for key, value in zip(rhs.keys, rhs.values):
if isinstance(key, ast.Str):
key = key.s
else:
return
if isinstance(value, ast.Str):
value = value.s
else:
value = 0
new_rhs[key] = value
rhs = new_rhs
elif isinstance(rhs, ast.Str):
rhs = rhs.s
elif isinstance(rhs, ast.Num):
rhs = 0
else:
return
try:
lhs % rhs
except KeyError as exc:
yield self.tag(node, 'string-formatting-error', 'missing key', str(exc))
except Exception as exc: # pylint: disable=broad-except
yield self.tag(node, 'string-formatting-error', str(exc))
def test_starred(self):
left = ast.List([ast.Starred(ast.Name("x", ast.Load()), ast.Store())],
ast.Store())
assign = ast.Assign([left], ast.Num(4))
self.stmt(assign, "must have Store context")
def get_target_vars(target):
get_id = lambda n: n.id if not isinstance(n, ast.Starred) else n.value.id
if isinstance(target, (ast.Name, ast.Starred)):
tv = [get_id(target)]
elif isinstance(target, ast.Tuple):
tv = [get_id(node) for node in target.elts]
else: tv = []
return TargetVars(tv)
def get_pos_arg_part(self, arg, indx_pos):
is_star = isinstance(arg, ast.Starred)
return {
'node': arg if not is_star else arg.value,
'highlight': arg,
'type': 'argument',
'is_starred': is_star,
'name': indx_pos
}
def getParent(self, node):
# Lookup the first parent which is not Tuple, List or Starred
while True:
node = node.parent
if not hasattr(node, 'elts') and not hasattr(node, 'ctx'):
return node
def add_vararg_to_super_call(super_call, vararg):
super_call.value.args.append(ast.Starred(ctx=ast.Load(), value=ast.Name(id=vararg.arg, ctx=ast.Load())))
def test_starred(self):
left = ast.List([ast.Starred(ast.Name("x", ast.Load()), ast.Store())],
ast.Store())
assign = ast.Assign([left], ast.Num(4))
self.stmt(assign, "must have Store context")
def _build_call35(self, o):
"""
Workaround for python 3.5 _ast.Call signature, docs found here
https://greentreesnakes.readthedocs.org/en/latest/nodes.html
"""
import ast
callee = self.build(o.func)
args = []
if o.args is not None:
for a in o.args:
if isinstance(a, ast.Starred):
args.append(self.build(a.value))
else:
args.append(self.build(a))
kwargs = {}
for kw in o.keywords:
if kw.arg is None: # double asterix `**`
rst = self.build(kw.value)
if not isinstance(rst, dict):
raise TypeError("Invalid argument for call."
"Must be a mapping object.")
# give preference to the keys set directly from arg=value
for k, v in rst.items():
if k not in kwargs:
kwargs[k] = v
else: # defined on the call as: arg=value
kwargs[kw.arg] = self.build(kw.value)
return callee(*args, **kwargs)
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 _build_parameter_assignments(call_node, functiondef_node):
# currently variadic arguments are not supported
assert all(type(arg) != ast.Starred for arg in call_node.args)
assert all(kw.arg is not None for kw in call_node.keywords)
parameter_assignments = []
for callee_arg, fn_arg in zip(call_node.args, functiondef_node.args.args):
parameter_assignments.append(ast.Assign(
targets=[ast.Name(fn_arg.arg, ast.Store())],
value=callee_arg))
return parameter_assignments