# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
# This program 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 General Public License for more details.
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""tests for specific behaviour of astng scoped nodes (ie module, class and
function)
"""
import sys
from logilab.common.testlib import TestCase, unittest_main
from logilab.common.compat import sorted
from logilab.astng import builder, nodes, scoped_nodes, \
InferenceError, NotFoundError
abuilder = builder.ASTNGBuilder()
MODULE = abuilder.file_build('data/module.py', 'data.module')
MODULE2 = abuilder.file_build('data/module2.py', 'data.module2')
NONREGR = abuilder.file_build('data/nonregr.py', 'data.nonregr')
def _test_dict_interface(self, node, test_attr):
self.assert_(node[test_attr] is node[test_attr])
self.assert_(test_attr in node)
node.keys()
node.values()
node.items()
iter(node)
class ModuleNodeTC(TestCase):
def test_dict_interface(self):
_test_dict_interface(self, MODULE, 'YO')
def test_getattr(self):
yo = MODULE.getattr('YO')[0]
self.assertIsInstance(yo, nodes.Class)
self.assertEquals(yo.name, 'YO')
red = MODULE.igetattr('redirect').next()
self.assertIsInstance(red, nodes.Function)
self.assertEquals(red.name, 'nested_args')
spawn = MODULE.igetattr('spawn').next()
self.assertIsInstance(spawn, nodes.Class)
self.assertEquals(spawn.name, 'Execute')
# resolve packageredirection
sys.path.insert(1, 'data')
try:
m = abuilder.file_build('data/appl/myConnection.py', 'appl.myConnection')
cnx = m.igetattr('SSL1').next().igetattr('Connection').next()
self.assertEquals(cnx.__class__, nodes.Class)
self.assertEquals(cnx.name, 'Connection')
self.assertEquals(cnx.root().name, 'SSL1.Connection1')
finally:
del sys.path[1]
self.assertEquals(len(NONREGR.getattr('enumerate')), 2)
# raise ResolveError
self.assertRaises(InferenceError, MODULE.igetattr, 'YOAA')
def test_wildard_import_names(self):
m = abuilder.file_build('data/all.py', 'all')
self.assertEquals(m.wildcard_import_names(), ['Aaa', '_bla', 'name'])
m = abuilder.file_build('data/notall.py', 'notall')
res = m.wildcard_import_names()
res.sort()
self.assertEquals(res, ['Aaa', 'func', 'name', 'other'])
def test_as_string(self):
"""just check as_string on a whole module doesn't raise an exception
"""
self.assert_(MODULE.as_string())
self.assert_(MODULE2.as_string())
class FunctionNodeTC(TestCase):
def test_dict_interface(self):
_test_dict_interface(self, MODULE['global_access'], 'local')
def test_default_value(self):
func = MODULE2['make_class']
self.assertIsInstance(func.default_value('base'), nodes.Getattr)
self.assertRaises(scoped_nodes.NoDefault, func.default_value, 'args')
self.assertRaises(scoped_nodes.NoDefault, func.default_value, 'kwargs')
self.assertRaises(scoped_nodes.NoDefault, func.default_value, 'any')
self.assertIsInstance(func.mularg_class('args'), nodes.Tuple)
self.assertIsInstance(func.mularg_class('kwargs'), nodes.Dict)
self.assertEquals(func.mularg_class('base'), None)
def test_navigation(self):
function = MODULE['global_access']
self.assertEquals(function.statement(), function)
l_sibling = function.previous_sibling()
self.assertIsInstance(l_sibling, nodes.Assign)
self.assert_(l_sibling is function.getChildNodes()[0].previous_sibling())
r_sibling = function.next_sibling()
self.assertIsInstance(r_sibling, nodes.Class)
self.assertEquals(r_sibling.name, 'YO')
self.assert_(r_sibling is function.getChildNodes()[0].next_sibling())
last = r_sibling.next_sibling().next_sibling().next_sibling()
self.assertIsInstance(last, nodes.Assign)
self.assertEquals(last.next_sibling(), None)
first = l_sibling.previous_sibling().previous_sibling().previous_sibling().previous_sibling().previous_sibling()
self.assertEquals(first.previous_sibling(), None)
def test_nested_args(self):
func = MODULE['nested_args']
self.assertEquals(func.argnames, ['a', ('b', 'c', 'd')])
local = func.keys()
local.sort()
self.assertEquals(local, ['a', 'b', 'c', 'd'])
self.assertEquals(func.type, 'function')
def test_format_args(self):
func = MODULE2['make_class']
self.assertEquals(func.format_args(), 'any, base=data.module.YO, *args, **kwargs')
func = MODULE['nested_args']
self.assertEquals(func.format_args(), 'a, (b,c,d)')
def test_is_abstract(self):
method = MODULE2['AbstractClass']['to_override']
self.assert_(method.is_abstract(pass_is_abstract=False))
self.failUnlessEqual(method.qname(), 'data.module2.AbstractClass.to_override')
self.failUnlessEqual(method.pytype(), '__builtin__.instancemethod')
method = MODULE2['AbstractClass']['return_something']
self.assert_(not method.is_abstract(pass_is_abstract=False))
# non regression : test raise "string" doesn't cause an exception in is_abstract
func = MODULE2['raise_string']
self.assert_(not func.is_abstract(pass_is_abstract=False))
## def test_raises(self):
## method = MODULE2['AbstractClass']['to_override']
## self.assertEquals([str(term) for term in method.raises()],
## ["CallFunc(Name('NotImplementedError'), [], None, None)"] )
## def test_returns(self):
## method = MODULE2['AbstractClass']['return_something']
## # use string comp since Node doesn't handle __cmp__
## self.assertEquals([str(term) for term in method.returns()],
## ["Const('toto')", "Const(None)"])
class ClassNodeTC(TestCase):
def test_dict_interface(self):
_test_dict_interface(self, MODULE['YOUPI'], 'method')
def test_navigation(self):
klass = MODULE['YO']
self.assertEquals(klass.statement(), klass)
l_sibling = klass.previous_sibling()
self.assert_(isinstance(l_sibling, nodes.Function), l_sibling)
self.assertEquals(l_sibling.name, 'global_access')
r_sibling = klass.next_sibling()
self.assertIsInstance(r_sibling, nodes.Class)
self.assertEquals(r_sibling.name, 'YOUPI')
def test_local_attr_ancestors(self):
klass2 = MODULE['YOUPI']
it = klass2.local_attr_ancestors('__init__')
anc_klass = it.next()
self.assertIsInstance(anc_klass, nodes.Class)
self.assertEquals(anc_klass.name, 'YO')
self.assertRaises(StopIteration, it.next)
it = klass2.local_attr_ancestors('method')
self.assertRaises(StopIteration, it.next)
def test_instance_attr_ancestors(self):
klass2 = MODULE['YOUPI']
it = klass2.instance_attr_ancestors('yo')
anc_klass = it.next()
self.assertIsInstance(anc_klass, nodes.Class)
self.assertEquals(anc_klass.name, 'YO')
self.assertRaises(StopIteration, it.next)
klass2 = MODULE['YOUPI']
it = klass2.instance_attr_ancestors('member')
self.assertRaises(StopIteration, it.next)
def test_methods(self):
klass2 = MODULE['YOUPI']
methods = [m.name for m in klass2.methods()]
methods.sort()
self.assertEquals(methods, ['__init__', 'class_method',
'method', 'static_method'])
methods = [m.name for m in klass2.mymethods()]
methods.sort()
self.assertEquals(methods, ['__init__', 'class_method',
'method', 'static_method'])
klass2 = MODULE2['Specialization']
methods = [m.name for m in klass2.mymethods()]
methods.sort()
self.assertEquals(methods, [])
self.assertEquals(klass2.local_attr('method').name, 'method')
self.assertRaises(NotFoundError, klass2.local_attr, 'nonexistant')
methods = [m.name for m in klass2.methods()]
methods.sort()
self.assertEquals(methods, ['__init__', 'class_method',
'method', 'static_method'])
#def test_rhs(self):
# my_dict = MODULE['MY_DICT']
# self.assertIsInstance(my_dict.rhs(), nodes.Dict)
# a = MODULE['YO']['a']
# value = a.rhs()
# self.assertIsInstance(value, nodes.Const)
# self.assertEquals(value.value, 1)
def test_ancestors(self):
klass = MODULE['YOUPI']
ancs = [a.name for a in klass.ancestors()]
self.assertEquals(ancs, ['YO'])
klass = MODULE2['Specialization']
ancs = [a.name for a in klass.ancestors()]
self.assertEquals(ancs, ['YOUPI', 'YO', 'YO'])
def test_type(self):
klass = MODULE['YOUPI']
self.assertEquals(klass.type, 'class')
klass = MODULE2['Metaclass']
self.assertEquals(klass.type, 'metaclass')
klass = MODULE2['MyException']
self.assertEquals(klass.type, 'exception')
klass = MODULE2['MyIFace']
self.assertEquals(klass.type, 'interface')
klass = MODULE2['MyError']
self.assertEquals(klass.type, 'exception')
def test_interfaces(self):
for klass, interfaces in (('Concrete0', ['MyIFace']),
('Concrete1', ['MyIFace', 'AnotherIFace']),
('Concrete2', ['MyIFace', 'AnotherIFace']),
('Concrete23', ['MyIFace', 'AnotherIFace'])):
klass = MODULE2[klass]
self.assertEquals([i.name for i in klass.interfaces()],
interfaces)
def test_inner_classes(self):
eee = NONREGR['Ccc']['Eee']
self.assertEquals([n.name for n in eee.ancestors()], ['Ddd', 'Aaa', 'object'])
def test_classmethod_attributes(self):
data = '''
class WebAppObject(object):
def registered(cls, application):
cls.appli = application
cls.schema = application.schema
cls.config = application.config
return cls
registered = classmethod(registered)
'''
astng = abuilder.string_build(data, __name__, __file__)
cls = astng['WebAppObject']
self.assertEquals(sorted(cls.locals.keys()),
['__dict__', '__doc__', '__module__', '__name__',
'appli', 'config', 'registered', 'schema'])
__all__ = ('ModuleNodeTC', 'ImportNodeTC', 'FunctionNodeTC', 'ClassNodeTC')
if __name__ == '__main__':
unittest_main()
syntax highlighted by Code2HTML, v. 0.9.1