root / logilab.pylintinstaller / logilab / astng / test / unittest_inference.py

Revision 202:d67e86292521, 29.4 kB (checked in by tziade@…, 11 months ago)

added logilab.pylintinstaller

Line 
1# This program is free software; you can redistribute it and/or modify it under
2# the terms of the GNU General Public License as published by the Free Software
3# Foundation; either version 2 of the License, or (at your option) any later
4# version.
5
6# This program is distributed in the hope that it will be useful, but WITHOUT
7# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9
10# You should have received a copy of the GNU General Public License along with
11# this program; if not, write to the Free Software Foundation, Inc.,
12# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
13"""tests for the astng inference capabilities
14"""
15
16import sys
17from logilab.common.testlib import TestCase, unittest_main
18
19from logilab.astng import builder, nodes, inference, YES, Instance, \
20     InstanceMethod
21
22def get_name_node(start_from, name, index=0):
23    return [n for n in start_from.nodes_of_class(nodes.Name) if n.name == name][index]
24
25def get_node_of_class(start_from, klass):
26    return start_from.nodes_of_class(klass).next()
27
28builder = builder.ASTNGBuilder()
29
30class InferenceUtilsTC(TestCase):
31
32    def test_path_wrapper(self):
33        infer_default = inference.path_wrapper(inference.infer_default)
34        infer_end = inference.path_wrapper(inference.infer_end)
35        self.failUnlessRaises(inference.InferenceError,
36                              infer_default(1).next)
37        self.failUnlessEqual(infer_end(1).next(), 1)
38       
39class InferenceTC(TestCase):
40
41    DATA = '''
42import exceptions
43
44class C(object):
45    "new style"
46    attr = 4
47   
48    def meth1(self, arg1, optarg=0):
49        var = object()
50        print "yo", arg1, optarg
51        self.iattr = "hop"
52        return var
53       
54    def meth2(self):
55        self.meth1(*self.meth3)
56       
57    def meth3(self, d=attr):
58        b = self.attr
59        c = self.iattr
60        return b, c
61   
62ex = exceptions.Exception("msg")
63v = C().meth1(1)
64m_unbound = C.meth1
65m_bound = C().meth1
66a, b, c = ex, 1, "bonjour"
67[d, e, f] = [ex, 1.0, ("bonjour", v)]
68g, h = f
69i, (j, k) = u"glup", f
70
71a, b= b, a # Gasp !
72'''
73       
74    def setUp(self):
75        self.astng = builder.string_build(self.DATA, __name__, __file__)
76
77    def test_module_inference(self):
78        infered = self.astng.infer()
79        obj = infered.next()
80        self.failUnlessEqual(obj.name, __name__)
81        self.failUnlessEqual(obj.root().name, __name__)
82        self.failUnlessRaises(StopIteration, infered.next)
83       
84    def test_class_inference(self):
85        infered = self.astng['C'].infer()
86        obj = infered.next()
87        self.failUnlessEqual(obj.name, 'C')
88        self.failUnlessEqual(obj.root().name, __name__)
89        self.failUnlessRaises(StopIteration, infered.next)
90       
91    def test_function_inference(self):
92        infered = self.astng['C']['meth1'].infer()
93        obj = infered.next()
94        self.failUnlessEqual(obj.name, 'meth1')
95        self.failUnlessEqual(obj.root().name, __name__)
96        self.failUnlessRaises(StopIteration, infered.next)
97
98    def test_builtin_name_inference(self):
99        infered = self.astng['C']['meth1']['var'].infer()
100        var = infered.next()
101        self.failUnlessEqual(var.name, 'object')
102        self.failUnlessEqual(var.root().name, '__builtin__')
103        self.failUnlessRaises(StopIteration, infered.next)
104       
105    def test_tupleassign_name_inference(self):
106        infered = self.astng['a'].infer()
107        exc = infered.next()
108        self.failUnless(isinstance(exc, inference.Instance))
109        self.failUnlessEqual(exc.name, 'Exception')
110        self.failUnlessEqual(exc.root().name, 'exceptions')
111        self.failUnlessRaises(StopIteration, infered.next)
112        infered = self.astng['b'].infer()
113        const = infered.next()
114        self.failUnless(isinstance(const, nodes.Const))
115        self.failUnlessEqual(const.value, 1)
116        self.failUnlessRaises(StopIteration, infered.next)
117        infered = self.astng['c'].infer()
118        const = infered.next()
119        self.failUnless(isinstance(const, nodes.Const))
120        self.failUnlessEqual(const.value, "bonjour")
121        self.failUnlessRaises(StopIteration, infered.next)
122       
123    def test_listassign_name_inference(self):
124        infered = self.astng['d'].infer()
125        exc = infered.next()
126        self.failUnless(isinstance(exc, inference.Instance))
127        self.failUnlessEqual(exc.name, 'Exception')
128        self.failUnlessEqual(exc.root().name, 'exceptions')
129        self.failUnlessRaises(StopIteration, infered.next)
130        infered = self.astng['e'].infer()
131        const = infered.next()
132        self.failUnless(isinstance(const, nodes.Const))
133        self.failUnlessEqual(const.value, 1.0)
134        self.failUnlessRaises(StopIteration, infered.next)
135        infered = self.astng['f'].infer()
136        const = infered.next()
137        self.failUnless(isinstance(const, nodes.Tuple))
138        self.failUnlessRaises(StopIteration, infered.next)
139       
140    def test_advanced_tupleassign_name_inference1(self):
141        infered = self.astng['g'].infer()
142        const = infered.next()
143        self.failUnless(isinstance(const, nodes.Const))
144        self.failUnlessEqual(const.value, "bonjour")
145        self.failUnlessRaises(StopIteration, infered.next)
146        infered = self.astng['h'].infer()
147        var = infered.next()
148        self.failUnlessEqual(var.name, 'object')
149        self.failUnlessEqual(var.root().name, '__builtin__')
150        self.failUnlessRaises(StopIteration, infered.next)
151       
152    def test_advanced_tupleassign_name_inference2(self):
153        infered = self.astng['i'].infer()
154        const = infered.next()
155        self.failUnless(isinstance(const, nodes.Const))
156        self.failUnlessEqual(const.value, u"glup")
157        self.failUnlessRaises(StopIteration, infered.next)
158        infered = self.astng['j'].infer()
159        const = infered.next()
160        self.failUnless(isinstance(const, nodes.Const))
161        self.failUnlessEqual(const.value, "bonjour")
162        self.failUnlessRaises(StopIteration, infered.next)
163        infered = self.astng['k'].infer()
164        var = infered.next()
165        self.failUnlessEqual(var.name, 'object')
166        self.failUnlessEqual(var.root().name, '__builtin__')
167        self.failUnlessRaises(StopIteration, infered.next)
168       
169    def test_swap_assign_inference(self):
170        infered = self.astng.locals['a'][1].infer()
171        const = infered.next()
172        self.failUnless(isinstance(const, nodes.Const))
173        self.failUnlessEqual(const.value, 1)
174        self.failUnlessRaises(StopIteration, infered.next)
175        infered = self.astng.locals['b'][1].infer()
176        exc = infered.next()
177        self.failUnless(isinstance(exc, inference.Instance))
178        self.failUnlessEqual(exc.name, 'Exception')
179        self.failUnlessEqual(exc.root().name, 'exceptions')
180        self.failUnlessRaises(StopIteration, infered.next)
181       
182    def test_getattr_inference1(self):
183        infered = self.astng['ex'].infer()
184        exc = infered.next()
185        self.failUnless(isinstance(exc, inference.Instance))
186        self.failUnlessEqual(exc.name, 'Exception')
187        self.failUnlessEqual(exc.root().name, 'exceptions')
188        self.failUnlessRaises(StopIteration, infered.next)
189       
190    def test_getattr_inference2(self):
191        infered = get_node_of_class(self.astng['C']['meth2'], nodes.Getattr).infer()
192        meth1 = infered.next()
193        self.failUnlessEqual(meth1.name, 'meth1')
194        self.failUnlessEqual(meth1.root().name, __name__)
195        self.failUnlessRaises(StopIteration, infered.next)
196       
197    def test_getattr_inference3(self):
198        infered = self.astng['C']['meth3']['b'].infer()
199        const = infered.next()
200        self.failUnless(isinstance(const, nodes.Const))
201        self.failUnlessEqual(const.value, 4)
202        self.failUnlessRaises(StopIteration, infered.next)
203       
204    def test_getattr_inference4(self):
205        infered = self.astng['C']['meth3']['c'].infer()
206        const = infered.next()
207        self.failUnless(isinstance(const, nodes.Const))
208        self.failUnlessEqual(const.value, "hop")
209        self.failUnlessRaises(StopIteration, infered.next)
210       
211    def test_callfunc_inference(self):
212        infered = self.astng['v'].infer()
213        meth1 = infered.next()
214        self.failUnless(isinstance(meth1, inference.Instance))
215        self.failUnlessEqual(meth1.name, 'object')
216        self.failUnlessEqual(meth1.root().name, '__builtin__')
217        self.failUnlessRaises(StopIteration, infered.next)
218
219    def test_unbound_method_inference(self):
220        infered = self.astng['m_unbound'].infer()
221        meth1 = infered.next()
222        self.failUnless(isinstance(meth1, nodes.Function))
223        self.failUnlessEqual(meth1.name, 'meth1')
224        self.failUnlessEqual(meth1.parent.frame().name, 'C')
225        self.failUnlessRaises(StopIteration, infered.next)
226
227    def test_bound_method_inference(self):
228        infered = self.astng['m_bound'].infer()
229        meth1 = infered.next()
230        self.failUnless(isinstance(meth1, InstanceMethod))
231        self.failUnlessEqual(meth1.name, 'meth1')
232        self.failUnlessEqual(meth1.parent.frame().name, 'C')
233        self.failUnlessRaises(StopIteration, infered.next)
234
235    def test_args_default_inference1(self):
236        optarg = get_name_node(self.astng['C']['meth1'], 'optarg')
237        infered = optarg.infer()
238        obj1 = infered.next()
239        self.failUnless(isinstance(obj1, nodes.Const))
240        self.failUnlessEqual(obj1.value, 0)
241        obj1 = infered.next()
242        self.failUnless(obj1 is YES)
243        self.failUnlessRaises(StopIteration, infered.next)
244
245    def test_args_default_inference2(self):
246        infered = self.astng['C']['meth3'].ilookup('d')
247        obj1 = infered.next()
248        self.failUnless(isinstance(obj1, nodes.Const))
249        self.failUnlessEqual(obj1.value, 4)
250        obj1 = infered.next()
251        self.failUnless(obj1 is YES)
252        self.failUnlessRaises(StopIteration, infered.next)
253       
254    def test_inference_restrictions(self):
255        infered = get_name_node(self.astng['C']['meth1'], 'arg1').infer()
256        obj1 = infered.next()
257        self.failUnless(obj1 is YES)
258        self.failUnlessRaises(StopIteration, infered.next)
259
260    def test_del(self):
261        data = '''
262del undefined_attr
263        '''
264        astng = builder.string_build(data, __name__, __file__)
265        self.failUnlessRaises(inference.InferenceError,
266                              astng.node.getChildNodes()[0].infer().next)
267       
268    def test_ancestors_inference(self):
269        data = '''
270class A:
271    pass
272
273class A(A):
274    pass
275        '''
276        astng = builder.string_build(data, __name__, __file__)
277        a1 = astng.locals['A'][0]
278        a2 = astng.locals['A'][1]
279        a2_ancestors = list(a2.ancestors())
280        self.failUnlessEqual(len(a2_ancestors), 1)
281        self.failUnless(a2_ancestors[0] is a1)
282
283    def test_ancestors_inference2(self):
284        data = '''
285class A:
286    pass
287
288class B(A): pass
289
290class A(B):
291    pass
292        '''
293        astng = builder.string_build(data, __name__, __file__)
294        a1 = astng.locals['A'][0]
295        a2 = astng.locals['A'][1]
296        a2_ancestors = list(a2.ancestors())
297        self.failUnlessEqual(len(a2_ancestors), 2)
298        self.failUnless(a2_ancestors[0] is astng.locals['B'][0])
299        self.failUnless(a2_ancestors[1] is a1, a2_ancestors[1])
300
301
302    def test_f_arg_f(self):
303        data = '''
304def f(f=1):
305    return f
306
307a = f()
308        '''
309        astng = builder.string_build(data, __name__, __file__)
310        a = astng['a']
311        a_infer = a.infer()
312        self.failUnlessEqual(a_infer.next().value, 1)
313        self.failUnlessRaises(StopIteration, a_infer.next)
314       
315    def test_exc_ancestors(self):
316        data = '''
317def f():
318    raise NotImplementedError
319        '''
320        astng = builder.string_build(data, __name__, __file__)
321        names = astng.nodes_of_class(nodes.Name)
322        nie = names.next().infer().next()
323        self.failUnless(isinstance(nie, nodes.Class))
324        nie_ancestors = [c.name for c in nie.ancestors()]
325        if sys.version_info < (2, 5):
326            self.failUnlessEqual(nie_ancestors, ['RuntimeError', 'StandardError', 'Exception'])
327        else:
328            self.failUnlessEqual(nie_ancestors, ['RuntimeError', 'StandardError', 'Exception', 'BaseException', 'object'])
329
330    def test_except_inference(self):
331        data = '''
332try:
333    print hop
334except NameError, ex:
335    ex1 = ex
336except Exception, ex:
337    ex2 = ex
338    raise
339        '''
340        astng = builder.string_build(data, __name__, __file__)
341        ex1 = astng['ex1']
342        ex1_infer = ex1.infer()
343        infered = list(ex1.infer())
344        #print 'EX1:', ex1
345        #print 'INFEREND', infered
346        ex1 = ex1_infer.next()
347        self.failUnless(isinstance(ex1, inference.Instance))
348        self.failUnlessEqual(ex1.name, 'NameError')
349        self.failUnlessRaises(StopIteration, ex1_infer