class TestWarnings(InferTestCase): #{{{ def setUp(self): self.parser = Parser() self.num_class = self.parser.extern_scope['num'] self.str_class = self.parser.extern_scope['str'] def test_nonexistent_attribute(self): code = makecode(""" |class A: | def __init__(self, x, y): | self.x = x | self.y = y | |a = A(3,4) |a.x = a.z |a.z = a.x |a.y = a.z |a.w = a.w """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) problem_symbols = {problem.symbol for problem in self.parser.problems} self.assertEqual(problem_symbols, {'w', 'z'}) def test_nonexistent_function(self): code = makecode(""" |class A: | def __init__(self, x, y): | self.x = x | self.y = y | | def fun1(self): | return self.x+self.y | |a = A(3,4) |a.z = a.fun1() |a.gun1() |a.fun2 = a.fun1 |a.fun2() |# since the problem with nonexistent gun1 is already reported, gun1 and gun2 are to be considered as |# any_type making all invocations and other manipulations with it legal |a.gun2 = a.gun1 |a.gun2() |a.gun3() """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) #problem_symbols = {problem.symbol for problem in self.parser.problems} #self.assertEqual(problem_symbols, {'gun1', 'gun3'}) def test_nonexistent_class(self): code = makecode(""" |class A: | def __init__(self, x, y): | self.x = x | self.y = y | |class B: | pass | |a = A(1,2) |b = B() |c = C() |a = D() """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) problem_symbols = {problem.symbol for problem in self.parser.problems} self.assertEqual(problem_symbols, {'C', 'D'})
class TestInfer(InferTestCase): #{{{ def setUp(self): self.parser = Parser() self.num_class = self.parser.extern_scope['num'] self.str_class = self.parser.extern_scope['str'] def test_simple_parse(self): code = makecode(""" |x = 3 |a = 'ahoj' |y = 6 |z = 3 + x |zz = x + y |b = 'jozo' |c = a + b |x = 'mumly' """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope x = module_scope.resolve('x') y = module_scope.resolve('y') z = module_scope.resolve('z') zz = module_scope.resolve('zz') a = module_scope.resolve('a') b = module_scope.resolve('b') c = module_scope.resolve('c') self.assertIsStr(x) self.assertIsNum(y) self.assertIsNum(z) self.assertIsNum(zz) self.assertIsStr(a) self.assertIsStr(b) self.assertIsStr(c) def test_fun_parse(self): code = makecode(""" |def mean(x,y): | return (x+y)/2 |def gean(x,y): | return x+y |x = 3 |y = x+2 |z = mean(x,y) |x = "jozo" |zz = gean(x,"fero") """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope x = module_scope.resolve('x') y = module_scope.resolve('y') z = module_scope.resolve('z') zz = module_scope.resolve('zz') self.assertIsStr(x) self.assertIsNum(y) self.assertIsNum(z) self.assertIsStr(zz) def test_default_object(self): code = makecode(""" |class A(): | pass |a = A() """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope a = module_scope.resolve('a') __setattr__ = a.resolve('__setattr__', 'straight') self.assertEqual(__setattr__, None) __setattr__ = a.resolve('__setattr__', mode = 'class') self.assertEqual(__setattr__.node.name, '__setattr__') def test_closure(self): code = makecode(""" |def f(x): | z = x | def g(y): | return(x+y) | return g |g1 = f(3) |g2 = f('jozo') |a = g1(4) |b = g2('fero') """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope a = module_scope.resolve('a') b = module_scope.resolve('b') self.assertIsNum(a) self.assertIsStr(b) def test_class(self): code = makecode(""" |class A: | def __init__(self, x, y, z): | self.x = x | self.y = y | w = 'johnie' | |a = A(3,"ahoj", "svet") """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope a = module_scope.resolve('a') self.assert_no_problem(); self.assertIsNum(a.scope['x']) self.assertIsStr(a.scope['y']) self.assertNotIn('w', a.scope) self.assertNotIn('z', a.scope) self.assertEqual(a.scope.resolve('z'),None) def test_override_setattr(self): code = makecode(""" |class A: | def __init__(self, x, y): | pass | | def __setattr__(self, attr, val): | object.__setattr__(self, attr, 4) | | |a = A(3,4) |a.x = 'jozo' |key = 'z' |object.__setattr__(a,key,'jozo') """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope a = module_scope.resolve('a') self.assert_no_problem(); self.assertIsNum(a.scope['x']) self.assertIsStr(a.scope['z']) def test_method_lookup(self): code = makecode(""" |class A: | def __init__(self, x): | self.x = x | def get_x(self): | return self.x |a = A('jozo') |b = a.get_x() |a = A(3) |c = a.get_x() """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope self.assert_no_problem(); a = module_scope.resolve('a') A = module_scope.resolve('A') self.assertNotIn('get_x', a.scope) self.assertIn('get_x', A.scope) b = module_scope.resolve('b') c = module_scope.resolve('c') self.assertIsStr(b) self.assertIsNum(c) def test_method_manipulation(self): code = makecode(""" |class A: | def __init__(self, x, y): | self.x = x | self.y = y | | def fun1(self): | return self.x+self.y | | |a = A(3,4) |a.fun1() |fun2 = a.fun1 |a.fun3 = a.fun1 |z2 = fun2() |z3 = a.fun3() """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope z2 = module_scope.resolve('z2') self.assertIsNum(z2) z3 = module_scope.resolve('z3') self.assertIsNum(z3) def test_class_closure(self): code = makecode(""" |class A: | def __init__(self, x): | self.x = x | def get_x(self): | return self.x |a = A('jozo') |getx = a.get_x |getx_class1 = A.get_x |getx_class2 = A.get_x |x1 = getx() |x2 = getx_class1() |x3 = getx_class2(a) """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope self.assertEqual(1, len(self.parser.problems)) self.assertEqual('getx_class1', self.parser.problems[0].symbol) x1 = module_scope.resolve('x1') x3 = module_scope.resolve('x3') self.assertIsStr(x1) self.assertIsStr(x3) def test_inheritance(self): code = makecode(""" |class A: | def __init__(self): | pass | | def get_x(self): | return self.x |class B(A): | def __init__(self): | pass | | def get_y(self): | return self.y |b = B() |b.x = 'jozo' |b.y = 4 """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope self.assertEqual(len(self.parser.problems), 0) b = module_scope.resolve('b') self.assertIsNum(b.scope['y']) self.assertIsStr(b.scope['x']) self.assertEqual(b.resolve('get_x', 'class').kind, 'func') def test_function_return(self): code = makecode(""" |def g(): | return "ahoj" | | |def f(): | x=1 | y=2 | g() | return x+y; | |z = f() """) node = ast.parse(code, mode = 'exec') self.parser.eval_in_root(node) module_scope = self.parser.root_scope self.assertEqual(len(self.parser.problems), 0) z = module_scope.resolve('z') self.assertIsNum(z)