def __build_unconditional_arg_check(self, argname, argtype): presence_check = ast.Call( func=ast.Name(id='isinstance', ctx=ast.Load()), args=[ast.Name(id=argname, ctx=ast.Load()), argtype], keywords=[], lineno=self.__get_line()) types = [t.id for t in argtype.elts] check_message = ast.BinOp(left=ast.Str( s='Argument \'{}\' must be of type \'{}\'. Received type: \'%s\''. format(argname, types)), op=ast.Mod(), right=ast.Call(func=ast.Name(id='type', ctx=ast.Load()), args=[ ast.Name(id=argname, ctx=ast.Load()) ], keywords=[]), lineno=self.__get_line()) new_ret = ast.Assert(test=presence_check, msg=check_message, lineno=self.__get_line()) return new_ret
def visit_FunctionDef(self, node): if len(preconditions[node.name]) == 0: return node ast_name = ast.Name(id="PreconditionException", ctx=ast.Load()) node_exception = ast.Raise(exc=ast_name, cause=None) precondition_node = preconditions[node.name][0] assert_node = ast.Assert(precondition_node, lineno=node.lineno, col_offset=node.col_offset, end_lineno=node.lineno, end_col_offset=node.end_col_offset) ast_exception = ast.Name(id="Exception", ctx=ast.Load()) handler = ast.ExceptHandler(type=ast_exception, name=None, body=[node_exception]) try_node = ast.Try(body=[assert_node], handlers=[handler], orelse=[], finalbody=[node.body]) #if_node = ast.If(precondition_node,[node.body],[node_exception]) node_res = ast.FunctionDef(node.name, node.args, [try_node], node.decorator_list, node.returns, node.type_comment, lineno=node.lineno, col_offset=node.col_offset, end_lineno=node.lineno, end_col_offset=node.end_col_offset) ast.fix_missing_locations(node_res) return node_res
def _create_float_delta_assert(self, var: vr.VariableReference, value: Any) -> ast.Assert: self._common_modules.add("math") # TODO(fk) maybe use something more specific for pytest or UnitTest? return ast.Assert( test=ast.Call( func=ast.Attribute( value=ast.Name(id="math", ctx=ast.Load()), attr="isclose", ctx=ast.Load(), ), args=[ au.create_var_name(self._variable_names, var, load=True), ast.Constant(value=value, kind=None), ], keywords=[ ast.keyword( arg="abs_tol", value=ast.Constant( value=config.configuration.float_precision, kind=None), ) ], ), msg=None, )
def visit_unknown_node(self, node): format_string = "Asserted {} but found it to be falsy" name = '@contexts_assertion_var' statements = [self.assign(name, node)] msg = self.format(format_string, [self.repr(self.load(name))]) statements.append(ast.Assert(self.load(name), msg)) return statements
def visit_match(self, match: Expr): """For matches, we wrap the entire expression in a thunk because it is easiest to implement them using if statements. For each clause, we generate a function that checks if the pattern matches. If yes, we call a function that assigns the variables appropriately and invokes the clause body.""" data, defs = self.visit(match.data) data_var = self.generate_var_name("_match_data") # must ensure the data clause is executed exactly once thunk_body = [Assign([Name(data_var, Store())], data)] for clause in match.clauses: check_expr = self.create_match_check(clause.lhs, Name(data_var, Load())) body_def, body_name = self.create_match_clause_body( clause.lhs, clause.rhs) defs.append(body_def) # equiv: if check(data): return body(data) thunk_body.append( ast.If(check_expr, [ Return( self.create_call(body_name, [Name(data_var, Load())])) ], [])) # finally if nothing matches we have a failed assert (should never happen) thunk_body.append( ast.Assert(NameConstant(False), Str("Match was not exhaustive"))) thunk_name = self.generate_function_name("_match_thunk") thunk_def = self.create_def(thunk_name, [], defs + thunk_body) return (self.create_call(thunk_name, []), [thunk_def])
def compile_assert_expression(self, expr): expr.pop(0) # assert e = expr.pop(0) return ast.Assert(test=self.compile(e), msg=None, lineno=e.start_line, col_offset=e.start_column)
def __build_unconditional_arg_check(self, argname, argtype): # checker_str = "assert isinstance({argname}, {typetuple}), \"Argument {argname} must be of type {typetuple}. Received type: %s\" % type({argname})".format( # argname = argname, # typetuple = argtype, # ) # checker = ast.parse(checker_str) # old_ret = checker.body.pop() presence_check = ast.Call(func = ast.Name(id='isinstance', ctx=ast.Load()), args = [ast.Name(id=argname, ctx=ast.Load()), argtype], keywords = [], lineno = self.__get_line()) check_message = ast.BinOp( left = ast.Str(s='Argument {} must be of type ({}). Received type: %s'.format(argname, argtype)), op = ast.Mod(), right = ast.Call(func=ast.Name(id='type', ctx=ast.Load()), args=[ast.Name(id=argname, ctx=ast.Load())], keywords=[]), lineno = self.__get_line()) new_ret = ast.Assert( test = presence_check, msg = check_message, lineno = self.__get_line()) return new_ret
def visit_Assert(self, node: Assert, *args, **kwargs) -> C.Assert: test = self.visit(node.test, *args, **kwargs) msg = self.visit(node.msg, *args, **kwargs) return C.Assert( test=test, msg=msg, )
def visit_UnaryOp(self, unaryop_node): if isinstance(unaryop_node.op, ast.Not): format_string = "Asserted not {} but found it to be truthy" name = '@contexts_assertion_var' statements = [self.assign(name, unaryop_node.operand)] msg = self.format(format_string, [self.repr(self.load(name))]) statements.append(ast.Assert(ast.UnaryOp(ast.Not(), self.load(name)), msg)) return statements
def visit_Assert(self, asr: ast.Assert) -> ActionsT: test, test_actions = self.visit_expr(asr.test) msg_actions: ActionsT if asr.msg is None: msg, msg_actions = None, [] else: msg, msg_actions = self.visit_expr(asr.msg) result_node = ast.Assert(test=test, msg=msg) return test_actions + msg_actions + [result_node]
def _create_constant_assert(self, var: vr.VariableReference, operator: ast.cmpop, value: Any) -> ast.Assert: return ast.Assert( test=ast.Compare( left=au.create_var_name(self._variable_names, var, load=True), ops=[operator], comparators=[ast.Constant(value=value, kind=None)], ), msg=None, )
def test_attributes(self): # assert True, "bad" assert0 = ast.Assert() self.assertFalse(hasattr(assert0, 'lineno')) self.assertFalse(hasattr(assert0, 'col_offset')) assert1 = ast.Assert(ast.Name('True', ast.Load()), ast.Str('bad')) self.assertFalse(hasattr(assert1, 'lineno')) self.assertFalse(hasattr(assert1, 'col_offset')) try: tmp=assert1.lineno except Exception as e: self.assertTrue(isinstance(e,AttributeError)) try: tmp=assert1.col_offset except Exception as e: self.assertTrue(isinstance(e,AttributeError)) assert2 = ast.Assert(ast.Name('True', ast.Load()), ast.Str('bad'),2,3) self.assertEqual(assert2.lineno,2) self.assertEqual(assert2.col_offset,3)
def assertions_builder(call: ast_mod.Attribute, ops: list, comperators: list): """ Args: call: rhs of the assertions, item to check ops: operation to check comperators: values to check in the lhs Return: assert ast node """ return ast_mod.Assert(test=ast_mod.Compare(left=call, ops=ops, comparators=comperators), msg=None)
def visit_BoolOp(self, boolop_node): statements = [] format_params = [] new_comparators = [] for i, comparator in enumerate(boolop_node.values): name = '@contexts_assertion_var' + str(i) statements.append(self.assign(name, comparator)) new_comparators.append(self.load(name)) format_params.append(self.repr(self.load(name))) if isinstance(boolop_node.op, ast.And): format_string = "Asserted " + (" and ".join("{}" for _ in format_params)) + " but found one to be falsy" msg = self.format(format_string, format_params) elif isinstance(boolop_node.op, ast.Or): format_string = "Asserted " + (" or ".join("{}" for _ in format_params)) + " but found them all to be falsy" msg = self.format(format_string, format_params) statements.append(ast.Assert(ast.BoolOp(boolop_node.op, new_comparators), msg)) return statements
def _visit_all(self, call): """Special rewrite for the builtin all function, see #5062""" gen_exp = call.args[0] assertion_module = ast.Module(body=[ ast.Assert(test=gen_exp.elt, lineno=1, msg="", col_offset=1) ]) AssertionRewriter(module_path=None, config=None).run(assertion_module) for_loop = ast.For( iter=gen_exp.generators[0].iter, target=gen_exp.generators[0].target, body=assertion_module.body, orelse=[], ) self.statements.append(for_loop) return ( ast.Num(n=1), "", ) # Return an empty expression, all the asserts are in the for_loop
def __build_conditional_arg_check(self, argname, argtype): target_value = ast.Subscript(value=ast.Name(id='kwargs', ctx=ast.Load()), slice=ast.Index(ast.Str(s=argname)), ctx=ast.Load()) presence_check = ast.Call(func=ast.Name(id='isinstance', ctx=ast.Load()), args=[target_value, argtype], keywords=[], lineno=self.__get_line()) # Assumes that argtype is a ast.Tuple of ast.Name items types = [t.id for t in argtype.elts] check_message = ast.BinOp(left=ast.Str( s='Optional argument \'{}\' must be of type \'{}\'. Received type: \'%s\'' .format(argname, types)), op=ast.Mod(), right=ast.Call(func=ast.Name(id='type', ctx=ast.Load()), args=[target_value], keywords=[]), lineno=self.__get_line()) assert_check = ast.Assert(test=presence_check, msg=check_message, lineno=self.__get_line()) check_body = [assert_check] check = ast.Compare( left=ast.Str(s=argname, ctx=ast.Load()), ops=[ast.In()], comparators=[ast.Name(id='kwargs', ctx=ast.Load())]) new_ret = ast.If(test=check, body=check_body, orelse=[], lineno=self.__get_line()) return new_ret
def visit_Compare(self, compare_node): if len(compare_node.comparators) > 1: return format_string = self.formatstring_for_comparison(compare_node) if format_string is None: return statements = [] format_params = [] new_comparators = [] for i, comparator in enumerate([compare_node.left] + compare_node.comparators): name = '@contexts_assertion_var' + str(i) statements.append(self.assign(name, comparator)) new_comparators.append(self.load(name)) format_params.append(self.repr(self.load(name))) name = '@contexts_formatparam' if isinstance(compare_node.ops[0], ast.Lt): ternary_expression = ast.IfExp( ast.Compare(new_comparators[0], [ast.Gt()], [new_comparators[1]]), ast.Str('it to be greater'), ast.Str('them to be equal') ) elif isinstance(compare_node.ops[0], ast.Gt): ternary_expression = ast.IfExp( ast.Compare(new_comparators[0], [ast.Lt()], [new_comparators[1]]), ast.Str('it to be less'), ast.Str('them to be equal') ) if isinstance(compare_node.ops[0], (ast.Lt, ast.Gt)): statements.append(self.assign(name, ternary_expression)) format_params.append(self.load(name)) compare_node.left, *compare_node.comparators = new_comparators msg = self.format(format_string, format_params) statements.append(ast.Assert(compare_node, msg)) return statements
def _create_float_delta_assert( self, var: vr.VariableReference, value: Any ) -> ast.Assert: self._common_modules.add("pytest") return ast.Assert( test=ast.Compare( left=au.create_var_name(self._variable_names, var, load=True), ops=[ast.Eq()], comparators=[ ast.Call( func=ast.Attribute( value=ast.Name(id="pytest", ctx=ast.Load()), attr="approx", ctx=ast.Load(), ), args=[ ast.Constant(value=value, kind=None), ], keywords=[ ast.keyword( arg="abs", value=ast.Constant( value=config.configuration.float_precision, kind=None, ), ), ast.keyword( arg="rel", value=ast.Constant( value=config.configuration.float_precision, kind=None, ), ), ], ), ], ), msg=None, )
def test_assert(self): self.stmt(ast.Assert(ast.Name("x", ast.Store()), None), "must have Load context") assrt = ast.Assert(ast.Name("x", ast.Load()), ast.Name("y", ast.Store())) self.stmt(assrt, "must have Load context")
def p_verify(self, p): '''expr : VERIFY expr''' p[0] = ast.Assert(test=p[2], msg=None)
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): # 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 or 3.6. 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 r_Assert(test, msg): return ast.Assert(test=test, msg=(None if msg == [] else reconstruct(msg)), ctx=None)
def make_assert(): """Assert(expr test, expr? msg)""" return ast.Assert(test=ast.Name(id="test", ctx=ast.Load()), msg=None)
def p_assert_statement(self, p): """ assert_statement : ASSERT expr SEMI """ p[0] = ast.Assert(p[2], coord=self._token_coord(p, 1))