def createNameMap(a, d=None):
if d == None:
d = { }
if not isinstance(a, ast.AST):
return d
if type(a) == ast.Module: # Need to go through the functions backwards to make this right
for i in range(len(a.body) - 1, -1, -1):
createNameMap(a.body[i], d)
return d
if type(a) in [ast.FunctionDef, ast.ClassDef]:
if hasattr(a, "originalId") and a.name not in d:
d[a.name] = a.originalId
elif type(a) == ast.arg:
if hasattr(a, "originalId") and a.arg not in d:
d[a.arg] = a.originalId
return d
elif type(a) == ast.Name:
if hasattr(a, "originalId") and a.id not in d:
d[a.id] = a.originalId
return d
for child in ast.iter_child_nodes(a):
createNameMap(child, d)
return d
python类arg()的实例源码
def basicTypeSpecialFunction(cv):
"""If you're in a number or string (which has no metadata), move up to the AST to make the special functions work."""
if isinstance(cv, SwapVector) or isinstance(cv, MoveVector):
return cv
if (cv.path[0] in [('n', 'Number'), ('s', 'String'), ('id', 'Name'), ('arg', 'Argument'),
('value', 'Name Constant'), ('s', 'Bytes'), ('name', 'Alias')]):
cvCopy = cv.deepcopy()
cv.oldSubtree = deepcopy(cvCopy.traverseTree(cv.start))
if cv.path[0] == ('n', 'Number'):
cv.newSubtree = ast.Num(cv.newSubtree)
elif cv.path[0] == ('s', 'String'):
cv.newSubtree = ast.Str(cv.newSubtree)
elif cv.path[0] == ('id', 'Name'):
cv.newSubtree = ast.Name(cv.newSubtree, cv.oldSubtree.ctx)
elif cv.path[0] == ('arg', 'Argument'):
cv.newSubtree = ast.arg(cv.newSubtree, cv.oldSubtree.annotation)
elif cv.path[0] == ('value', 'Name Constant'):
cv.newSubtree = ast.NameConstant(cv.newSubtree)
elif cv.path[0] == ('s', 'Bytes'):
cv.newSubtree = ast.Bytes(cv.newSubtree)
elif cv.path[0] == ('name', 'Alias'):
cv.newSubtree = ast.alias(cv.newSubtree, cv.oldSubtree.asname)
cv.path = cv.path[1:]
return cv
def mapVariable(a, varId, assn):
"""Map the variable assignment into the function, if it's needed"""
if type(a) != ast.FunctionDef:
return a
for arg in a.args.args:
if arg.arg == varId:
return a # overriden by local variable
for i in range(len(a.body)):
line = a.body[i]
if type(line) == ast.Assign:
for target in line.targets:
if type(target) == ast.Name and target.id == varId:
break
elif type(target) in [ast.Tuple, ast.List]:
for elt in target.elts:
if type(elt) == ast.Name and elt.id == varId:
break
if countVariables(line, varId) > 0:
a.body[i:i+1] = [deepcopy(assn), line]
break
return a
def event_changes(self, coro):
if coro.name == 'on_voice_state_update':
if self.interactive and not prompt_change(
'A possible change was found to insert the member argument into {}.'.format(coro.name)
):
return coro
coro.args.args.insert(0, ast.arg(arg='member', annotation=None))
elif coro.name in ['on_guild_emojis_update', 'on_member_ban']:
if self.interactive and not prompt_change(
'A possible change was found to insert the guild argument into {}.'.format(coro.name)
):
return coro
coro.args.args.insert(0, ast.arg(arg='guild', annotation=None))
elif coro.name in ['on_channel_delete', 'on_channel_create', 'on_channel_update']:
if self.interactive and not prompt_change(
'A possible change was found to change {} to {}.'.format(
coro.name, coro.name.replace('on_channel', 'on_guild_channel'))
):
return coro
coro.name = coro.name.replace('on_channel', 'on_guild_channel')
stats_counter['coro_changes'] += 1
return coro
def stateful_wait_for(self, call):
if isinstance(call.func, ast.Attribute):
if call.func.attr in ['wait_for_message', 'wait_for_reaction']:
if self.interactive and not prompt_change(
'A possible change was found to change {} into wait_for.'.format(call.func.attr)
):
return call
event = call.func.attr.split('_')[2]
event = 'message' if event == 'message' else 'reaction_add'
call.func.attr = 'wait_for'
if call.args:
timeout = call.args[0]
call.args = []
call.keywords.append(ast.keyword(arg='timeout', value=timeout))
call.args.insert(0, ast.Str(s=event))
for kw in list(call.keywords):
if kw.arg != 'check' and kw.arg != 'timeout':
call.keywords.remove(kw)
warnings.warn('wait_for change detected. Rewrite removes the author, channel, and content '
'keyword arguments from this method.')
stats_counter['call_changes'] += 1
return call
def _define(self, collection, name, first_node, last_node=None,
message='', confidence=DEFAULT_CONFIDENCE, ignore=None):
last_node = last_node or first_node
typ = collection.typ
if ignore and ignore(self.filename, name):
self._log('Ignoring {typ} "{name}"'.format(**locals()))
else:
try:
first_lineno = first_node.lineno
last_lineno = lines.get_last_line_number(last_node)
except AttributeError:
# ast.arg has lineno attribute since Python 3.4.
first_lineno = last_lineno = -1
collection.append(
Item(name, typ, self.filename, first_lineno, last_lineno,
message=message, confidence=confidence))
def parse_decorator(node: ast.AST):
if isinstance(node, ast.Name):
ret = Decorator()
ret.name = node.id
return ret
elif isinstance(node, ast.Call):
ret = Decorator()
ret.name = node.func.id
for arg in node.args:
if isinstance(arg, ast.Num):
ret.args.append(str(arg.n))
elif isinstance(arg, ast.Str):
ret.args.append(str(arg.n))
elif isinstance(arg, ast.Name):
ret.args.append(arg.id)
else:
v = eval_numeric_constexpr(arg)
if v:
ret.args.append(str(v))
else:
error(loc(node), "Unsupported decorator type")
return ret
else:
error(loc(node), "Supported decorators are Name and Call")
return None
def iscode(object):
"""Return true if the object is a code object.
Code objects provide these attributes:
co_argcount number of arguments (not including * or ** args)
co_code string of raw compiled bytecode
co_consts tuple of constants used in the bytecode
co_filename name of file in which this code object was created
co_firstlineno number of first line in Python source code
co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
co_lnotab encoded mapping of line numbers to bytecode indices
co_name name with which this code object was defined
co_names tuple of names of local variables
co_nlocals number of local variables
co_stacksize virtual machine stack space required
co_varnames tuple of names of arguments and local variables"""
return isinstance(object, types.CodeType)
def _too_many(f_name, args, kwonly, varargs, defcount, given, values):
atleast = len(args) - defcount
kwonly_given = len([arg for arg in kwonly if arg in values])
if varargs:
plural = atleast != 1
sig = "at least %d" % (atleast,)
elif defcount:
plural = True
sig = "from %d to %d" % (atleast, len(args))
else:
plural = len(args) != 1
sig = str(len(args))
kwonly_sig = ""
if kwonly_given:
msg = " positional argument%s (and %d keyword-only argument%s)"
kwonly_sig = (msg % ("s" if given != 1 else "", kwonly_given,
"s" if kwonly_given != 1 else ""))
raise TypeError("%s() takes %s positional argument%s but %d%s %s given" %
(f_name, sig, "s" if plural else "", given, kwonly_sig,
"was" if given == 1 and not kwonly_given else "were"))
def args(self):
args = []
for param_name, param in self._signature.parameters.items():
if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY):
break
try:
arg = self.arguments[param_name]
except KeyError:
# We're done here. Other arguments
# will be mapped in 'BoundArguments.kwargs'
break
else:
if param.kind == _VAR_POSITIONAL:
# *args
args.extend(arg)
else:
# plain argument
args.append(arg)
return tuple(args)
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 iscode(object):
"""Return true if the object is a code object.
Code objects provide these attributes:
co_argcount number of arguments (not including * or ** args)
co_code string of raw compiled bytecode
co_consts tuple of constants used in the bytecode
co_filename name of file in which this code object was created
co_firstlineno number of first line in Python source code
co_flags bitmap: 1=optimized | 2=newlocals | 4=*arg | 8=**arg
co_lnotab encoded mapping of line numbers to bytecode indices
co_name name with which this code object was defined
co_names tuple of names of local variables
co_nlocals number of local variables
co_stacksize virtual machine stack space required
co_varnames tuple of names of arguments and local variables"""
return isinstance(object, types.CodeType)
def _too_many(f_name, args, kwonly, varargs, defcount, given, values):
atleast = len(args) - defcount
kwonly_given = len([arg for arg in kwonly if arg in values])
if varargs:
plural = atleast != 1
sig = "at least %d" % (atleast,)
elif defcount:
plural = True
sig = "from %d to %d" % (atleast, len(args))
else:
plural = len(args) != 1
sig = str(len(args))
kwonly_sig = ""
if kwonly_given:
msg = " positional argument%s (and %d keyword-only argument%s)"
kwonly_sig = (msg % ("s" if given != 1 else "", kwonly_given,
"s" if kwonly_given != 1 else ""))
raise TypeError("%s() takes %s positional argument%s but %d%s %s given" %
(f_name, sig, "s" if plural else "", given, kwonly_sig,
"was" if given == 1 and not kwonly_given else "were"))
def args(self):
args = []
for param_name, param in self._signature.parameters.items():
if param.kind in (_VAR_KEYWORD, _KEYWORD_ONLY):
break
try:
arg = self.arguments[param_name]
except KeyError:
# We're done here. Other arguments
# will be mapped in 'BoundArguments.kwargs'
break
else:
if param.kind == _VAR_POSITIONAL:
# *args
args.extend(arg)
else:
# plain argument
args.append(arg)
return tuple(args)
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 _visit_local(gen_sym, node, to_mangle, mangled):
"""
Replacing known variables with literal values
"""
is_name = type(node) == ast.Name
node_id = node.id if is_name else node.arg
if node_id in to_mangle:
if node_id in mangled:
mangled_id = mangled[node_id]
else:
mangled_id, gen_sym = gen_sym('mangled')
mangled = mangled.set(node_id, mangled_id)
if is_name:
new_node = ast.Name(id=mangled_id, ctx=node.ctx)
else:
new_node = ast.arg(arg=mangled_id, annotation=node.annotation)
else:
new_node = node
return gen_sym, new_node, mangled
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 test_remove_field():
"""
Tests the removal of an AST node that is referenced by a field of the parent node.
"""
@ast_transformer
def remove_field(node, **kwds):
if isinstance(node, ast.arg) and node.arg == 'x':
return None
else:
return node
node = get_ast(dummy)
new_node = check_mutation(node, remove_field)
assert_ast_equal(new_node, get_ast("""
def dummy(y):
c = 4
a = 1
"""))
# Error checks
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
def __init__(self, opcode, arg):
self.opcode = opcode
self.arg = arg
self.length = 1 if arg is None else 3
def encode(self, start, addresses):
if self.opcode in dis.hasjabs: arg = addresses[self.arg]
elif self.opcode in dis.hasjrel: arg = addresses[self.arg] - (start+3)
else: arg = self.arg
if arg is None: return bytes([self.opcode])
else: return bytes([self.opcode, arg % 256, arg // 256])
def plumb(self, depths):
arg = 0 if isinstance(self.arg, Label) else self.arg
depths.append(depths[-1] + dis.stack_effect(self.opcode, arg))
def denotation(opcode):
if opcode < dis.HAVE_ARGUMENT:
return Instruction(opcode, None)
else:
return lambda arg: Instruction(opcode, arg)
def visit_keyword(self, t):
return self.load_const(t.arg) + self(t.value)
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_Function(self, t):
all_args = list(t.args.args) + [t.args.vararg, t.args.kwarg]
subscope = Scope(t, [arg.arg for arg in all_args if arg])
self.children[t] = subscope
for stmt in t.body: subscope.visit(stmt)
def __init__(self, opcode, arg):
self.opcode = opcode
self.arg = arg
self.length = 1 if arg is None else 3
def encode(self, start, addresses):
if self.opcode in dis.hasjabs: arg = addresses[self.arg]
elif self.opcode in dis.hasjrel: arg = addresses[self.arg] - (start+3)
else: arg = self.arg
if arg is None: return bytes([self.opcode])
else: return bytes([self.opcode, arg % 256, arg // 256])
def plumb(self, depths):
arg = 0 if isinstance(self.arg, Label) else self.arg
depths.append(depths[-1] + dis.stack_effect(self.opcode, arg))