def _transform_function_arguments(left):
if type(left) is ast.Name:
names = [left]
else:
names = left.elts
# Python3
if hasattr(_ast, 'arg'):
args = [_ast.arg(annotation=None, arg=name.id, col_offset = name.col_offset, lineno=name.lineno) for name in names]
return ast.arguments(args=args, defaults=[], kwonlyargs=[], kw_defaults=[])
# Python 2
arguments = ast.arguments(args=names, defaults=[])
for argument in arguments.args:
argument.ctx = ast.Param()
return arguments
python类arguments()的实例源码
def visit_Compare(self, node):
"""
:type node: _ast.FunctionDef
"""
is_lambda_def = len(node.ops) == 1\
and type(node.ops[0]) is _ast.Gt \
and (type(node.left) is _ast.Tuple or type(node.left) is _ast.Name) \
and all(map(lambda t: type(t) == _ast.Name, getattr(node.left, 'elts', [])))
if not is_lambda_def:
return node
arguments = _transform_function_arguments(node.left)
function_body = node.comparators[0]
lambda_ast_transform = ast.Lambda(args=arguments,
body=function_body,
lineno=node.lineno,
col_offset=node.col_offset)
return lambda_ast_transform
def _check_specific_to_fields(self, name):
# these tests don't apply for the typename, just the fieldnames
if name in self.seen_fields:
raise ValueError('Encountered duplicate field name: '
'{0!r}'.format(name))
if name.startswith('_'):
raise ValueError('Field names cannot start with an underscore: '
'{0!r}'.format(name))
########################################################################
# Returns a function with name 'name', that calls another function 'chain_fn'
# This is used to create the __init__ function with the right argument names and defaults, that
# calls into _init to do the real work.
# The new function takes args as arguments, with defaults as given.
def test_AST_objects(self):
if not support.check_impl_detail():
# PyPy also provides a __dict__ to the ast.AST base class.
return
x = ast.AST()
self.assertEqual(x._fields, ())
with self.assertRaises(AttributeError):
x.vararg
with self.assertRaises(AttributeError):
x.foobar = 21
with self.assertRaises(AttributeError):
ast.AST(lineno=2)
with self.assertRaises(TypeError):
# "_ast.AST constructor takes 0 positional arguments"
ast.AST(2)
def test_AST_objects(self):
x = ast.AST()
self.assertEqual(x._fields, ())
with self.assertRaises(AttributeError):
x.vararg
with self.assertRaises(AttributeError):
x.foobar = 21
with self.assertRaises(AttributeError):
ast.AST(lineno=2)
with self.assertRaises(TypeError):
# "_ast.AST constructor takes 0 positional arguments"
ast.AST(2)
def test_AST_objects(self):
x = ast.AST()
self.assertEqual(x._fields, ())
with self.assertRaises(AttributeError):
x.vararg
with self.assertRaises(AttributeError):
x.foobar = 21
with self.assertRaises(AttributeError):
ast.AST(lineno=2)
with self.assertRaises(TypeError):
# "_ast.AST constructor takes 0 positional arguments"
ast.AST(2)
def do_ClassDef(self, node):
result = []
name = node.name # Only a plain string is valid.
bases = [self.visit(z) for z in node.bases] if node.bases else []
if getattr(node, 'keywords', None): # Python 3
for keyword in node.keywords:
bases.append('%s=%s' % (keyword.arg, self.visit(keyword.value)))
if getattr(node, 'starargs', None): # Python 3
bases.append('*%s', self.visit(node.starargs))
if getattr(node, 'kwargs', None): # Python 3
bases.append('*%s', self.visit(node.kwargs))
if bases:
result.append(self.indent('class %s(%s):\n' % (name, ','.join(bases))))
else:
result.append(self.indent('class %s:\n' % name))
for z in node.body:
self.level += 1
result.append(self.visit(z))
self.level -= 1
return ''.join(result)
# 2: FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list)
# 3: FunctionDef(identifier name, arguments args, stmt* body, expr* decorator_list,
# expr? returns)
def trace_stubs(self, stub, aList=None, header=None, level=-1):
'''Return a trace of the given stub and all its descendants.'''
indent = ' '*4*max(0,level)
if level == -1:
aList = ['===== %s...\n' % (header) if header else '']
for s in stub.out_list:
aList.append('%s%s' % (indent, s.rstrip()))
for child in stub.children:
self.trace_stubs(child, level=level+1, aList=aList)
if level == -1:
return '\n'.join(aList) + '\n'
# 2: ClassDef(identifier name, expr* bases,
# stmt* body, expr* decorator_list)
# 3: ClassDef(identifier name, expr* bases,
# keyword* keywords, expr? starargs, expr? kwargs
# stmt* body, expr* decorator_list)
#
# keyword arguments supplied to call (NULL identifier for **kwargs)
# keyword = (identifier? arg, expr value)
def visit_FunctionDef(self, node):
# Create the stub in the old context.
old_stub = self.parent_stub
self.parent_stub = Stub('def', node.name, old_stub, self.context_stack)
self.add_stub(self.stubs_dict, self.parent_stub)
# Enter the new context.
self.returns = []
self.level += 1
self.context_stack.append(node.name)
for z in node.body:
self.visit(z)
self.context_stack.pop()
self.level -= 1
# Format *after* traversing
# if self.trace_matches or self.trace_reduce:
# if not self.class_name_stack:
# print('def %s\n' % node.name)
self.out('def %s(%s) -> %s' % (
node.name,
self.format_arguments(node.args),
self.format_returns(node)))
self.parent_stub = old_stub
# arguments = (expr* args, identifier? vararg, identifier? kwarg, expr* defaults)
def test_AST_objects(self):
if not test_support.check_impl_detail():
# PyPy also provides a __dict__ to the ast.AST base class.
return
x = ast.AST()
self.assertEqual(x._fields, ())
with self.assertRaises(AttributeError):
x.vararg
with self.assertRaises(AttributeError):
x.foobar = 21
with self.assertRaises(AttributeError):
ast.AST(lineno=2)
with self.assertRaises(TypeError):
# "_ast.AST constructor takes 0 positional arguments"
ast.AST(2)
def test_AST_objects(self):
x = ast.AST()
self.assertEqual(x._fields, ())
with self.assertRaises(AttributeError):
x.vararg
with self.assertRaises(AttributeError):
x.foobar = 21
with self.assertRaises(AttributeError):
ast.AST(lineno=2)
with self.assertRaises(TypeError):
# "_ast.AST constructor takes 0 positional arguments"
ast.AST(2)
def add_init_if_not_existing(class_node):
"""Add a default empty __init__ function if it doesn't exist in the class node"""
for stmt in class_node.body:
if isinstance(stmt, ast.FunctionDef) and stmt.name == "__init__":
return
class_node.body.append(ast.FunctionDef(
name="__init__",
args=ast.arguments(
args=[ast.arg(arg="self", annotation=None, lineno=class_node.lineno)],
vararg=None,
kwonlyargs=[],
kw_defaults=[],
kwarg=None,
defaults=[]
),
body=[ast.Pass()],
decorator_list=[],
returns=None,
lineno=class_node.lineno
))
def make_plugin_module(rule_body):
return FavaCode(
Module(
body=[
FunctionDef(
name='report',
args=arguments(
args=[
Name(id='shared', ctx=Param()),
],
vararg=None,
kwarg=None,
defaults=[]),
body=[
Return(
value=rule_body.get_ast())],
decorator_list=[
Call(
func=Name(id='fava_rule', ctx=Load()),
args=[Name(id=each, ctx=Load()) for each in rule_body.get_parsers()],
keywords=[],
starargs=None, kwargs=None),
])
]),
[rule_body])
def make_wrapper(new_variables, value):
"""
Define a set of new variables by createing a call to a lambda function.
The value becomes the body of the lambda.
The names of the new_variables become the names of the formal parameters to the lambda.
The values of the new_variables become the values of the actual arguments to the call.
"""
return FavaCode(
Call(
func=Lambda(
args=arguments(
args=[Name(id=key, ctx=Param()) for key, val in new_variables.iteritems()],
vararg=None, kwarg=None, defaults=[]),
body=value.get_ast()),
args=[val.get_ast() for key, val in new_variables.iteritems()],
keywords=[],
starargs=None,
kwargs=None),
[value] + [val for key, val in new_variables.iteritems()])
def pythoneval(self, args, debug=False):
refs = [ast.Name("x{0}".format(i), ast.Load()) for i in xrange(len(args))]
if sys.version_info[0] <= 2:
params = ast.arguments([ast.Name("x{0}".format(i), ast.Param()) for i in xrange(len(args))], None, None, [])
fcn = ast.FunctionDef("tmp", params, [ast.Return(self.pythonast(refs))], [])
else:
params = ast.arguments([ast.arg("x{0}".format(i), None) for i in xrange(len(args))], None, [], [], None, [])
fcn = ast.FunctionDef("tmp", params, [ast.Return(self.pythonast(refs))], [], None)
moduleast = ast.Module([fcn])
fakeLineNumbers(moduleast)
if debug:
print(astToSource(fcn))
modulecomp = compile(moduleast, "Femtocode", "exec")
out = {"$importlib": importlib, "$math": math}
exec(modulecomp, out)
return out["tmp"](*args)
def build(fcn, args, original=None):
if all(isinstance(x, Literal) for x in args):
empty = SymbolTable()
schema, typedargs, subempty = fcn.buildtyped(args, empty)
if isinstance(schema, Impossible):
if schema.reason is not None:
reason = "\n\n " + schema.reason
else:
reason = ""
complain("Function \"{0}\" does not accept arguments with the given literal types:\n\n {0}({1}){2}".format(fcn.name, ",\n {0} ".format(" " * len(fcn.name)).join(pretty(x.schema, prefix=" " + " " * len(fcn.name)).lstrip() for x in typedargs), reason), original)
else:
return Literal(fcn.pythoneval([x.value for x in args]), original)
else:
if fcn.associative:
newargs = []
for arg in args:
if isinstance(arg, Call) and arg.fcn == fcn:
newargs.extend(arg.args)
else:
newargs.append(arg)
else:
newargs = args
return Call(fcn, newargs, original)
def filter_arglist(args, defaults, bound_argnames):
"""
Filters a list of function argument nodes (``ast.arg``)
and corresponding defaults to exclude all arguments with the names
present in ``bound_arguments``.
Returns a pair of new arguments and defaults.
"""
new_args = []
new_defaults = []
required_args = len(args) - len(defaults)
for i, arg in enumerate(args):
if arg.arg not in bound_argnames:
new_args.append(arg)
if i >= required_args:
new_defaults.append(defaults[i - required_args])
return new_args, new_defaults
def filter_function_def(function_def, bound_argnames):
"""
Filters a node containing a function definition (an ``ast.FunctionDef`` object)
to exclude all arguments with the names present in ``bound_arguments``.
Returns the new ``ast.arguments`` node.
"""
assert type(function_def) == ast.FunctionDef
new_args = filter_arguments(function_def.args, bound_argnames)
params = dict(
name=function_def.name,
args=new_args,
body=function_def.body,
decorator_list=function_def.decorator_list,
returns=function_def.returns)
return ast.FunctionDef(**params)
def _setup_args(ctx, args, arg_types, tree):
# var and kw args are not supported
if args.vararg:
raise _errors.TyError("Varargs are not supported.", args.vararg)
if args.kwarg:
raise _errors.TyError("Kwargs are not supported.", args.kwarg)
if len(args.defaults) != 0:
raise _errors.TyError("Defaults are not supported.", tree)
variables = ctx.variables
arguments = args.args
n_args, n_arg_types = len(arguments), len(arg_types)
if n_args != n_arg_types:
raise _errors.TyError(
"Type specifies {0} arguments but function has {1}.".format(
n_arg_types, n_args),
tree)
for arg, arg_type in zip(arguments, arg_types):
if not isinstance(arg, ast.Name):
raise _errors.TyError("Argument must be an identifier.", arg)
arg_id = arg.id
uniq_id = ctx.generate_fresh_id(arg_id)
arg.uniq_id = uniq_id
variables[arg_id] = (uniq_id, arg_type)
yield arg_id
def translate_FunctionDef(self, ctx, tree):
argument_translation = ast.arguments(
args=[
ast.Name(id=arg.uniq_id)
for arg in tree.args.args
],
vararg=None,
kwarg=None,
defaults=[])
body_block = tree.body_block
body_block_translation = body_block.translate_return(ctx)
return ast.FunctionDef(
name=tree.uniq_id,
args=argument_translation,
body=body_block_translation,
decorator_list=[])
def visit_ListComp(self, t):
result_append = ast.Attribute(ast.Name('.0', load), 'append', load)
body = ast.Expr(Call(result_append, [t.elt]))
for loop in reversed(t.generators):
for test in reversed(loop.ifs):
body = ast.If(test, [body], [])
body = ast.For(loop.target, loop.iter, [body], [])
fn = [body,
ast.Return(ast.Name('.0', load))]
args = ast.arguments([ast.arg('.0', None)], None, [], None, [], [])
return Call(Function('<listcomp>', args, fn),
[ast.List([], load)])
def visit_ListComp(self, t):
t = self.generic_visit(t)
add_element = ast.Attribute(ast.Name('.elements', load), 'append', load)
body = ast.Expr(Call(add_element, [t.elt]))
for loop in reversed(t.generators):
for test in reversed(loop.ifs):
body = ast.If(test, [body], [])
body = ast.For(loop.target, loop.iter, [body], [])
fn = [body,
ast.Return(ast.Name('.elements', load))]
args = ast.arguments([ast.arg('.elements', None)], None, [], None, [], [])
result = Call(Function('<listcomp>', args, fn),
[ast.List([], load)])
return ast.copy_location(result, t)
def visit_ListComp(self, t):
t = self.generic_visit(t)
add_element = ast.Attribute(ast.Name('.elements', load), 'append', load)
body = ast.Expr(Call(add_element, [t.elt]))
for loop in reversed(t.generators):
for test in reversed(loop.ifs):
body = ast.If(test, [body], [])
body = ast.For(loop.target, loop.iter, [body], [])
fn = [body,
ast.Return(ast.Name('.elements', load))]
args = ast.arguments([ast.arg('.elements', None)], None, [], None, [], [])
result = Call(Function('<listcomp>', args, fn),
[ast.List([], load)])
return ast.copy_location(result, t)
def visit_ListComp(self, t):
t = self.generic_visit(t)
add_element = ast.Attribute(ast.Name('.elements', load), 'append', load)
body = ast.Expr(Call(add_element, [t.elt]))
for loop in reversed(t.generators):
for test in reversed(loop.ifs):
body = ast.If(test, [body], [])
body = ast.For(loop.target, loop.iter, [body], [])
fn = [body,
ast.Return(ast.Name('.elements', load))]
args = ast.arguments([ast.arg('.elements', None)], None, [], None, [], [])
result = Call(Function('<listcomp>', args, fn),
[ast.List([], load)])
return ast.copy_location(result, t)
def individualizeVariables(a, variablePairs, idNum, imports):
"""Replace variable names with new individualized ones (for inlining methods)"""
if not isinstance(a, ast.AST):
return
if type(a) == ast.Name:
if a.id not in variablePairs and not (builtInName(a.id) or importedName(a.id, imports)):
name = "_var_" + a.id + "_" + str(idNum[0])
variablePairs[a.id] = name
if a.id in variablePairs:
a.id = variablePairs[a.id]
# Override built-in names when they're assigned to.
elif type(a) == ast.Assign and type(a.targets[0]) == ast.Name:
if a.targets[0].id not in variablePairs:
name = "_var_" + a.targets[0].id + "_" + str(idNum[0])
variablePairs[a.targets[0].id] = name
elif type(a) == ast.arguments:
for arg in a.args:
if type(arg) == ast.arg:
name = "_arg_" + arg.arg + "_" + str(idNum[0])
variablePairs[arg.arg] = name
arg.arg = variablePairs[arg.arg]
return
elif type(a) == ast.Call:
if type(a.func) == ast.Name:
variablePairs[a.func.id] = a.func.id # save the function name!
for child in ast.iter_child_nodes(a):
individualizeVariables(child, variablePairs, idNum, imports)
def cleanupEquals(a):
"""Gets rid of silly blah == True statements that students make"""
if not isinstance(a, ast.AST):
return a
if type(a) == ast.Call:
a.func = cleanupEquals(a.func)
for i in range(len(a.args)):
# But test expressions don't carry through to function arguments
a.args[i] = cleanupEquals(a.args[i])
return a
elif type(a) == ast.Compare and type(a.ops[0]) in [ast.Eq, ast.NotEq]:
l = a.left = cleanupEquals(a.left)
r = cleanupEquals(a.comparators[0])
a.comparators = [r]
if type(l) == ast.NameConstant and l.value in [True, False]:
(l,r) = (r,l)
# If we have (boolean expression) == True
if type(r) == ast.NameConstant and r.value in [True, False] and (eventualType(l) == bool):
# Matching types
if (type(a.ops[0]) == ast.Eq and r.value == True) or \
(type(a.ops[0]) == ast.NotEq and r.value == False):
transferMetaData(a, l) # make sure to keep the original location
return l
else:
tmp = ast.UnaryOp(ast.Not(addedNotOp=True), l)
transferMetaData(a, tmp)
return tmp
else:
return a
else:
return applyToChildren(a, cleanupEquals)
def _compile(self):
c = _NameSubstitute()
t = c.visit(copy(self._tree))
name = repr(self)
maxarg = max((int(name[1:]) for name in c.name_cache), default=0) + 1
args = [
ast.arg(arg='_%d' % n, annotation=None)
for n in range(1, maxarg)
]
code = compile(
ast.fix_missing_locations(ast.Module(
body=[
ast.FunctionDef(
name=name,
args=ast.arguments(
args=args,
vararg=None,
kwonlyargs=[],
kw_defaults=[],
kwarg=None,
defaults=[],
),
body=[ast.Return(value=t)],
decorator_list=[],
returns=None,
lineno=1,
col_offset=0,
),
],
)),
name,
'exec',
)
ns = {}
exec(code, ns)
return asconstants(**self._constants)(ns[name])
def _make_fn(name, chain_fn, args, defaults):
args_with_self = ['_self'] + list(args)
arguments = [_ast.Name(id=arg, ctx=_ast.Load()) for arg in args_with_self]
defs = [_ast.Name(id='_def{0}'.format(idx), ctx=_ast.Load()) for idx, _ in enumerate(defaults)]
if _PY2:
parameters = _ast.arguments(args=[_ast.Name(id=arg, ctx=_ast.Param()) for arg in args_with_self],
defaults=defs)
else:
parameters = _ast.arguments(args=[_ast.arg(arg=arg) for arg in args_with_self],
kwonlyargs=[],
defaults=defs,
kw_defaults=[])
module_node = _ast.Module(body=[_ast.FunctionDef(name=name,
args=parameters,
body=[_ast.Return(value=_ast.Call(func=_ast.Name(id='_chain', ctx=_ast.Load()),
args=arguments,
keywords=[]))],
decorator_list=[])])
module_node = _ast.fix_missing_locations(module_node)
# compile the ast
code = compile(module_node, '<string>', 'exec')
# and eval it in the right context
globals_ = {'_chain': chain_fn}
locals_ = dict(('_def{0}'.format(idx), value) for idx, value in enumerate(defaults))
eval(code, globals_, locals_)
# extract our function from the newly created module
return locals_[name]
########################################################################
# Produce a docstring for the class.
def _nt_make(cls, iterable, new=tuple.__new__):
result = new(cls, iterable)
if len(result) != len(cls._fields):
raise TypeError('Expected {0} arguments, got {1}'.format(len(cls._fields), len(result)))
return result
def test_arguments(self):
x = ast.arguments()
self.assertEqual(x._fields, ('args', 'vararg', 'varargannotation',
'kwonlyargs', 'kwarg', 'kwargannotation',
'defaults', 'kw_defaults'))
with self.assertRaises(AttributeError):
x.vararg
x = ast.arguments(*range(1, 9))
self.assertEqual(x.vararg, 2)