def test_return_value_is_filled_dict_by_keyword(): # when method return dict(a='b') try: assert ReturnedExpression( _ast.Return( value=_ast.Call( func=_ast.Name(id='dict', ctx=_ast.Load()), args=[], keywords=[_ast.keyword(arg='a', value=_ast.Str(s='b'))], ), lineno=1, ), ).value_not_none() is True except (AttributeError): assert ReturnedExpression( _ast.Return( value=_ast.Call( func=_ast.Name(id='dict', ctx=_ast.Load()), args=[], keywords=[ _ast.keyword(arg='a', value=_ast.JoinedStr(values=['a', 'b'])) ], ), lineno=1, ), ).value_not_none() is True
class ResultReturnValueFixture: none = FunctionParseResult( return_not_none=bool(FunctionLint.EMPTY_RETURNED_VALUE), line_number=-1, ).__dict__ wrong = FunctionParseResult( return_not_none=bool(FunctionLint.EMPTY_RETURNED_VALUE), line_number=1, ).__dict__ success = FunctionParseResult( return_not_none=ReturnedExpression(_ast.Return( lineno=1, value=None)).value_not_none(), line_number=_ast.Return(lineno=1, value=None).lineno, ).__dict__
def queue_scope(self, node, state, parent_scope): assert (node in self.cfgs) == (node in self.scopes) if node in self.cfgs: assert state == self.input_states[(node, self.first_block( self.cfgs[node]))] else: if isinstance(node, _ast.FunctionDef): if ast_utils.has_yields(node): body = node.body else: body = node.body + [ _ast.Return(_ast.Name( "None", _ast.Load(), not_real=True), not_real=True) ] self.scopes[node] = FunctionScope(parent_scope) elif isinstance(node, _ast.Lambda): body = [ _ast.Return(node.body, lineno=node.lineno, col_offset=node.col_offset, not_real=True) ] self.scopes[node] = FunctionScope(parent_scope) elif isinstance(node, _ast.Module): body = node.body assert parent_scope is None self.scopes[node] = ModuleScope() elif isinstance(node, _ast.ClassDef): body = node.body self.scopes[node] = ClassScope(parent_scope) else: raise Exception(node) cfg = cfa(node, body) # cfg.show() self.cfgs[node] = cfg self.input_states[(node, self.first_block(cfg))] = state self.mark_changed((node, self.first_block(cfg))) if isinstance(node, (_ast.FunctionDef, _ast.ClassDef)): scope = self.scopes[node] for n in ast_utils.find_global_vars(node): scope._set_global(n) return self.scopes[node]
def test_return_value_is_empty_string(): # when method return '' try: assert ReturnedExpression(_ast.Return( value=_ast.Str(s=''), lineno=1)).value_not_none() is False except (AttributeError): pass
def test_return_value_is_filled_string(): # when method return 'test' try: assert ReturnedExpression( _ast.Return(value=_ast.Str(s='test'), lineno=1)).value_not_none() is True except (AttributeError): pass
def test_return_value_is_class_constant(): # when method return SomeClass.CONSTANT assert ReturnedExpression( _ast.Return( value=_ast.Attribute(value=_ast.Name(id='SomeClass', ctx=_ast.Load()), attr='CONSTANT', ctx=_ast.Load()), lineno=1, ), ).value_not_none() is True
def test_return_value_is_empty_frozenset_by_keyword(): # when method return frozenset() assert ReturnedExpression( _ast.Return( value=_ast.Call( func=_ast.Name(id='frozenset', ctx=_ast.Load()), args=[], keywords=[], ), lineno=1, ), ).value_not_none() is False
def make_function(code, defaults=None, lineno=0): from meta.decompiler.disassemble import disassemble instructions = Instructions(disassemble(code)) stmnts = instructions.stmnt() if code.co_flags & 2: vararg = None kwarg = None varnames = list(code.co_varnames[:code.co_argcount]) co_locals = list(code.co_varnames[code.co_argcount:]) #have var args if code.co_flags & 4: vararg = co_locals.pop(0) #have kw args if code.co_flags & 8: kwarg = co_locals.pop() args = [_ast.Name(id=argname, ctx=_ast.Param(), lineno=lineno, col_offset=0) for argname in varnames] args = _ast.arguments(args=args, defaults=defaults if defaults else [], kwarg=kwarg, vararg=vararg, lineno=lineno, col_offset=0 ) if code.co_name == '<lambda>': if len(stmnts) == 2: if isinstance(stmnts[0], _ast.If) and isinstance(stmnts[1], _ast.Return): assert len(stmnts[0].body) == 1 assert isinstance(stmnts[0].body[0], _ast.Return) stmnts = [_ast.Return(_ast.IfExp(stmnts[0].test, stmnts[0].body[0].value, stmnts[1].value))] assert len(stmnts) == 1, stmnts assert isinstance(stmnts[0], _ast.Return) stmnt = stmnts[0].value ast_obj = _ast.Lambda(args=args, body=stmnt, lineno=lineno, col_offset=0) else: if instructions.seen_yield: return_ = stmnts[-1] assert isinstance(return_, _ast.Return) assert isinstance(return_.value, _ast.Name) assert return_.value.id == 'None' return_.value = None ast_obj = _ast.FunctionDef(name=code.co_name, args=args, body=stmnts, decorator_list=[], lineno=lineno, col_offset=0) return ast_obj
def test_return_value_is_filled_frozenset_by_keyword(): # when method return frozenset('1') try: assert ReturnedExpression( _ast.Return( value=_ast.Call( func=_ast.Name(id='frozenset', ctx=_ast.Load()), args=[_ast.Str(s='1')], keywords=[], ), lineno=1, ), ).value_not_none() is True except (AttributeError): assert ReturnedExpression( _ast.Return( value=_ast.Call( func=_ast.Name(id='frozenset', ctx=_ast.Load()), args=[_ast.JoinedStr(values=['1'])], keywords=[], ), lineno=1, ), ).value_not_none() is True
def test_return_value_is_func(): assert ReturnedExpression( _ast.Return( value=_ast.Call( func=_ast.Attribute( value=_ast.Name(id='Function', ctx=_ast.Load()), attr='staticm', ctx=_ast.Load(), ), args=[], keywords=[], ), lineno=1, ), ).value_not_none() is True
def visit_Lambda(self, node): """Rewrite the Lambda visitor function to transform the lambda into a real iterator function. """ iden = self._gen_iden(node) funcnode = _ast.FunctionDef(name=iden, args=node.args, body=[_ast.Return(value=node.body)], decorator_list=[]) self.visit(funcnode) return iden
class ReturnedValueFixture: node_is_none = None assign_expression_as_input = _ast.Assign(lineno=1) pass_expression_as_input = _ast.Pass(lineno=1) plain_expression_as_input = _ast.Expr(lineno=1) function_body_is_empty = _ast.FunctionDef(lineno=1, body=[]) function_body_without_return_expression = _ast.FunctionDef( lineno=1, body=[_ast.Pass(), _ast.Expr(), _ast.Assign], ) function_body_with_return_expression = _ast.FunctionDef( lineno=1, body=[ _ast.Pass(), _ast.Expr(), _ast.Assign(), _ast.Return(lineno=1, value=None) ], )
def return_stmt(value: _ast.expr) -> _ast.Return: return _ast.Return(value=value)
def test_return_value_is_filled_joined_string(): # when method return '{}{}{}'.format('a', 'b', 'c') assert ReturnedExpression( _ast.Return(value=_ast.JoinedStr(values=['a', 'b', 'c']), lineno=1)).value_not_none() is True
def test_return_value_is_empty_joined_string(): # when method return '' assert ReturnedExpression( _ast.Return(value=_ast.JoinedStr(values=[]), lineno=1)).value_not_none() is False
def RETURN_VALUE(self, instr): value = self.pop_ast_item() value = self.process_ifexpr(value) ret = _ast.Return(value=value, lineno=instr.lineno, col_offset=0) self.push_ast_item(ret)
def Return(value): return _ast.Return(value=value)
def test_return_value_is_float_limit_to_zero(): # when method return 0.0000000000000000000000001 assert ReturnedExpression( _ast.Return(value=_ast.Num(n=0.0000000000000000000000001), lineno=1), ).value_not_none() is True
def test_return_value_is_filled_tuple(): # when method return ('1') assert ReturnedExpression( _ast.Return(value=_ast.Tuple(elts=['1'], ctx=_ast.Load()), lineno=1), ).value_not_none() is True
def RETURN_VALUE(self, instr): value = self.ast_stack.pop() value = self.process_ifexpr(value) ret = _ast.Return(value=value, lineno=instr.lineno, col_offset=0) self.ast_stack.append(ret)
def test_return_value_is_int_zero(): # when method return 0 assert ReturnedExpression(_ast.Return(value=_ast.Num(n=0), lineno=1)).value_not_none() is True
def test_return_value_is_none(): # when method return None assert ReturnedExpression( _ast.Return(value=_ast.NameConstant(value=None), lineno=1)).value_not_none() is False
def return_expr(self, items): (items, ) = items return _ast.Return(value=items)
def test_return_value_is_empty_dict(): # when method return {} assert ReturnedExpression( _ast.Return(value=_ast.Dict(keys=[], values=[]), lineno=1), ).value_not_none() is False
def make_function(code, defaults=None, annotations=(), kw_defaults=(), lineno=0): from ..decompiler.disassemble import disassemble instructions = Instructions(disassemble(code)) stmnts = instructions.stmnt() if code.co_flags & 2: vararg = None kwarg = None varnames = list(code.co_varnames[:code.co_argcount]) kwonly_varnames = list(code.co_varnames[code.co_argcount:code.co_argcount + code.co_kwonlyargcount]) co_locals = list(code.co_varnames[code.co_argcount + code.co_kwonlyargcount:]) assert (len(kw_defaults) % 2) == 0 kw_defaults = list(kw_defaults) kw_default_dict = {} while kw_defaults: name = kw_defaults.pop(0) value = kw_defaults.pop(0) kw_default_dict[name.s] = value kw_defaults = [] for argname in kwonly_varnames: kw_defaults.append(kw_default_dict.pop(argname)) #have var args if code.co_flags & 4: vararg = co_locals.pop(0) #have kw args if code.co_flags & 8: kwarg = co_locals.pop() args = [] annotation_names = [annotation.arg for annotation in annotations] for argname in varnames: if argname in annotation_names: arg = [ annotation for annotation in annotations if annotation.arg == argname ][0] else: arg = _ast.arg(annotation=None, arg=argname, lineno=lineno, col_offset=0) #@UndefinedVariable args.append(arg) kwonlyargs = [] for argname in kwonly_varnames: if argname in annotation_names: arg = [ annotation for annotation in annotations if annotation.arg == argname ][0] else: arg = _ast.arg(annotation=None, arg=argname, lineno=lineno, col_offset=0) #@UndefinedVariable kwonlyargs.append(arg) if 'return' in annotation_names: arg = [ annotation for annotation in annotations if annotation.arg == 'return' ][0] returns = arg.annotation else: returns = None if vararg in annotation_names: arg = [ annotation for annotation in annotations if annotation.arg == vararg ][0] varargannotation = arg.annotation else: varargannotation = None if kwarg in annotation_names: arg = [ annotation for annotation in annotations if annotation.arg == kwarg ][0] kwargannotation = arg.annotation else: kwargannotation = None args = _ast.arguments(args=args, defaults=defaults if defaults else [], kwarg=kwarg, vararg=vararg, kw_defaults=kw_defaults, kwonlyargs=kwonlyargs, kwargannotation=kwargannotation, varargannotation=varargannotation, lineno=lineno, col_offset=0) if code.co_name == '<lambda>': if len(stmnts) == 2: if isinstance(stmnts[0], _ast.If) and isinstance( stmnts[1], _ast.Return): assert len(stmnts[0].body) == 1 assert isinstance(stmnts[0].body[0], _ast.Return) stmnts = [ _ast.Return( _ast.IfExp(stmnts[0].test, stmnts[0].body[0].value, stmnts[1].value)) ] assert isinstance(stmnts[0], _ast.Return) stmnt = stmnts[0].value ast_obj = _ast.Lambda(args=args, body=stmnt, lineno=lineno, col_offset=0) else: if instructions.seen_yield: return_ = stmnts[-1] assert isinstance(return_, _ast.Return) assert isinstance(return_.value, _ast.Name) assert return_.value.id == 'None' return_.value = None ast_obj = _ast.FunctionDef(name=code.co_name, args=args, body=stmnts, decorator_list=[], returns=returns, lineno=lineno, col_offset=0) return ast_obj
def test_return_is_empty(): # when method return nothing, not None, only 'return' assert ReturnedExpression(_ast.Return( value=None, lineno=1, ), ).value_not_none() is False
def test_return_value_is_filled_dict(): # when method return {'1': '2'} assert ReturnedExpression( _ast.Return(value=_ast.Dict(keys=['1'], values=['2']), lineno=1), ).value_not_none() is True
def test_return_value_is_empty_tuple(): # when method return () assert ReturnedExpression( _ast.Return(value=_ast.Tuple(elts=[], ctx=_ast.Load()), lineno=1), ).value_not_none() is False