def inner(array_id: str) -> typing.Iterator[CStatements]: if alloc.name: # get shape shape_tuple_id = identifier() yield CallUnary(ShapeAsTuple(Sequence(length, getitem)), shape_tuple_id) # allocate array array = ast.Call( ast.Attribute(ast.Name("np", ast.Load()), "empty", ast.Load()), [ast.Name(shape_tuple_id.name, ast.Load())], [], ) yield VectorCallable( Statement(ast.Assign([ast.Name(array_id, ast.Store())], array))) length_id = identifier() yield CallUnary(Initializer(ToPythonContent(length)), length_id) index_id = identifier() result_id = identifier() # result = getitem(i) initialize_result = CallUnary( Initializer( ToNPArray( CallUnary(getitem, python_content_from_id(index_id)), ShouldAllocate(False), )), result_id, ) # result = array[i] set_result = ast.Assign( [ast.Name(result_id.name, ast.Store())], ast.Subscript( ast.Name(array_id, ast.Load()), ast.Index(ast.Name(index_id.name, ast.Load())), ast.Load(), ), ) # we have to assign twice, this is for scalar case previous is for sequence # need to look into this more # array[i] = result set_array = ast.Assign( [ ast.Subscript( ast.Name(array_id, ast.Load()), ast.Index(ast.Name(index_id.name, ast.Load())), ast.Store(), ) ], ast.Name(result_id.name, ast.Load()), ) # range(length) range_expr = ast.Call(ast.Name("range", ast.Load()), [ast.Name(length_id.name, ast.Load())], []) @SubstituteStatements def inner(*results_initializer: ast.AST) -> CStatements: # for i in range(length): return VectorCallable( Statement( ast.For( ast.Name(index_id.name, ast.Store()), range_expr, [set_result, *results_initializer, set_array], [], ))) yield CallUnary(inner, initialize_result)
def getASTNode(self, val): if val.isdigit(): return ast.Num(n=int(val)) else: return ast.Name(id=val, ctx=ast.Load())
def assign(self, expr): """Give *expr* a name.""" name = self.variable() self.statements.append(ast.Assign([ast.Name(name, ast.Store())], expr)) return ast.Name(name, ast.Load())
ast.arguments( defaults=[1], posonlyargs=[], args=[], kw_defaults=[], kwonlyargs=[], ), ast.arguments( defaults=[], posonlyargs=[], args=[], kw_defaults=[1], kwonlyargs=[], ), ast.AnnAssign(simple=True, target=ast.Tuple(ast.Name("a", ast.Load()))), ast.With(items=[]), ast.Raise(exc=None, cause=1), ast.Try(body=[]), ast.Try(body=[ast.Pass()], handlers=[], finalbody=[]), ast.Try( body=[ast.Pass()], handlers=[], finalbody=[ast.Pass()], orelse=[ast.Pass()], ), ast.ImportFrom(level=-1, names=[1]), ast.BoolOp(values=[1]), ast.Dict(keys=[1], values=[]), ast.Compare(comparators=[]), ast.Compare(comparators=[1], ops=[]),
def builtin(self, name): """Return the builtin called *name*.""" builtin_name = ast.Name("@py_builtins", ast.Load()) return ast.Attribute(builtin_name, name, ast.Load())
def getattr(self, node, name): return ast.Attribute(node, name, ast.Load())
def return_type_test(expr: str, arg_type: type, expected_type: type): s = ast_lambda(expr) objs = ObjectStream(ast.Name(id="e", ctx=ast.Load()), arg_type) _, _, expr_type = remap_by_types(objs, "e", arg_type, s) assert expr_type == expected_type
class PhYtographer_argparse(ast.NodeTransformer): def __init__(self): # Maybe allow for people to include argparse as ssomething else # But totally screw the from argparse import * nonsense self.argparse_variable_names = ["argparse"] self.found_arguments = [] self.found_parsed_argument_handles = [] ast.Assign(targets=[ ast.Name(id='target', ctx=ast.Store(), lineno=75, col_offset=15), ], value=ast.Subscript( value=ast.Attribute(value=ast.Name(id='sys', ctx=ast.Load(), lineno=75, col_offset=24), attr='argv', ctx=ast.Load(), lineno=75, col_offset=24), slice=ast.Index(value=ast.Num(n=1, lineno=75, col_offset=33)), ctx=ast.Load(), lineno=75, col_offset=24), lineno=75, col_offset=15) def visit_Assign(self, node): # Find the instances of argparse that are an ArgumentParser and add them to the argparse_variable_names section if not hasattr(node.value, '__iter__'): if isinstance(node.value, ast.Call): if isinstance(node.value.func, ast.Attribute): if isinstance(node.value.func.value, ast.Name): # Finds the Argparse instances of Argument Parser or similar if node.value.func.value.id in self.argparse_variable_names and node.value.func.attr in [ "ArgumentParser", "add_argument_group", "add_mutually_exclusive_group"]: self.argparse_variable_names.append(node.targets[0].id) return None # Finds parsed args variable names to replace with self later if len(node.targets) == 1: if hasattr(node.value, "func"): if node.value.func.attr == "parse_args": if node.value.func.value.id in self.argparse_variable_names: self.found_parsed_argument_handles.append(node.targets[0].id) return None return node def visit_Attribute(self, node): if isinstance(node.value, ast.Name): if node.value.id in self.found_parsed_argument_handles: node.value.id = 'self' return node return node def visit_Expr(self, node): if isinstance(node.value, ast.Call): if isinstance(node.value.func, ast.Attribute): if node.value.func.attr in ["add_argument"]: if isinstance(node.value.func.value, ast.Name): if node.value.func.value.id in self.argparse_variable_names: temp_found_argument = {"static": [], "keyword": {}} for static_argument in node.value.args: if isinstance(static_argument, ast.Str): temp_found_argument["static"].append(static_argument.s) for keyword_argument in node.value.keywords: if isinstance(keyword_argument, ast.keyword): if isinstance(keyword_argument.value, ast.Str): temp_found_argument["keyword"][keyword_argument.arg] = keyword_argument.value.s if isinstance(keyword_argument.value, ast.NameConstant): temp_found_argument["keyword"][ keyword_argument.arg] = keyword_argument.value.value if isinstance(keyword_argument.value, ast.Num): temp_found_argument["keyword"][keyword_argument.arg] = keyword_argument.value.n self.found_arguments.append(temp_found_argument) return None return node
""" """ import json import logging import ast import difflib import sys import os.path import astor CHECKS = { "array": ast.Tuple(ctx=ast.Load(), elts=[ ast.Name(id='list', ctx=ast.Load()), ast.Name(id='tuple', ctx=ast.Load()) ]), # "(list, tuple)", "boolean": ast.Tuple(ctx=ast.Load(), elts=[ast.Name(id='bool', ctx=ast.Load())]), # "(bool, )", "integer": ast.Tuple(ctx=ast.Load(), elts=[ast.Name(id='int', ctx=ast.Load())]), # "(int, )", "number": ast.Tuple(ctx=ast.Load(), elts=[ ast.Name(id='float', ctx=ast.Load()), ast.Name(id='int', ctx=ast.Load()) ]), # "(float, int)", "string":
class _EvaluateFalseTransformer(sympy_parser.EvaluateFalseTransformer): """Extend default SymPy EvaluateFalseTransformer to affect functions too. The SymPy version does not force function calls to be 'evaluate=False', which means expressions like "log(x, 10)" get simplified to "log(x)/log(10)" or "cos(-x)" becomes "cos(x)". For our purposes, this is unhelpful and so we also prevent this from occuring. Currently there is a list of functions not to transform, because some do not support the "evaluate=False" argument. This isn't particularly nice or future proof! """ _evaluate_false_keyword = ast.keyword(arg='evaluate', value=ast.Name(id='False', ctx=ast.Load())) _one = ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()), args=[ast.Num(n=1)], keywords=[]) _minus_one = ast.UnaryOp(op=ast.USub(), operand=_one) _bool_ops = {ast.And: "And", ast.Or: "Or"} def visit_Call(self, node): """Ensure all function calls are 'evaluate=False'.""" # Since we have overridden the visit method, we are now responsible for # ensuring all child nodes are visited too. This is done most simply by # calling generic_visit(...) on ourself: self.generic_visit(node) # FIXME: Some functions cannot accept "evaluate=False" as an argument # without their __new__() method raising a TypeError. There is probably # some underlying reason which we could take into account of. # For now, blacklist those known to be problematic: _ignore_functions = ["Integer", "Float", "Symbol", "factorial"] if node.func.id in _ignore_functions: # print("\tIgnoring function: {}".format(node.func.id)) pass else: # print("\tModifying function: {}".format(node.func.id)) node.keywords.append(self._evaluate_false_keyword) # We must return the node, modified or not: return node def visit_Compare(self, node): """Ensure all comparisons use sympy classes with 'evaluate=False'.""" # Can't cope with comparing multiple inequalities: if len(node.comparators) > 1: raise TypeError("Cannot parse nested inequalities!") # As above, must ensure child nodes are visited: self.generic_visit(node) # Use the custom Equals class if equality, otherwise swap with a know relation: operator_class = node.ops[0].__class__ if isinstance(node.ops[0], ast.Eq): return ast.Call(func=ast.Name(id='Eq', ctx=ast.Load()), args=[node.left, node.comparators[0]], keywords=[self._evaluate_false_keyword]) elif operator_class in RELATIONS: return ast.Call(func=ast.Name(id='Rel', ctx=ast.Load()), args=[ node.left, node.comparators[0], ast.Str(RELATIONS[operator_class]) ], keywords=[self._evaluate_false_keyword]) else: # An unknown type of relation. Leave alone: return node def sympy_visit_BinOp(self, node): """Convert some operators to SymPy equivalents. This method is mostly copied from SymPy directly, but there is a fix to the nesting of Mul not yet in the upstream! """ if node.op.__class__ in self.operators: sympy_class = self.operators[node.op.__class__] right = self.visit(node.right) left = self.visit(node.left) if isinstance(node.left, ast.UnaryOp) and not isinstance( node.right, ast.UnaryOp) and sympy_class in ('Mul', ): left, right = right, left if isinstance(node.op, ast.Sub): right = ast.Call( func=ast.Name(id='Mul', ctx=ast.Load()), # Ensure Mul objects don't end up nested: args=self.flatten([self._minus_one, right], 'Mul'), keywords=[self._evaluate_false_keyword]) if isinstance(node.op, ast.Div): if isinstance(node.left, ast.UnaryOp): if isinstance(node.right, ast.UnaryOp): left, right = right, left left = ast.Call(func=ast.Name(id='Pow', ctx=ast.Load()), args=[left, self._minus_one], keywords=[self._evaluate_false_keyword]) else: right = ast.Call(func=ast.Name(id='Pow', ctx=ast.Load()), args=[right, self._minus_one], keywords=[self._evaluate_false_keyword]) new_node = ast.Call(func=ast.Name(id=sympy_class, ctx=ast.Load()), args=[left, right], keywords=[self._evaluate_false_keyword]) if sympy_class in ('Add', 'Mul'): # Denest Add or Mul as appropriate new_node.args = self.flatten(new_node.args, sympy_class) return new_node return node def visit_BinOp(self, node): """Ensure bitwise operations are modified into SymPy operations. This function also calls a SymPy function to convert Add, Sub, Mul and Div into SymPy classes. """ node_class = node.op.__class__ # "Implies", which overloads bit-shifting, mustn't get simplified: if node_class in [ast.LShift, ast.RShift]: # As above, must ensure child nodes are visited: right = self.generic_visit(node.right) left = self.generic_visit(node.left) if node_class is ast.LShift: left, right = right, left return ast.Call(func=ast.Name(id="Implies", ctx=ast.Load()), args=[left, right], keywords=[self._evaluate_false_keyword]) # "Xor" must be transformed from Bitwise to Boolean, and not simplified either: elif node_class == ast.BitXor: right = self.generic_visit(node.right) left = self.generic_visit(node.left) return ast.Call(func=ast.Name(id="Xor", ctx=ast.Load()), args=[left, right], keywords=[self._evaluate_false_keyword]) else: # Otherwise we want ensure the parent SymPy method runs on this node, # to save re-writing that code here: return self.sympy_visit_BinOp(node) def visit_BoolOp(self, node): """Ensure And and Or are not simplified.""" # As above, must ensure child nodes are visited: self.generic_visit(node) # Fix the boolean operations to SymPy versions to ensure no simplification: node_class = node.op.__class__ if node_class in self._bool_ops: return ast.Call(func=ast.Name(id=self._bool_ops[node_class], ctx=ast.Load()), args=node.values, keywords=[self._evaluate_false_keyword]) else: # An unknown type of boolean operation. Leave alone: return node def visit_UnaryOp(self, node): """Ensure boolean Not is not simplified and unary minus is consistent.""" node_class = node.op.__class__ # As above, must ensure child nodes are visited: self.generic_visit(node) # Fix the boolean Not to the SymPy version to ensure no simplification: if node_class in [ast.Not, ast.Invert]: return ast.Call(func=ast.Name(id="Not", ctx=ast.Load()), args=[node.operand], keywords=[self._evaluate_false_keyword]) # Replace all uses of unary minus with multiplication by minus one for # consistency reasons: elif node_class in [ast.USub]: return ast.Call( func=ast.Name(id='Mul', ctx=ast.Load()), # Ensure Mul objects don't end up nested: args=self.flatten([self._minus_one, node.operand], 'Mul'), keywords=[self._evaluate_false_keyword]) else: # Only interested these; leave everything else alone: return node
import ast ASTNone = ast.NameConstant(value=None) dirFunc = ast.Name(id="dir", ctx=ast.Load()) strAST = ast.Name(id="str", ctx=ast.Load()) getAttrFunc = ast.Name(id="getattr", ctx=ast.Load()) ASTSelf = ast.Name(id="self", ctx=ast.Load()) astSelfArg = ast.arg(arg="self", annotation=None, type_comment=None) ASTSelfClass = ast.Attribute(value=ASTSelf, attr="__class__", ctx=ast.Load()) AST__slots__ = ast.Name(id="__slots__", ctx=ast.Load()) emptySlots = ast.Assign(targets=[ast.Name(id="__slots__", ctx=ast.Store())], value=ast.Tuple(elts=[], ctx=ast.Load()), type_comment=None) ASTTypeError = ast.Name(id="TypeError", ctx=ast.Load()) typingAST = ast.Name(id="typing", ctx=ast.Load()) typingOptionalAST = ast.Attribute(value=typingAST, attr="Optional") typingIterableAST = ast.Attribute(value=typingAST, attr="Iterable") typingUnionAST = ast.Attribute(value=typingAST, attr="Union")
def visit_Name(self, node): return ast.Name(id=self.mapping.get(node.id, node.id), ctx=ast.Load())
def _get_attr_node(names): """Builds an Attribute node, or a Name node if names has just one entry.""" node = ast.Name(id=names[0], ctx=ast.Load()) for name in names[1:]: node = ast.Attribute(value=node, attr=name, ctx=ast.Load()) return node
from collections import namedtuple from mdtraj.utils.six import PY2 from mdtraj.utils.external.pyparsing import (Word, ParserElement, MatchFirst, Keyword, opAssoc, quotedString, alphas, alphanums, infixNotation, Group, Optional, ParseException) from mdtraj.utils.external.astor import codegen ParserElement.enablePackrat() __all__ = ['parse_selection'] # ############################################################################ # Globals # ############################################################################ NUMS = '.0123456789' THIS_ATOM = ast.Name(id='atom', ctx=ast.Load(), SINGLETON=True) RE_MODULE = ast.Name(id='re', ctx=ast.Load(), SINGLETON=True) SELECTION_GLOBALS = {'re': re} _ParsedSelection = namedtuple('_ParsedSelection', ['expr', 'source', 'astnode']) # ############################################################################ # Utils # ############################################################################ class _RewriteNames(ast.NodeTransformer): def visit_Name(self, node): if hasattr(node, 'SINGLETON'): return node _safe_names = {'None': None, 'True': True, 'False': False} if node.id in _safe_names:
def repr(self, load_name_node): return ast.Call(func=ast.Name('repr', ast.Load()), args=[load_name_node], keywords=[])
def __build__init(self): super_func_call = ast.Call(func=ast.Name(id='super', ctx=ast.Load()), args=[], keywords=[]) if (sys.version_info[0], sys.version_info[1]) == (3, 5) or \ (sys.version_info[0], sys.version_info[1]) == (3, 6) or \ (sys.version_info[0], sys.version_info[1]) == (3, 7): super_func = ast.Call( func=ast.Attribute(value=super_func_call, attr='__init__', ctx=ast.Load()), args=[ ast.Starred(value=ast.Name(id='args', ctx=ast.Load()), ctx=ast.Load()) ], keywords=[ ast.keyword(arg=None, value=ast.Name(id='kwargs', ctx=ast.Load()), ctx=ast.Load()) ], ) elif (sys.version_info[0], sys.version_info[1]) == (3, 4): super_func = ast.Call( func=ast.Attribute(value=super_func_call, attr='__init__', ctx=ast.Load()), args=[], keywords=[], starargs=ast.Name(id='args', ctx=ast.Load()), kwargs=ast.Name(id='kwargs', ctx=ast.Load()), ) else: print("Version:", sys.version_info) raise RuntimeError( "This script only functions on python 3.4, 3.5, 3.6, or 3.7. Active python version {}.{}" .format(*sys.version_info)) super_init = ast.Expr( value=super_func, lineno=self.__get_line(), col_offset=0, ) body = [super_init] sig = ast.arguments(args=[ast.arg('self', None)], vararg=ast.arg(arg='args', annotation=None), kwarg=ast.arg(arg='kwargs', annotation=None), varargannotation=None, kwonlyargs=[], kwargannotation=None, defaults=[], kw_defaults=[]) func = ast.FunctionDef( name="__init__", args=sig, body=body, decorator_list=[], lineno=self.__get_line(), col_offset=0, ) return func
def load(self, name): return ast.Name(name, ast.Load())
def __build_function(self, dom_name, full_name, func_params): assert 'name' in func_params func_name = func_params['name'] docstr = self.__build_desc_string(dom_name, func_name, func_params) args = [ast.arg('self', None)] message_params = [] func_body = [] if docstr: func_body.append(ast.Expr(ast.Str("\n" + docstr + "\n\t\t"))) for param in func_params.get("parameters", []): argname = param['name'] param_optional = param.get("optional", False) if param_optional is False: message_params.append( ast.keyword(argname, ast.Name(id=argname, ctx=ast.Load()))) args.append(ast.arg(argname, None)) if self.do_debug_prints: func_body.append(self.__build_debug_print( argname, argname)) param_type = param.get("type", None) if param_type in CHECKS: if param_optional: check = self.__build_conditional_arg_check( argname, CHECKS[param_type]) else: check = self.__build_unconditional_arg_check( argname, CHECKS[param_type]) if check: func_body.append(check) optional_params = [ param.get("name") for param in func_params.get("parameters", []) if param.get("optional", False) ] func_kwargs = None if len(optional_params): value = ast.List(elts=[ ast.Str(s=param, ctx=ast.Store()) for param in optional_params ], ctx=ast.Load()) create_list = ast.Assign( targets=[ast.Name(id='expected', ctx=ast.Store())], value=value) func_body.append(create_list) passed_arg_list = ast.Assign( targets=[ast.Name(id='passed_keys', ctx=ast.Store())], value=ast.Call(func=ast.Name(id='list', ctx=ast.Load()), args=[ ast.Call(func=ast.Attribute(value=ast.Name( id='kwargs', ctx=ast.Load()), attr='keys', ctx=ast.Load()), args=[], keywords=[]) ], keywords=[])) func_body.append(passed_arg_list) comprehension = ast.comprehension(target=ast.Name(id='key', ctx=ast.Store()), iter=ast.Name(id='passed_keys', ctx=ast.Load()), ifs=[], is_async=False) comparator = ast.Name(id='expected', ctx=ast.Load()) listcomp = ast.ListComp(elt=ast.Compare(left=ast.Name( id='key', ctx=ast.Load()), ops=[ast.In()], comparators=[comparator]), generators=[comprehension]) check_message = ast.BinOp(left=ast.Str( s="Allowed kwargs are {}. Passed kwargs: %s".format( optional_params)), op=ast.Mod(), right=ast.Name(id='passed_keys', ctx=ast.Load()), lineno=self.__get_line()) kwarg_check = ast.Assert(test=ast.Call(func=ast.Name( id='all', ctx=ast.Load()), args=[listcomp], keywords=[]), msg=check_message) func_body.append(kwarg_check) func_kwargs = ast.Name(id='kwargs', ctx=ast.Load()) fname = "{}.{}".format(dom_name, func_name) fname = ast.Str(s=fname, ctx=ast.Load()) if (sys.version_info[0], sys.version_info[1]) == (3, 5) or \ (sys.version_info[0], sys.version_info[1]) == (3, 6) or \ (sys.version_info[0], sys.version_info[1]) == (3, 7): # More irritating minor semantic differences in the AST between 3.4 and 3.5 if func_kwargs: message_params.append( ast.keyword(arg=None, value=ast.Name(id='kwargs', ctx=ast.Load()))) communicate_call = ast.Call(func=ast.Attribute( value=ast.Name(id='self', ctx=ast.Load()), ctx=ast.Load(), attr='synchronous_command'), args=[fname], keywords=message_params) elif (sys.version_info[0], sys.version_info[1]) == (3, 4): communicate_call = ast.Call(func=ast.Attribute( value=ast.Name(id='self', ctx=ast.Load()), ctx=ast.Load(), attr='synchronous_command'), args=[fname], kwargs=func_kwargs, keywords=message_params) else: print("Version:", sys.version_info) raise RuntimeError( "This script only functions on python 3.4, 3.5, 3.6, or 3.7. Active python version {}.{}" .format(*sys.version_info)) do_communicate = ast.Assign( targets=[ast.Name(id='subdom_funcs', ctx=ast.Store())], value=communicate_call) func_ret = ast.Return( value=ast.Name(id='subdom_funcs', ctx=ast.Load())) if len(optional_params) and self.do_debug_prints: func_body.append(self.__build_debug_print('kwargs', 'kwargs')) func_body.append(do_communicate) func_body.append(func_ret) if len(optional_params): kwarg = ast.arg(arg='kwargs', annotation=None) else: kwarg = None sig = ast.arguments(args=args, vararg=None, varargannotation=None, kwonlyargs=[], kwarg=kwarg, kwargannotation=None, defaults=[], kw_defaults=[]) func = ast.FunctionDef( name="{}_{}".format(full_name, func_name), args=sig, body=func_body, decorator_list=[], lineno=self.__get_line(), col_offset=0, ) return func
def _compile_directive_call_assets(self, el, options): """ This special 't-call' tag can be used in order to aggregate/minify javascript and css assets""" if len(el): raise SyntaxError("t-call-assets cannot contain children nodes") # nodes = self._get_asset_nodes(bundle, options, css=css, js=js, debug=values.get('debug'), async=async, values=values) # # for index, (tagName, t_attrs, content) in enumerate(nodes): # if index: # append('\n ') # append('<') # append(tagName) # # self._post_processing_att(tagName, t_attrs, options) # for name, value in t_attrs.items(): # if value or isinstance(value, string_types)): # append(u' ') # append(name) # append(u'="') # append(escape(pycompat.to_text((value))) # append(u'"') # # if not content and tagName in self._void_elements: # append('/>') # else: # append('>') # if content: # append(content) # append('</') # append(tagName) # append('>') # space = el.getprevious() is not None and el.getprevious( ).tail or el.getparent().text sep = u'\n' + space.rsplit('\n').pop() return [ ast.Assign( targets=[ast.Name(id='nodes', ctx=ast.Store())], value=ast.Call( func=ast.Attribute(value=ast.Name(id='self', ctx=ast.Load()), attr='_get_asset_nodes', ctx=ast.Load()), args=[ ast.Str(el.get('t-call-assets')), ast.Name(id='options', ctx=ast.Load()), ], keywords=[ ast.keyword('css', self._get_attr_bool(el.get('t-css', True))), ast.keyword('js', self._get_attr_bool(el.get('t-js', True))), ast.keyword( 'debug', ast.Call(func=ast.Attribute(value=ast.Name( id='values', ctx=ast.Load()), attr='get', ctx=ast.Load()), args=[ast.Str('debug')], keywords=[], starargs=None, kwargs=None)), ast.keyword( 'async_load', self._get_attr_bool(el.get('async_load', False))), ast.keyword( 'defer_load', self._get_attr_bool(el.get('defer_load', False))), ast.keyword( 'lazy_load', self._get_attr_bool(el.get('lazy_load', False))), ast.keyword('media', ast.Constant(el.get('media'))), ], starargs=None, kwargs=None)), ast.For( target=ast.Tuple(elts=[ ast.Name(id='index', ctx=ast.Store()), ast.Tuple(elts=[ ast.Name(id='tagName', ctx=ast.Store()), ast.Name(id='t_attrs', ctx=ast.Store()), ast.Name(id='content', ctx=ast.Store()) ], ctx=ast.Store()) ], ctx=ast.Store()), iter=ast.Call(func=ast.Name(id='enumerate', ctx=ast.Load()), args=[ast.Name(id='nodes', ctx=ast.Load())], keywords=[], starargs=None, kwargs=None), body=[ ast.If(test=ast.Name(id='index', ctx=ast.Load()), body=[self._append(ast.Str(sep))], orelse=[]), self._append(ast.Str(u'<')), self._append(ast.Name(id='tagName', ctx=ast.Load())), ] + self._append_attributes() + [ ast.If(test=ast.BoolOp( op=ast.And(), values=[ ast.UnaryOp(ast.Not(), ast.Name(id='content', ctx=ast.Load()), lineno=0, col_offset=0), ast.Compare( left=ast.Name(id='tagName', ctx=ast.Load()), ops=[ast.In()], comparators=[ ast.Attribute(value=ast.Name( id='self', ctx=ast.Load()), attr='_void_elements', ctx=ast.Load()) ]), ]), body=[self._append(ast.Str(u'/>'))], orelse=[ self._append(ast.Str(u'>')), ast.If(test=ast.Name(id='content', ctx=ast.Load()), body=[ self._append( ast.Name(id='content', ctx=ast.Load())) ], orelse=[]), self._append(ast.Str(u'</')), self._append( ast.Name(id='tagName', ctx=ast.Load())), self._append(ast.Str(u'>')), ]) ], orelse=[]) ]
def _transform_js_to_python_identifier(obj): return ast.Name(id=obj["name"], ctx=ast.Load(), lineno=0, col_offset=0)
def visit_Assert(self, assert_): """Return the AST statements to replace the ast.Assert instance. This rewrites the test of an assertion to provide intermediate values and replace it with an if statement which raises an assertion error with a detailed explanation in case the expression is false. """ if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1: from _pytest.warning_types import PytestAssertRewriteWarning import warnings warnings.warn_explicit( PytestAssertRewriteWarning( "assertion is always true, perhaps remove parentheses?" ), category=None, filename=fspath(self.module_path), lineno=assert_.lineno, ) self.statements = [] # type: List[ast.stmt] self.variables = [] # type: List[str] self.variable_counter = itertools.count() if self.enable_assertion_pass_hook: self.format_variables = [] # type: List[str] self.stack = [] # type: List[Dict[str, ast.expr]] self.expl_stmts = [] # type: List[ast.stmt] self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) negation = ast.UnaryOp(ast.Not(), top_condition) if self.enable_assertion_pass_hook: # Experimental pytest_assertion_pass hook msg = self.pop_format_context(ast.Str(explanation)) # Failed if assert_.msg: assertmsg = self.helper("_format_assertmsg", assert_.msg) gluestr = "\n>assert " else: assertmsg = ast.Str("") gluestr = "assert " err_explanation = ast.BinOp(ast.Str(gluestr), ast.Add(), msg) err_msg = ast.BinOp(assertmsg, ast.Add(), err_explanation) err_name = ast.Name("AssertionError", ast.Load()) fmt = self.helper("_format_explanation", err_msg) exc = ast.Call(err_name, [fmt], []) raise_ = ast.Raise(exc, None) statements_fail = [] statements_fail.extend(self.expl_stmts) statements_fail.append(raise_) # Passed fmt_pass = self.helper("_format_explanation", msg) orig = self._assert_expr_to_lineno()[assert_.lineno] hook_call_pass = ast.Expr( self.helper( "_call_assertion_pass", ast.Num(assert_.lineno), ast.Str(orig), fmt_pass, ) ) # If any hooks implement assert_pass hook hook_impl_test = ast.If( self.helper("_check_if_assertion_pass_impl"), self.expl_stmts + [hook_call_pass], [], ) statements_pass = [hook_impl_test] # Test for assertion condition main_test = ast.If(negation, statements_fail, statements_pass) self.statements.append(main_test) if self.format_variables: variables = [ ast.Name(name, ast.Store()) for name in self.format_variables ] clear_format = ast.Assign(variables, ast.NameConstant(None)) self.statements.append(clear_format) else: # Original assertion rewriting # Create failure message. body = self.expl_stmts self.statements.append(ast.If(negation, body, [])) if assert_.msg: assertmsg = self.helper("_format_assertmsg", assert_.msg) explanation = "\n>assert " + explanation else: assertmsg = ast.Str("") explanation = "assert " + explanation template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation)) msg = self.pop_format_context(template) fmt = self.helper("_format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) exc = ast.Call(err_name, [fmt], []) raise_ = ast.Raise(exc, None) body.append(raise_) # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] clear = ast.Assign(variables, ast.NameConstant(None)) self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) return self.statements
def var(id): return ast.Name(id=id, ctx=ast.Load())
def node(self): node = ast.Name(self.temp_name, ast.Load()) node.type = self.type node.variable = self return node
def visit_Call(self, node): """ Transform call site to have normal function call. Examples -------- For methods: >> a = [1, 2, 3] >> a.append(1) Becomes >> __list__.append(a, 1) For functions: >> __builtin__.dict.fromkeys([1, 2, 3]) Becomes >> __builtin__.__dict__.fromkeys([1, 2, 3]) """ node = self.generic_visit(node) # Only attributes function can be Pythonic and should be normalized if isinstance(node.func, ast.Attribute): if node.func.attr in methods: # Get object targeted by methods obj = lhs = node.func.value # Get the most left identifier to check if it is not an # imported module while isinstance(obj, ast.Attribute): obj = obj.value is_not_module = (not isinstance(obj, ast.Name) or obj.id not in self.imports) if is_not_module: # As it was a methods call, push targeted object as first # arguments and add correct module prefix node.args.insert(0, lhs) mod = methods[node.func.attr][0] # Submodules import full module self.to_import.add(mod[0]) node.func = reduce( lambda v, o: ast.Attribute(v, o, ast.Load()), mod[1:] + (node.func.attr,), ast.Name(mod[0], ast.Load()) ) # else methods have been called using function syntax if node.func.attr in methods or node.func.attr in functions: # Now, methods and function have both function syntax def rec(path, cur_module): """ Recursively rename path content looking in matching module. Prefers __module__ to module if it exists. This recursion is done as modules are visited top->bottom while attributes have to be visited bottom->top. """ err = "Function path is chained attributes and name" assert isinstance(path, (ast.Name, ast.Attribute)), err if isinstance(path, ast.Attribute): new_node, cur_module = rec(path.value, cur_module) new_id = self.renamer(path.attr, cur_module) return (ast.Attribute(new_node, new_id, ast.Load()), cur_module[new_id]) else: new_id = self.renamer(path.id, cur_module) return ast.Name(new_id, ast.Load()), cur_module[new_id] # Rename module path to avoid naming issue. node.func.value, _ = rec(node.func.value, MODULES) return node
def visit_Assert(self, assert_): """Return the AST statements to replace the ast.Assert instance. This rewrites the test of an assertion to provide intermediate values and replace it with an if statement which raises an assertion error with a detailed explanation in case the expression is false. """ if isinstance(assert_.test, ast.Tuple) and len(assert_.test.elts) >= 1: from _pytest.warning_types import PytestAssertRewriteWarning import warnings warnings.warn_explicit( PytestAssertRewriteWarning( "assertion is always true, perhaps remove parentheses?" ), category=None, filename=str(self.module_path), lineno=assert_.lineno, ) self.statements = [] self.variables = [] self.variable_counter = itertools.count() self.stack = [] self.on_failure = [] self.push_format_context() # Rewrite assert into a bunch of statements. top_condition, explanation = self.visit(assert_.test) # If in a test module, check if directly asserting None, in order to warn [Issue #3191] if self.module_path is not None: self.statements.append( self.warn_about_none_ast( top_condition, module_path=self.module_path, lineno=assert_.lineno ) ) # Create failure message. body = self.on_failure negation = ast.UnaryOp(ast.Not(), top_condition) self.statements.append(ast.If(negation, body, [])) if assert_.msg: assertmsg = self.helper("_format_assertmsg", assert_.msg) explanation = "\n>assert " + explanation else: assertmsg = ast.Str("") explanation = "assert " + explanation template = ast.BinOp(assertmsg, ast.Add(), ast.Str(explanation)) msg = self.pop_format_context(template) fmt = self.helper("_format_explanation", msg) err_name = ast.Name("AssertionError", ast.Load()) exc = ast_Call(err_name, [fmt], []) if sys.version_info[0] >= 3: raise_ = ast.Raise(exc, None) else: raise_ = ast.Raise(exc, None, None) body.append(raise_) # Clear temporary variables by setting them to None. if self.variables: variables = [ast.Name(name, ast.Store()) for name in self.variables] clear = ast.Assign(variables, _NameConstant(None)) self.statements.append(clear) # Fix line numbers. for stmt in self.statements: set_location(stmt, assert_.lineno, assert_.col_offset) return self.statements
def visit_Num(self, node): if isinstance(node.n, int): return ast.Call(func=ast.Name(id='Integer', ctx=ast.Load()), args=[node], keywords=[], starargs=None, kwargs=None) return node
def _NameConstant(c): return ast.Name(str(c), ast.Load())
def visit_Call(self, call_node): func_node = call_node.func if isinstance(func_node, ast.Name) and func_node.id == "isinstance": # original code was: # assert isinstance(obj, cls_or_tuple) # # generated code is: # # @contexts_assertion_var1 = obj # @contexts_assertion_var2 = cls_or_tuple # @contexts_assertion_var3 = obj.__class__ # @contexts_assertion_var4 = (tuple(@x.__name__ for @x in @contexts_assertion_var2) # if isinstance(@contexts_assertion_var2, tuple) # else @contexts_assertion_var2.__name__) # assert isinstance(@contexts_assertion_var1, @contexts_assertion_var2), 'Asserted isinstance({0}, {1}) but found it to be a {2}'.format(@contexts_assertion_var1, repr(@contexts_assertion_var4).replace("'", ""), @contexts_assertion_var3) if sys.version_info < (3, 6): tupleAstArgs = ast.comprehension( ast.Name('@x', ast.Store()), self.load('@contexts_assertion_var2'), []) else: tupleAstArgs = ast.comprehension( ast.Name('@x', ast.Store()), self.load('@contexts_assertion_var2'), [], False) return [ self.assign('@contexts_assertion_var1', call_node.args[0]), self.assign('@contexts_assertion_var2', call_node.args[1]), self.assign( '@contexts_assertion_var3', self.clsname( self.getattr(self.load('@contexts_assertion_var1'), '__class__'))), self.assign( '@contexts_assertion_var4', ast.IfExp( ast.Call(func=self.load('isinstance'), args=[ self.load('@contexts_assertion_var2'), self.load('tuple'), ], keywords=[]), ast.Call(func=self.load('tuple'), args=[ ast.GeneratorExp( self.clsname(self.load('@x')), [ tupleAstArgs, ]), ], keywords=[]), self.clsname(self.load('@contexts_assertion_var2')))), ast.Assert( ast.Call(func=ast.Name(id='isinstance', ctx=ast.Load()), args=[ self.load('@contexts_assertion_var1'), self.load('@contexts_assertion_var2'), ], keywords=[]), self.format( 'Asserted isinstance({0}, {1}) but found it to be a {2}', [ self.repr(self.load('@contexts_assertion_var1')), ast.Call(func=self.getattr( self.repr( self.load('@contexts_assertion_var4')), 'replace'), args=[ast.Str("'"), ast.Str("")], keywords=[]), self.load('@contexts_assertion_var3'), ])) ] if isinstance(func_node, ast.Name) and func_node.id == "all": # original code was: # # assert all(iterable) # # generated code is: # # @contexts_assertion_var1 = iterable # for @contexts_assertion_var_ix, @contexts_assertion_var_elem in enumerate(@contexts_assertion_var1): # assert x, "Not all elements of {} were truthy. First falsy element: {} at position {}".format(@contexts_assertion_var1, @contexts_assertion_var_ix, @contexts_assertion_var_elem) return [ self.assign('@contexts_assertion_var1', call_node.args[0]), ast.For( ast.Tuple([ ast.Name("@contexts_assertion_var_ix", ast.Store()), ast.Name("@contexts_assertion_var_elem", ast.Store()) ], ast.Store()), ast.Call(func=self.load("enumerate"), args=[self.load('@contexts_assertion_var1')], keywords=[]), [ ast.Assert( self.load('@contexts_assertion_var_elem'), self.format( "Not all elements of {0} were truthy. First falsy element: {1} at position {2}", [ self.repr( self.load('@contexts_assertion_var1')), self.repr( self.load( '@contexts_assertion_var_elem')), self.load('@contexts_assertion_var_ix'), ])) ], []) ]
def helper(self, name, *args): """Call a helper in this module.""" py_name = ast.Name("@pytest_ar", ast.Load()) attr = ast.Attribute(py_name, "_" + name, ast.Load()) return ast.Call(attr, list(args), [], None, None)
def _shape_as_tuple__scalar(_: CContent) -> CInitializer: return Expression(ast.Tuple([], ast.Load()))