def filterstr_to_filterfunc(filter_str: str, logged_in: bool) -> Callable[['Post'], bool]:
"""Takes an --only-if=... filter specification and makes a filter_func Callable out of it."""
# The filter_str is parsed, then all names occurring in its AST are replaced by loads to post.<name>. A
# function Post->bool is returned which evaluates the filter with the post as 'post' in its namespace.
class TransformFilterAst(ast.NodeTransformer):
def visit_Name(self, node: ast.Name):
# pylint:disable=invalid-name,no-self-use
if not isinstance(node.ctx, ast.Load):
raise InvalidArgumentException("Invalid filter: Modifying variables ({}) not allowed.".format(node.id))
if not hasattr(Post, node.id):
raise InvalidArgumentException("Invalid filter: Name {} is not defined.".format(node.id))
if node.id in Post.LOGIN_REQUIRING_PROPERTIES and not logged_in:
raise InvalidArgumentException("Invalid filter: Name {} requires being logged in.".format(node.id))
new_node = ast.Attribute(ast.copy_location(ast.Name('post', ast.Load()), node), node.id,
ast.copy_location(ast.Load(), node))
return ast.copy_location(new_node, node)
input_filename = '<--only-if parameter>'
compiled_filter = compile(TransformFilterAst().visit(ast.parse(filter_str, filename=input_filename, mode='eval')),
filename=input_filename, mode='eval')
def filterfunc(post: 'Post') -> bool:
# pylint:disable=eval-used
return bool(eval(compiled_filter, {'post': post}))
return filterfunc
python类copy_location()的实例源码
def visit_BinOp(self, node):
node = self.generic_visit(node)
left = node.left
right = node.right
if all(isinstance(value, ast.Num) for value in (left, right)):
if isinstance(node.op, tuple(self._operators.keys())):
val = self._operators[type(node.op)](left.n, right.n)
node = ast.copy_location(ast.Num(n = val), node)
return node
elif all(isinstance(value, ast.Str) for value in (left, right)):
if isinstance(node.op, ast.Add):
val = left.s + right.s
node = ast.copy_location(ast.Str(s = val), node)
return node
return self.fold(node)
#def visit_GeneratorExp(self, node):
# return self.comprehension(node)
def visit_BinOp(self, node: ast.BinOp) -> ast.BinOp:
node = self.generic_visit(node)
if self._is_numeric_mult(node):
if isinstance(node.right, ast.Num):
if node.right.n == 0:
node = ast.copy_location(ast.Num(n = 0), node)
elif node.right.n == 1:
node = node.left
elif node.right.n == 2:
node.op = ast.copy_location(ast.Add(), node.op)
node.right = copy(node.left)
elif isinstance(node.left , ast.Num):
if node.left.n == 0:
node = ast.copy_location(ast.Num(n = 0), node)
elif node.left.n == 1:
node = node.right
elif node.left.n == 2:
node.op = ast.copy_location(ast.Add(), node.op)
node.left = copy(node.right)
return node
def stateful_get_all_emojis(self, expr):
if not isinstance(expr.value, ast.Await):
return expr
if not isinstance(expr.value.value, ast.Call):
return expr
call = expr.value.value
if isinstance(call.func, ast.Attribute):
if call.func.attr == 'get_all_emojis':
if self.interactive and not prompt_change(
'A possible change was found to make get_all_emojis stateful.'
):
return expr
new_expr = ast.Expr()
new_expr.value = ast.Attribute()
new_expr.value.value = call.func.value
new_expr.value.attr = 'emojis'
new_expr.value.ctx = ast.Load()
new_expr = ast.copy_location(new_expr, expr)
stats_counter['expr_changes'] += 1
return new_expr
return expr
def subs(root, **kwargs):
'''Substitute ast.Name nodes for numbers in root using the mapping in
kwargs. Returns a new copy of root.
'''
root = copy.deepcopy(root)
class Transformer(ast.NodeTransformer):
def visit_FunctionDef(self, node):
return node
def visit_Name(self, node):
if node.id in kwargs and not isinstance(node.ctx, ast.Store):
replacement = kwargs[node.id]
if isinstance(replacement, int):
return ast.copy_location(ast.Num(n=replacement), node)
else:
return copy.copy(replacement)
else:
return node
return Transformer().visit(root)
def translate_Call_constructor(self, ctx, e):
args, keywords = e.args, e.keywords
idx = self.idx
elt_translation = []
idx_mapping = []
for i, arg in enumerate(args):
elt_translation.append(ctx.translate(arg))
n = _util.odict_idx_of(idx, i)
idx_mapping.append(n)
for keyword in keywords:
label = keyword.arg
value = keyword.value
elt_translation.append(ctx.translate(value))
n = _util.odict_idx_of(idx, label)
idx_mapping.append(n)
arg_translation = ast.Tuple(elts=elt_translation)
return ast.copy_location(_labeled_translation(idx_mapping,
arg_translation),
e)
def translate_Tuple(self, ctx, e):
elts = e.elts
rl, im = elts[0], elts[1]
rl_trans = ctx.translate(rl)
if isinstance(im, ast.Num):
n = im.n
if isinstance(n, complex):
n = n.imag
im_trans = ast.copy_location(
ast.Num(n),
im)
else:
im_trans = ctx.translate(im)
# __builtin__.complex([[rl_trans]], [[im_trans]])
return ast.copy_location(
astx.builtin_call('complex', [rl_trans, im_trans]),
e)
def propagating(maker):
result = lambda node_fn, *node_fns: lambda ctx: next(ast.copy_location(maker(node, *[n(ctx) for n in node_fns]), node)
for node in [node_fn(ctx)])
result.__name__ = maker.__name__
return result
def make_module(*stmts):
m = ast.Module(list(stmts))
return ast.copy_location(m, stmts[0]) if stmts else m
def maybe_assignment(*expr_fns):
if len(expr_fns) == 1:
node0 = expr_fns[0](ast.Load())
stmt = ast.Expr(node0)
else:
lhses = [fn(ast.Store()) for fn in expr_fns[:-1]]
node0 = lhses[0]
stmt = ast.Assign(lhses, expr_fns[-1](ast.Load()))
return ast.copy_location(stmt, node0)
def rewriter(rewrite):
def visit(self, t):
return ast.copy_location(rewrite(self, self.generic_visit(t)),
t)
return visit
def visit_Assert(self, t):
t = self.generic_visit(t)
result = ast.If(t.test,
[],
[ast.Raise(Call(ast.Name('AssertionError', load),
[] if t.msg is None else [t.msg]),
None)])
return ast.copy_location(result, t)
def visit_FunctionDef(self, t):
t = self.generic_visit(t)
fn = Function(t.name, t.args, t.body)
for d in reversed(t.decorator_list):
fn = Call(d, [fn])
result = ast.Assign([ast.Name(t.name, store)], fn)
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_Assert(self, t):
t = self.generic_visit(t)
result = ast.If(t.test,
[],
[ast.Raise(Call(ast.Name('AssertionError', load),
[] if t.msg is None else [t.msg]),
None)])
return ast.copy_location(result, t)
def visit_Lambda(self, t):
t = self.generic_visit(t)
result = Function('<lambda>', t.args, [ast.Return(t.body)])
return ast.copy_location(result, t)
def visit_FunctionDef(self, t):
t = self.generic_visit(t)
fn = Function(t.name, t.args, t.body)
for d in reversed(t.decorator_list):
fn = Call(d, [fn])
result = ast.Assign([ast.Name(t.name, store)], fn)
return ast.copy_location(result, t)
def visit_Assert(self, t):
t = self.generic_visit(t)
result = ast.If(t.test,
[],
[ast.Raise(Call(ast.Name('AssertionError', load),
[] if t.msg is None else [t.msg]),
None)])
return ast.copy_location(result, t)
def visit_Lambda(self, t):
t = self.generic_visit(t)
result = Function('<lambda>', t.args, [ast.Return(t.body)])
return ast.copy_location(result, t)
def visit_FunctionDef(self, t):
t = self.generic_visit(t)
fn = Function(t.name, t.args, t.body)
for d in reversed(t.decorator_list):
fn = Call(d, [fn])
result = ast.Assign([ast.Name(t.name, store)], fn)
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_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def visit_Attribute(self, node):
"""Flatten one level of attribute access."""
new_node = ast.Name("%s.%s" % (node.value.id, node.attr), node.ctx)
return ast.copy_location(new_node, node)
def ast_to_module(node: ast.AST, old_module: types.ModuleType = None, file: str = None) -> types.ModuleType:
"""
Compile node object to module.
"""
if node and not isinstance(node, ast.AST):
raise TypeError('Unexpected type for node: {}'.format(str(type(node))))
if old_module and not isinstance(old_module, types.ModuleType):
raise TypeError('Unexpected type for old_module: {}'.format(str(type(old_module))))
if not isinstance(node, ast.Module):
node = ast.copy_location(ast.Module(body = [node]), node)
file = file or (inspect.getfile(old_module) if old_module else None)
code = _call_with_frames_removed\
( compile
, source = node
, filename = file or '<file>'
, mode = 'exec'
, dont_inherit = True
)
module = old_module or types.ModuleType()
exec(code, module.__dict__)
return module
def ast_to_func(node: ast.AST, old_func: types.FunctionType, file: str = None) -> types.FunctionType:
"""
Compile node object to function.
"""
if node and not isinstance(node, (ast.Module, ast.FunctionDef)):
raise TypeError('Unexpected type for node: {}'.format(str(type(node))))
if old_func and not isinstance(old_func, types.FunctionType):
raise TypeError('Unexpected type for old_func: {}'.format(str(type(old_func))))
result = old_func
if node and old_func:
old_code = getattr(old_func, '__code__', None)
if not isinstance(node, ast.Module):
mod_node = ast.copy_location(ast.Module(body = [node]), node)
fun_node = node
else:
mod_node = node
fun_node = node.body[0]
module = ast_to_code(mod_node, old_code, file=file)
for code in module.co_consts:
if not isinstance(code, types.CodeType):
continue
if code.co_name == fun_node.name and code.co_firstlineno == fun_node.lineno:
result.__code__ = code
break
else:
raise ValueError('Not specified value')
return result
def convert(self, node):
code = compile(node, '<string>', mode = 'eval')
value = eval(code)
new_node = ast.parse(str(value), mode = 'eval')
if isinstance(new_node, ast.Expression):
new_node = new_node.body
new_node = self.generic_visit(new_node)
node = ast.copy_location(new_node, node)
node = ast.fix_missing_locations(node)
return node