# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
# contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
#
# This file is part of astroid.
#
# astroid is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 2.1 of the License, or (at your
# option) any later version.
#
# astroid is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
# for more details.
#
# You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see .
"""tests for the astroid inference capabilities
"""
from os.path import join, dirname, abspath
import sys
from StringIO import StringIO
from logilab.common.testlib import TestCase, unittest_main, require_version
from astroid import InferenceError, builder, nodes
from astroid.inference import infer_end as inference_infer_end
from astroid.bases import YES, Instance, BoundMethod, UnboundMethod,\
path_wrapper, BUILTINS
def get_name_node(start_from, name, index=0):
return [n for n in start_from.nodes_of_class(nodes.Name) if n.name == name][index]
def get_node_of_class(start_from, klass):
return start_from.nodes_of_class(klass).next()
builder = builder.AstroidBuilder()
class InferenceUtilsTC(TestCase):
def test_path_wrapper(self):
def infer_default(self, *args):
raise InferenceError
infer_default = path_wrapper(infer_default)
infer_end = path_wrapper(inference_infer_end)
self.assertRaises(InferenceError,
infer_default(1).next)
self.assertEqual(infer_end(1).next(), 1)
if sys.version_info < (3, 0):
EXC_MODULE = 'exceptions'
else:
EXC_MODULE = BUILTINS
class InferenceTC(TestCase):
CODE = '''
class C(object):
"new style"
attr = 4
def meth1(self, arg1, optarg=0):
var = object()
print ("yo", arg1, optarg)
self.iattr = "hop"
return var
def meth2(self):
self.meth1(*self.meth3)
def meth3(self, d=attr):
b = self.attr
c = self.iattr
return b, c
ex = Exception("msg")
v = C().meth1(1)
m_unbound = C.meth1
m_bound = C().meth1
a, b, c = ex, 1, "bonjour"
[d, e, f] = [ex, 1.0, ("bonjour", v)]
g, h = f
i, (j, k) = "glup", f
a, b= b, a # Gasp !
'''
astroid = builder.string_build(CODE, __name__, __file__)
def test_module_inference(self):
infered = self.astroid.infer()
obj = infered.next()
self.assertEqual(obj.name, __name__)
self.assertEqual(obj.root().name, __name__)
self.assertRaises(StopIteration, infered.next)
def test_class_inference(self):
infered = self.astroid['C'].infer()
obj = infered.next()
self.assertEqual(obj.name, 'C')
self.assertEqual(obj.root().name, __name__)
self.assertRaises(StopIteration, infered.next)
def test_function_inference(self):
infered = self.astroid['C']['meth1'].infer()
obj = infered.next()
self.assertEqual(obj.name, 'meth1')
self.assertEqual(obj.root().name, __name__)
self.assertRaises(StopIteration, infered.next)
def test_builtin_name_inference(self):
infered = self.astroid['C']['meth1']['var'].infer()
var = infered.next()
self.assertEqual(var.name, 'object')
self.assertEqual(var.root().name, BUILTINS)
self.assertRaises(StopIteration, infered.next)
def test_tupleassign_name_inference(self):
infered = self.astroid['a'].infer()
exc = infered.next()
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, infered.next)
infered = self.astroid['b'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 1)
self.assertRaises(StopIteration, infered.next)
infered = self.astroid['c'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "bonjour")
self.assertRaises(StopIteration, infered.next)
def test_listassign_name_inference(self):
infered = self.astroid['d'].infer()
exc = infered.next()
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, infered.next)
infered = self.astroid['e'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 1.0)
self.assertRaises(StopIteration, infered.next)
infered = self.astroid['f'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Tuple)
self.assertRaises(StopIteration, infered.next)
def test_advanced_tupleassign_name_inference1(self):
infered = self.astroid['g'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "bonjour")
self.assertRaises(StopIteration, infered.next)
infered = self.astroid['h'].infer()
var = infered.next()
self.assertEqual(var.name, 'object')
self.assertEqual(var.root().name, BUILTINS)
self.assertRaises(StopIteration, infered.next)
def test_advanced_tupleassign_name_inference2(self):
infered = self.astroid['i'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, u"glup")
self.assertRaises(StopIteration, infered.next)
infered = self.astroid['j'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "bonjour")
self.assertRaises(StopIteration, infered.next)
infered = self.astroid['k'].infer()
var = infered.next()
self.assertEqual(var.name, 'object')
self.assertEqual(var.root().name, BUILTINS)
self.assertRaises(StopIteration, infered.next)
def test_swap_assign_inference(self):
infered = self.astroid.locals['a'][1].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 1)
self.assertRaises(StopIteration, infered.next)
infered = self.astroid.locals['b'][1].infer()
exc = infered.next()
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, infered.next)
def test_getattr_inference1(self):
infered = self.astroid['ex'].infer()
exc = infered.next()
self.assertIsInstance(exc, Instance)
self.assertEqual(exc.name, 'Exception')
self.assertEqual(exc.root().name, EXC_MODULE)
self.assertRaises(StopIteration, infered.next)
def test_getattr_inference2(self):
infered = get_node_of_class(self.astroid['C']['meth2'], nodes.Getattr).infer()
meth1 = infered.next()
self.assertEqual(meth1.name, 'meth1')
self.assertEqual(meth1.root().name, __name__)
self.assertRaises(StopIteration, infered.next)
def test_getattr_inference3(self):
infered = self.astroid['C']['meth3']['b'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, 4)
self.assertRaises(StopIteration, infered.next)
def test_getattr_inference4(self):
infered = self.astroid['C']['meth3']['c'].infer()
const = infered.next()
self.assertIsInstance(const, nodes.Const)
self.assertEqual(const.value, "hop")
self.assertRaises(StopIteration, infered.next)
def test_callfunc_inference(self):
infered = self.astroid['v'].infer()
meth1 = infered.next()
self.assertIsInstance(meth1, Instance)
self.assertEqual(meth1.name, 'object')
self.assertEqual(meth1.root().name, BUILTINS)
self.assertRaises(StopIteration, infered.next)
def test_unbound_method_inference(self):
infered = self.astroid['m_unbound'].infer()
meth1 = infered.next()
self.assertIsInstance(meth1, UnboundMethod)
self.assertEqual(meth1.name, 'meth1')
self.assertEqual(meth1.parent.frame().name, 'C')
self.assertRaises(StopIteration, infered.next)
def test_bound_method_inference(self):
infered = self.astroid['m_bound'].infer()
meth1 = infered.next()
self.assertIsInstance(meth1, BoundMethod)
self.assertEqual(meth1.name, 'meth1')
self.assertEqual(meth1.parent.frame().name, 'C')
self.assertRaises(StopIteration, infered.next)
def test_args_default_inference1(self):
optarg = get_name_node(self.astroid['C']['meth1'], 'optarg')
infered = optarg.infer()
obj1 = infered.next()
self.assertIsInstance(obj1, nodes.Const)
self.assertEqual(obj1.value, 0)
obj1 = infered.next()
self.assertIs(obj1, YES, obj1)
self.assertRaises(StopIteration, infered.next)
def test_args_default_inference2(self):
infered = self.astroid['C']['meth3'].ilookup('d')
obj1 = infered.next()
self.assertIsInstance(obj1, nodes.Const)
self.assertEqual(obj1.value, 4)
obj1 = infered.next()
self.assertIs(obj1, YES, obj1)
self.assertRaises(StopIteration, infered.next)
def test_inference_restrictions(self):
infered = get_name_node(self.astroid['C']['meth1'], 'arg1').infer()
obj1 = infered.next()
self.assertIs(obj1, YES, obj1)
self.assertRaises(StopIteration, infered.next)
def test_ancestors_inference(self):
code = '''
class A:
pass
class A(A):
pass
'''
astroid = builder.string_build(code, __name__, __file__)
a1 = astroid.locals['A'][0]
a2 = astroid.locals['A'][1]
a2_ancestors = list(a2.ancestors())
self.assertEqual(len(a2_ancestors), 1)
self.assertIs(a2_ancestors[0], a1)
def test_ancestors_inference2(self):
code = '''
class A:
pass
class B(A): pass
class A(B):
pass
'''
astroid = builder.string_build(code, __name__, __file__)
a1 = astroid.locals['A'][0]
a2 = astroid.locals['A'][1]
a2_ancestors = list(a2.ancestors())
self.assertEqual(len(a2_ancestors), 2)
self.assertIs(a2_ancestors[0], astroid.locals['B'][0])
self.assertIs(a2_ancestors[1], a1)
def test_f_arg_f(self):
code = '''
def f(f=1):
return f
a = f()
'''
astroid = builder.string_build(code, __name__, __file__)
a = astroid['a']
a_infered = a.infered()
self.assertEqual(a_infered[0].value, 1)
self.assertEqual(len(a_infered), 1)
def test_exc_ancestors(self):
code = '''
def f():
raise NotImplementedError
'''
astroid = builder.string_build(code, __name__, __file__)
error = astroid.nodes_of_class(nodes.Name).next()
nie = error.infered()[0]
self.assertIsInstance(nie, nodes.Class)
nie_ancestors = [c.name for c in nie.ancestors()]
if sys.version_info < (3, 0):
self.assertEqual(nie_ancestors, ['RuntimeError', 'StandardError', 'Exception', 'BaseException', 'object'])
else:
self.assertEqual(nie_ancestors, ['RuntimeError', 'Exception', 'BaseException', 'object'])
def test_except_inference(self):
code = '''
try:
print (hop)
except NameError, ex:
ex1 = ex
except Exception, ex:
ex2 = ex
raise
'''
if sys.version_info >= (3, 0):
code = code.replace(', ex:', ' as ex:')
astroid = builder.string_build(code, __name__, __file__)
ex1 = astroid['ex1']
ex1_infer = ex1.infer()
ex1 = ex1_infer.next()
self.assertIsInstance(ex1, Instance)
self.assertEqual(ex1.name, 'NameError')
self.assertRaises(StopIteration, ex1_infer.next)
ex2 = astroid['ex2']
ex2_infer = ex2.infer()
ex2 = ex2_infer.next()
self.assertIsInstance(ex2, Instance)
self.assertEqual(ex2.name, 'Exception')
self.assertRaises(StopIteration, ex2_infer.next)
def test_del1(self):
code = '''
del undefined_attr
'''
delete = builder.string_build(code, __name__, __file__).body[0]
self.assertRaises(InferenceError, delete.infer)
def test_del2(self):
code = '''
a = 1
b = a
del a
c = a
a = 2
d = a
'''
astroid = builder.string_build(code, __name__, __file__)
n = astroid['b']
n_infer = n.infer()
infered = n_infer.next()
self.assertIsInstance(infered, nodes.Const)
self.assertEqual(infered.value, 1)
self.assertRaises(StopIteration, n_infer.next)
n = astroid['c']
n_infer = n.infer()
self.assertRaises(InferenceError, n_infer.next)
n = astroid['d']
n_infer = n.infer()
infered = n_infer.next()
self.assertIsInstance(infered, nodes.Const)
self.assertEqual(infered.value, 2)
self.assertRaises(StopIteration, n_infer.next)
def test_builtin_types(self):
code = '''
l = [1]
t = (2,)
d = {}
s = ''
s2 = '_'
'''
astroid = builder.string_build(code, __name__, __file__)
n = astroid['l']
infered = n.infer().next()
self.assertIsInstance(infered, nodes.List)
self.assertIsInstance(infered, Instance)
self.assertEqual(infered.getitem(0).value, 1)
self.assertIsInstance(infered._proxied, nodes.Class)
self.assertEqual(infered._proxied.name, 'list')
self.assertIn('append', infered._proxied.locals)
n = astroid['t']
infered = n.infer().next()
self.assertIsInstance(infered, nodes.Tuple)
self.assertIsInstance(infered, Instance)
self.assertEqual(infered.getitem(0).value, 2)
self.assertIsInstance(infered._proxied, nodes.Class)
self.assertEqual(infered._proxied.name, 'tuple')
n = astroid['d']
infered = n.infer().next()
self.assertIsInstance(infered, nodes.Dict)
self.assertIsInstance(infered, Instance)
self.assertIsInstance(infered._proxied, nodes.Class)
self.assertEqual(infered._proxied.name, 'dict')
self.assertIn('get', infered._proxied.locals)
n = astroid['s']
infered = n.infer().next()
self.assertIsInstance(infered, nodes.Const)
self.assertIsInstance(infered, Instance)
self.assertEqual(infered.name, 'str')
self.assertIn('lower', infered._proxied.locals)
n = astroid['s2']
infered = n.infer().next()
self.assertEqual(infered.getitem(0).value, '_')
@require_version('2.7')
def test_builtin_types_py27(self):
code = 's = {1}'
astroid = builder.string_build(code, __name__, __file__)
n = astroid['s']
infered = n.infer().next()
self.assertIsInstance(infered, nodes.Set)
self.assertIsInstance(infered, Instance)
self.assertEqual(infered.name, 'set')
self.assertIn('remove', infered._proxied.locals)
def test_unicode_type(self):
if sys.version_info >= (3, 0):
self.skipTest('unicode removed on py >= 3.0')
code = '''u = u""'''
astroid = builder.string_build(code, __name__, __file__)
n = astroid['u']
infered = n.infer().next()
self.assertIsInstance(infered, nodes.Const)
self.assertIsInstance(infered, Instance)
self.assertEqual(infered.name, 'unicode')
self.assertIn('lower', infered._proxied.locals)
def test_descriptor_are_callable(self):
code = '''
class A:
statm = staticmethod(open)
clsm = classmethod('whatever')
'''
astroid = builder.string_build(code, __name__, __file__)
statm = astroid['A'].igetattr('statm').next()
self.assertTrue(statm.callable())
clsm = astroid['A'].igetattr('clsm').next()
self.assertTrue(clsm.callable())
def test_bt_ancestor_crash(self):
code = '''
class Warning(Warning):
pass
'''
astroid = builder.string_build(code, __name__, __file__)
w = astroid['Warning']
ancestors = w.ancestors()
ancestor = ancestors.next()
self.assertEqual(ancestor.name, 'Warning')
self.assertEqual(ancestor.root().name, EXC_MODULE)
ancestor = ancestors.next()
self.assertEqual(ancestor.name, 'Exception')
self.assertEqual(ancestor.root().name, EXC_MODULE)
ancestor = ancestors.next()
self.assertEqual(ancestor.name, 'BaseException')
self.assertEqual(ancestor.root().name, EXC_MODULE)
ancestor = ancestors.next()
self.assertEqual(ancestor.name, 'object')
self.assertEqual(ancestor.root().name, BUILTINS)
self.assertRaises(StopIteration, ancestors.next)
def test_qqch(self):
code = '''
from logilab.common.modutils import load_module_from_name
xxx = load_module_from_name('__pkginfo__')
'''
astroid = builder.string_build(code, __name__, __file__)
xxx = astroid['xxx']
self.assertSetEqual(set(n.__class__ for n in xxx.infered()),
set([nodes.Const, YES.__class__]))
def test_method_argument(self):
code = '''
class ErudiEntitySchema:
"""a entity has a type, a set of subject and or object relations"""
def __init__(self, e_type, **kwargs):
kwargs['e_type'] = e_type.capitalize().encode()
def meth(self, e_type, *args, **kwargs):
kwargs['e_type'] = e_type.capitalize().encode()
print(args)
'''
astroid = builder.string_build(code, __name__, __file__)
arg = get_name_node(astroid['ErudiEntitySchema']['__init__'], 'e_type')
self.assertEqual([n.__class__ for n in arg.infer()],
[YES.__class__])
arg = get_name_node(astroid['ErudiEntitySchema']['__init__'], 'kwargs')
self.assertEqual([n.__class__ for n in arg.infer()],
[nodes.Dict])
arg = get_name_node(astroid['ErudiEntitySchema']['meth'], 'e_type')
self.assertEqual([n.__class__ for n in arg.infer()],
[YES.__class__])
arg = get_name_node(astroid['ErudiEntitySchema']['meth'], 'args')
self.assertEqual([n.__class__ for n in arg.infer()],
[nodes.Tuple])
arg = get_name_node(astroid['ErudiEntitySchema']['meth'], 'kwargs')
self.assertEqual([n.__class__ for n in arg.infer()],
[nodes.Dict])
def test_tuple_then_list(self):
code = '''
def test_view(rql, vid, tags=()):
tags = list(tags)
tags.append(vid)
'''
astroid = builder.string_build(code, __name__, __file__)
name = get_name_node(astroid['test_view'], 'tags', -1)
it = name.infer()
tags = it.next()
self.assertEqual(tags.__class__, Instance)
self.assertEqual(tags._proxied.name, 'list')
self.assertRaises(StopIteration, it.next)
def test_mulassign_inference(self):
code = '''
def first_word(line):
"""Return the first word of a line"""
return line.split()[0]
def last_word(line):
"""Return last word of a line"""
return line.split()[-1]
def process_line(word_pos):
"""Silly function: returns (ok, callable) based on argument.
For test purpose only.
"""
if word_pos > 0:
return (True, first_word)
elif word_pos < 0:
return (True, last_word)
else:
return (False, None)
if __name__ == '__main__':
line_number = 0
for a_line in file('test_callable.py'):
tupletest = process_line(line_number)
(ok, fct) = process_line(line_number)
if ok:
fct(a_line)
'''
astroid = builder.string_build(code, __name__, __file__)
self.assertEqual(len(list(astroid['process_line'].infer_call_result(
None))), 3)
self.assertEqual(len(list(astroid['tupletest'].infer())), 3)
values = ['Function(first_word)', 'Function(last_word)', 'Const(NoneType)']
self.assertEqual([str(infered)
for infered in astroid['fct'].infer()], values)
def test_float_complex_ambiguity(self):
code = '''
def no_conjugate_member(magic_flag):
"""should not raise E1101 on something.conjugate"""
if magic_flag:
something = 1.0
else:
something = 1.0j
if isinstance(something, float):
return something
return something.conjugate()
'''
astroid = builder.string_build(code, __name__, __file__)
self.assertEqual([i.value for i in
astroid['no_conjugate_member'].ilookup('something')], [1.0, 1.0j])
self.assertEqual([i.value for i in
get_name_node(astroid, 'something', -1).infer()], [1.0, 1.0j])
def test_lookup_cond_branches(self):
code = '''
def no_conjugate_member(magic_flag):
"""should not raise E1101 on something.conjugate"""
something = 1.0
if magic_flag:
something = 1.0j
return something.conjugate()
'''
astroid = builder.string_build(code, __name__, __file__)
self.assertEqual([i.value for i in
get_name_node(astroid, 'something', -1).infer()], [1.0, 1.0j])
def test_simple_subscript(self):
code = '''
a = [1, 2, 3][0]
b = (1, 2, 3)[1]
c = (1, 2, 3)[-1]
d = a + b + c
print (d)
e = {'key': 'value'}
f = e['key']
print (f)
'''
astroid = builder.string_build(code, __name__, __file__)
self.assertEqual([i.value for i in
get_name_node(astroid, 'a', -1).infer()], [1])
self.assertEqual([i.value for i in
get_name_node(astroid, 'b', -1).infer()], [2])
self.assertEqual([i.value for i in
get_name_node(astroid, 'c', -1).infer()], [3])
self.assertEqual([i.value for i in
get_name_node(astroid, 'd', -1).infer()], [6])
self.assertEqual([i.value for i in
get_name_node(astroid, 'f', -1).infer()], ['value'])
#def test_simple_tuple(self):
#"""test case for a simple tuple value"""
## XXX tuple inference is not implemented ...
#code = """
#a = (1,)
#b = (22,)
#some = a + b
#"""
#astroid = builder.string_build(code, __name__, __file__)
#self.assertEqual(astroid['some'].infer.next().as_string(), "(1, 22)")
def test_simple_for(self):
code = '''
for a in [1, 2, 3]:
print (a)
for b,c in [(1,2), (3,4)]:
print (b)
print (c)
print ([(d,e) for e,d in ([1,2], [3,4])])
'''
astroid = builder.string_build(code, __name__, __file__)
self.assertEqual([i.value for i in
get_name_node(astroid, 'a', -1).infer()], [1, 2, 3])
self.assertEqual([i.value for i in
get_name_node(astroid, 'b', -1).infer()], [1, 3])
self.assertEqual([i.value for i in
get_name_node(astroid, 'c', -1).infer()], [2, 4])
self.assertEqual([i.value for i in
get_name_node(astroid, 'd', -1).infer()], [2, 4])
self.assertEqual([i.value for i in
get_name_node(astroid, 'e', -1).infer()], [1, 3])
def test_simple_for_genexpr(self):
code = '''
print ((d,e) for e,d in ([1,2], [3,4]))
'''
astroid = builder.string_build(code, __name__, __file__)
self.assertEqual([i.value for i in
get_name_node(astroid, 'd', -1).infer()], [2, 4])
self.assertEqual([i.value for i in
get_name_node(astroid, 'e', -1).infer()], [1, 3])
def test_builtin_help(self):
code = '''
help()
'''
# XXX failing since __builtin__.help assignment has
# been moved into a function...
astroid = builder.string_build(code, __name__, __file__)
node = get_name_node(astroid, 'help', -1)
infered = list(node.infer())
self.assertEqual(len(infered), 1, infered)
self.assertIsInstance(infered[0], Instance)
self.assertEqual(str(infered[0]),
'Instance of site._Helper')
def test_builtin_open(self):
code = '''
open("toto.txt")
'''
astroid = builder.string_build(code, __name__, __file__)
node = get_name_node(astroid, 'open', -1)
infered = list(node.infer())
self.assertEqual(len(infered), 1)
if hasattr(sys, 'pypy_version_info'):
self.assertIsInstance(infered[0], nodes.Class)
self.assertEqual(infered[0].name, 'file')
else:
self.assertIsInstance(infered[0], nodes.Function)
self.assertEqual(infered[0].name, 'open')
def test_callfunc_context_func(self):
code = '''
def mirror(arg=None):
return arg
un = mirror(1)
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid.igetattr('un'))
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Const)
self.assertEqual(infered[0].value, 1)
def test_callfunc_context_lambda(self):
code = '''
mirror = lambda x=None: x
un = mirror(1)
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid.igetattr('mirror'))
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Lambda)
infered = list(astroid.igetattr('un'))
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Const)
self.assertEqual(infered[0].value, 1)
def test_factory_method(self):
code = '''
class Super(object):
@classmethod
def instance(cls):
return cls()
class Sub(Super):
def method(self):
print ('method called')
sub = Sub.instance()
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid.igetattr('sub'))
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], Instance)
self.assertEqual(infered[0]._proxied.name, 'Sub')
def test_import_as(self):
code = '''
import os.path as osp
print (osp.dirname(__file__))
from os.path import exists as e
assert e(__file__)
from new import code as make_code
print (make_code)
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid.igetattr('osp'))
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Module)
self.assertEqual(infered[0].name, 'os.path')
infered = list(astroid.igetattr('e'))
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Function)
self.assertEqual(infered[0].name, 'exists')
if sys.version_info >= (3, 0):
self.skipTest(' module has been removed')
infered = list(astroid.igetattr('make_code'))
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], Instance)
self.assertEqual(str(infered[0]),
'Instance of %s.type' % BUILTINS)
def _test_const_infered(self, node, value):
infered = list(node.infer())
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Const)
self.assertEqual(infered[0].value, value)
def test_unary_not(self):
for code in ('a = not (1,); b = not ()',
'a = not {1:2}; b = not {}'):
astroid = builder.string_build(code, __name__, __file__)
self._test_const_infered(astroid['a'], False)
self._test_const_infered(astroid['b'], True)
def test_binary_op_int_add(self):
astroid = builder.string_build('a = 1 + 2', __name__, __file__)
self._test_const_infered(astroid['a'], 3)
def test_binary_op_int_sub(self):
astroid = builder.string_build('a = 1 - 2', __name__, __file__)
self._test_const_infered(astroid['a'], -1)
def test_binary_op_float_div(self):
astroid = builder.string_build('a = 1 / 2.', __name__, __file__)
self._test_const_infered(astroid['a'], 1 / 2.)
def test_binary_op_str_mul(self):
astroid = builder.string_build('a = "*" * 40', __name__, __file__)
self._test_const_infered(astroid['a'], "*" * 40)
def test_binary_op_bitand(self):
astroid = builder.string_build('a = 23&20', __name__, __file__)
self._test_const_infered(astroid['a'], 23&20)
def test_binary_op_bitor(self):
astroid = builder.string_build('a = 23|8', __name__, __file__)
self._test_const_infered(astroid['a'], 23|8)
def test_binary_op_bitxor(self):
astroid = builder.string_build('a = 23^9', __name__, __file__)
self._test_const_infered(astroid['a'], 23^9)
def test_binary_op_shiftright(self):
astroid = builder.string_build('a = 23 >>1', __name__, __file__)
self._test_const_infered(astroid['a'], 23>>1)
def test_binary_op_shiftleft(self):
astroid = builder.string_build('a = 23 <<1', __name__, __file__)
self._test_const_infered(astroid['a'], 23<<1)
def test_binary_op_list_mul(self):
for code in ('a = [[]] * 2', 'a = 2 * [[]]'):
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid['a'].infer())
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.List)
self.assertEqual(len(infered[0].elts), 2)
self.assertIsInstance(infered[0].elts[0], nodes.List)
self.assertIsInstance(infered[0].elts[1], nodes.List)
def test_binary_op_list_mul_none(self):
'test correct handling on list multiplied by None'
astroid = builder.string_build( 'a = [1] * None\nb = [1] * "r"')
infered = astroid['a'].infered()
self.assertEqual(len(infered), 1)
self.assertEqual(infered[0], YES)
infered = astroid['b'].infered()
self.assertEqual(len(infered), 1)
self.assertEqual(infered[0], YES)
def test_binary_op_tuple_add(self):
astroid = builder.string_build('a = (1,) + (2,)', __name__, __file__)
infered = list(astroid['a'].infer())
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Tuple)
self.assertEqual(len(infered[0].elts), 2)
self.assertEqual(infered[0].elts[0].value, 1)
self.assertEqual(infered[0].elts[1].value, 2)
def test_binary_op_custom_class(self):
code = '''
class myarray:
def __init__(self, array):
self.array = array
def __mul__(self, x):
return myarray([2,4,6])
def astype(self):
return "ASTYPE"
def randint(maximum):
if maximum is not None:
return myarray([1,2,3]) * 2
else:
return int(5)
x = randint(1)
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid.igetattr('x'))
self.assertEqual(len(infered), 2)
value = [str(v) for v in infered]
# The __name__ trick here makes it work when invoked directly
# (__name__ == '__main__') and through pytest (__name__ ==
# 'unittest_inference')
self.assertEqual(value, ['Instance of %s.myarray' % __name__,
'Instance of %s.int' % BUILTINS])
def test_nonregr_lambda_arg(self):
code = '''
def f(g = lambda: None):
g().x
'''
astroid = builder.string_build(code, __name__, __file__)
callfuncnode = astroid['f'].body[0].value.expr
infered = list(callfuncnode.infer())
self.assertEqual(len(infered), 2, infered)
infered.remove(YES)
self.assertIsInstance(infered[0], nodes.Const)
self.assertIsNone(infered[0].value)
def test_nonregr_getitem_empty_tuple(self):
code = '''
def f(x):
a = ()[x]
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid['f'].ilookup('a'))
self.assertEqual(len(infered), 1)
self.assertEqual(infered[0], YES)
def test_python25_generator_exit(self):
sys.stderr = StringIO()
data = "b = {}[str(0)+''].a"
astroid = builder.string_build(data, __name__, __file__)
list(astroid['b'].infer())
output = sys.stderr.getvalue()
# I have no idea how to test for this in another way...
self.assertNotIn("RuntimeError", output, "Exception exceptions.RuntimeError: 'generator ignored GeneratorExit' in ignored")
sys.stderr = sys.__stderr__
def test_python25_relative_import(self):
data = "from ...logilab.common import date; print (date)"
# !! FIXME also this relative import would not work 'in real' (no __init__.py in test/)
# the test works since we pretend we have a package by passing the full modname
astroid = builder.string_build(data, 'astroid.test.unittest_inference', __file__)
infered = get_name_node(astroid, 'date').infer().next()
self.assertIsInstance(infered, nodes.Module)
self.assertEqual(infered.name, 'logilab.common.date')
def test_python25_no_relative_import(self):
fname = join(abspath(dirname(__file__)), 'regrtest_data', 'package', 'absimport.py')
astroid = builder.file_build(fname, 'absimport')
self.assertTrue(astroid.absolute_import_activated(), True)
infered = get_name_node(astroid, 'import_package_subpackage_module').infer().next()
# failed to import since absolute_import is activated
self.assertIs(infered, YES)
def test_nonregr_absolute_import(self):
fname = join(abspath(dirname(__file__)), 'regrtest_data', 'absimp', 'string.py')
astroid = builder.file_build(fname, 'absimp.string')
self.assertTrue(astroid.absolute_import_activated(), True)
infered = get_name_node(astroid, 'string').infer().next()
self.assertIsInstance(infered, nodes.Module)
self.assertEqual(infered.name, 'string')
self.assertIn('ascii_letters', infered.locals)
def test_mechanize_open(self):
try:
import mechanize
except ImportError:
self.skipTest('require mechanize installed')
data = '''from mechanize import Browser
print (Browser)
b = Browser()
'''
astroid = builder.string_build(data, __name__, __file__)
browser = get_name_node(astroid, 'Browser').infer().next()
self.assertIsInstance(browser, nodes.Class)
bopen = list(browser.igetattr('open'))
self.skipTest('the commit said: "huum, see that later"')
self.assertEqual(len(bopen), 1)
self.assertIsInstance(bopen[0], nodes.Function)
self.assertTrue(bopen[0].callable())
b = get_name_node(astroid, 'b').infer().next()
self.assertIsInstance(b, Instance)
bopen = list(b.igetattr('open'))
self.assertEqual(len(bopen), 1)
self.assertIsInstance(bopen[0], BoundMethod)
self.assertTrue(bopen[0].callable())
def test_property(self):
code = '''
from smtplib import SMTP
class SendMailController(object):
@property
def smtp(self):
return SMTP(mailhost, port)
@property
def me(self):
return self
my_smtp = SendMailController().smtp
my_me = SendMailController().me
'''
decorators = set(['%s.property' % BUILTINS])
astroid = builder.string_build(code, __name__, __file__)
self.assertEqual(astroid['SendMailController']['smtp'].decoratornames(),
decorators)
propinfered = list(astroid.body[2].value.infer())
self.assertEqual(len(propinfered), 1)
propinfered = propinfered[0]
self.assertIsInstance(propinfered, Instance)
self.assertEqual(propinfered.name, 'SMTP')
self.assertEqual(propinfered.root().name, 'smtplib')
self.assertEqual(astroid['SendMailController']['me'].decoratornames(),
decorators)
propinfered = list(astroid.body[3].value.infer())
self.assertEqual(len(propinfered), 1)
propinfered = propinfered[0]
self.assertIsInstance(propinfered, Instance)
self.assertEqual(propinfered.name, 'SendMailController')
self.assertEqual(propinfered.root().name, __name__)
def test_im_func_unwrap(self):
code = '''
class EnvBasedTC:
def pactions(self):
pass
pactions = EnvBasedTC.pactions.im_func
print (pactions)
class EnvBasedTC2:
pactions = EnvBasedTC.pactions.im_func
print (pactions)
'''
astroid = builder.string_build(code, __name__, __file__)
pactions = get_name_node(astroid, 'pactions')
infered = list(pactions.infer())
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Function)
pactions = get_name_node(astroid['EnvBasedTC2'], 'pactions')
infered = list(pactions.infer())
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Function)
def test_augassign(self):
code = '''
a = 1
a += 2
print (a)
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(get_name_node(astroid, 'a').infer())
self.assertEqual(len(infered), 1)
self.assertIsInstance(infered[0], nodes.Const)
self.assertEqual(infered[0].value, 3)
def test_nonregr_func_arg(self):
code = '''
def foo(self, bar):
def baz():
pass
def qux():
return baz
spam = bar(None, qux)
print (spam)
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(get_name_node(astroid['foo'], 'spam').infer())
self.assertEqual(len(infered), 1)
self.assertIs(infered[0], YES)
def test_nonregr_func_global(self):
code = '''
active_application = None
def get_active_application():
global active_application
return active_application
class Application(object):
def __init__(self):
global active_application
active_application = self
class DataManager(object):
def __init__(self, app=None):
self.app = get_active_application()
def test(self):
p = self.app
print (p)
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(Instance(astroid['DataManager']).igetattr('app'))
self.assertEqual(len(infered), 2, infered) # None / Instance(Application)
infered = list(get_name_node(astroid['DataManager']['test'], 'p').infer())
self.assertEqual(len(infered), 2, infered)
for node in infered:
if isinstance(node, Instance) and node.name == 'Application':
break
else:
self.fail('expected to find an instance of Application in %s' % infered)
def test_list_inference(self):
"""#20464"""
code = '''
import optparse
A = []
B = []
def test():
xyz = [
"foobar=%s" % options.ca,
] + A + B
if options.bind is not None:
xyz.append("bind=%s" % options.bind)
return xyz
def main():
global options
parser = optparse.OptionParser()
(options, args) = parser.parse_args()
Z = test()
'''
astroid = builder.string_build(code, __name__, __file__)
infered = list(astroid['Z'].infer())
self.assertEqual(len(infered), 1, infered)
self.assertIsInstance(infered[0], Instance)
self.assertIsInstance(infered[0]._proxied, nodes.Class)
self.assertEqual(infered[0]._proxied.name, 'list')
def test__new__(self):
code = '''
class NewTest(object):
"doc"
def __new__(cls, arg):
self = object.__new__(cls)
self.arg = arg
return self
n = NewTest()
'''
astroid = builder.string_build(code, __name__, __file__)
self.assertRaises(InferenceError, list, astroid['NewTest'].igetattr('arg'))
n = astroid['n'].infer().next()
infered = list(n.igetattr('arg'))
self.assertEqual(len(infered), 1, infered)
def test_two_parents_from_same_module(self):
code = '''
from data import nonregr
class Xxx(nonregr.Aaa, nonregr.Ccc):
"doc"
'''
astroid = builder.string_build(code, __name__, __file__)
parents = list(astroid['Xxx'].ancestors())
self.assertEqual(len(parents), 3, parents) # Aaa, Ccc, object
def test_pluggable_inference(self):
code = '''
from collections import namedtuple
A = namedtuple('A', ['a', 'b'])
B = namedtuple('B', 'a b')
'''
astroid = builder.string_build(code, __name__, __file__)
aclass = astroid['A'].infered()[0]
self.assertIsInstance(aclass, nodes.Class)
self.assertIn('a', aclass.instance_attrs)
self.assertIn('b', aclass.instance_attrs)
bclass = astroid['B'].infered()[0]
self.assertIsInstance(bclass, nodes.Class)
self.assertIn('a', bclass.instance_attrs)
self.assertIn('b', bclass.instance_attrs)
if __name__ == '__main__':
unittest_main()