Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

unittest_helpers.py 9.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. # Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com>
  2. # Copyright (c) 2015-2016 Claudiu Popa <pcmanticore@gmail.com>
  3. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  4. # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
  5. import unittest
  6. import six
  7. from six.moves import builtins
  8. from astroid import builder
  9. from astroid import exceptions
  10. from astroid import helpers
  11. from astroid import manager
  12. from astroid import raw_building
  13. from astroid import test_utils
  14. from astroid import util
  15. class TestHelpers(unittest.TestCase):
  16. def setUp(self):
  17. builtins_name = builtins.__name__
  18. astroid_manager = manager.AstroidManager()
  19. self.builtins = astroid_manager.astroid_cache[builtins_name]
  20. self.manager = manager.AstroidManager()
  21. def _extract(self, obj_name):
  22. return self.builtins.getattr(obj_name)[0]
  23. def _build_custom_builtin(self, obj_name):
  24. proxy = raw_building.build_class(obj_name)
  25. proxy.parent = self.builtins
  26. return proxy
  27. def assert_classes_equal(self, cls, other):
  28. self.assertEqual(cls.name, other.name)
  29. self.assertEqual(cls.parent, other.parent)
  30. self.assertEqual(cls.qname(), other.qname())
  31. def test_object_type(self):
  32. pairs = [
  33. ('1', self._extract('int')),
  34. ('[]', self._extract('list')),
  35. ('{1, 2, 3}', self._extract('set')),
  36. ('{1:2, 4:3}', self._extract('dict')),
  37. ('type', self._extract('type')),
  38. ('object', self._extract('type')),
  39. ('object()', self._extract('object')),
  40. ('lambda: None', self._build_custom_builtin('function')),
  41. ('len', self._build_custom_builtin('builtin_function_or_method')),
  42. ('None', self._build_custom_builtin('NoneType')),
  43. ('import sys\nsys#@', self._build_custom_builtin('module')),
  44. ]
  45. for code, expected in pairs:
  46. node = builder.extract_node(code)
  47. objtype = helpers.object_type(node)
  48. self.assert_classes_equal(objtype, expected)
  49. def test_object_type_classes_and_functions(self):
  50. ast_nodes = builder.extract_node('''
  51. def generator():
  52. yield
  53. class A(object):
  54. def test(self):
  55. self #@
  56. @classmethod
  57. def cls_method(cls): pass
  58. @staticmethod
  59. def static_method(): pass
  60. A #@
  61. A() #@
  62. A.test #@
  63. A().test #@
  64. A.cls_method #@
  65. A().cls_method #@
  66. A.static_method #@
  67. A().static_method #@
  68. generator() #@
  69. ''')
  70. from_self = helpers.object_type(ast_nodes[0])
  71. cls = next(ast_nodes[1].infer())
  72. self.assert_classes_equal(from_self, cls)
  73. cls_type = helpers.object_type(ast_nodes[1])
  74. self.assert_classes_equal(cls_type, self._extract('type'))
  75. instance_type = helpers.object_type(ast_nodes[2])
  76. cls = next(ast_nodes[2].infer())._proxied
  77. self.assert_classes_equal(instance_type, cls)
  78. expected_method_types = [
  79. (ast_nodes[3], 'instancemethod' if six.PY2 else 'function'),
  80. (ast_nodes[4], 'instancemethod' if six.PY2 else 'method'),
  81. (ast_nodes[5], 'instancemethod' if six.PY2 else 'method'),
  82. (ast_nodes[6], 'instancemethod' if six.PY2 else 'method'),
  83. (ast_nodes[7], 'function'),
  84. (ast_nodes[8], 'function'),
  85. (ast_nodes[9], 'generator'),
  86. ]
  87. for node, expected in expected_method_types:
  88. node_type = helpers.object_type(node)
  89. expected_type = self._build_custom_builtin(expected)
  90. self.assert_classes_equal(node_type, expected_type)
  91. @test_utils.require_version(minver='3.0')
  92. def test_object_type_metaclasses(self):
  93. module = builder.parse('''
  94. import abc
  95. class Meta(metaclass=abc.ABCMeta):
  96. pass
  97. meta_instance = Meta()
  98. ''')
  99. meta_type = helpers.object_type(module['Meta'])
  100. self.assert_classes_equal(meta_type, module['Meta'].metaclass())
  101. meta_instance = next(module['meta_instance'].infer())
  102. instance_type = helpers.object_type(meta_instance)
  103. self.assert_classes_equal(instance_type, module['Meta'])
  104. @test_utils.require_version(minver='3.0')
  105. def test_object_type_most_derived(self):
  106. node = builder.extract_node('''
  107. class A(type):
  108. def __new__(*args, **kwargs):
  109. return type.__new__(*args, **kwargs)
  110. class B(object): pass
  111. class C(object, metaclass=A): pass
  112. # The most derived metaclass of D is A rather than type.
  113. class D(B , C): #@
  114. pass
  115. ''')
  116. metaclass = node.metaclass()
  117. self.assertEqual(metaclass.name, 'A')
  118. obj_type = helpers.object_type(node)
  119. self.assertEqual(metaclass, obj_type)
  120. def test_inference_errors(self):
  121. node = builder.extract_node('''
  122. from unknown import Unknown
  123. u = Unknown #@
  124. ''')
  125. self.assertEqual(helpers.object_type(node), util.Uninferable)
  126. def test_object_type_too_many_types(self):
  127. node = builder.extract_node('''
  128. from unknown import Unknown
  129. def test(x):
  130. if x:
  131. return lambda: None
  132. else:
  133. return 1
  134. test(Unknown) #@
  135. ''')
  136. self.assertEqual(helpers.object_type(node), util.Uninferable)
  137. def test_is_subtype(self):
  138. ast_nodes = builder.extract_node('''
  139. class int_subclass(int):
  140. pass
  141. class A(object): pass #@
  142. class B(A): pass #@
  143. class C(A): pass #@
  144. int_subclass() #@
  145. ''')
  146. cls_a = ast_nodes[0]
  147. cls_b = ast_nodes[1]
  148. cls_c = ast_nodes[2]
  149. int_subclass = ast_nodes[3]
  150. int_subclass = helpers.object_type(next(int_subclass.infer()))
  151. base_int = self._extract('int')
  152. self.assertTrue(helpers.is_subtype(int_subclass, base_int))
  153. self.assertTrue(helpers.is_supertype(base_int, int_subclass))
  154. self.assertTrue(helpers.is_supertype(cls_a, cls_b))
  155. self.assertTrue(helpers.is_supertype(cls_a, cls_c))
  156. self.assertTrue(helpers.is_subtype(cls_b, cls_a))
  157. self.assertTrue(helpers.is_subtype(cls_c, cls_a))
  158. self.assertFalse(helpers.is_subtype(cls_a, cls_b))
  159. self.assertFalse(helpers.is_subtype(cls_a, cls_b))
  160. @test_utils.require_version(maxver='3.0')
  161. def test_is_subtype_supertype_old_style_classes(self):
  162. cls_a, cls_b = builder.extract_node('''
  163. class A: #@
  164. pass
  165. class B(A): #@
  166. pass
  167. ''')
  168. self.assertFalse(helpers.is_subtype(cls_a, cls_b))
  169. self.assertFalse(helpers.is_subtype(cls_b, cls_a))
  170. self.assertFalse(helpers.is_supertype(cls_a, cls_b))
  171. self.assertFalse(helpers.is_supertype(cls_b, cls_a))
  172. def test_is_subtype_supertype_mro_error(self):
  173. cls_e, cls_f = builder.extract_node('''
  174. class A(object): pass
  175. class B(A): pass
  176. class C(A): pass
  177. class D(B, C): pass
  178. class E(C, B): pass #@
  179. class F(D, E): pass #@
  180. ''')
  181. self.assertFalse(helpers.is_subtype(cls_e, cls_f))
  182. self.assertFalse(helpers.is_subtype(cls_e, cls_f))
  183. with self.assertRaises(exceptions._NonDeducibleTypeHierarchy):
  184. helpers.is_subtype(cls_f, cls_e)
  185. self.assertFalse(helpers.is_supertype(cls_f, cls_e))
  186. def test_is_subtype_supertype_unknown_bases(self):
  187. cls_a, cls_b = builder.extract_node('''
  188. from unknown import Unknown
  189. class A(Unknown): pass #@
  190. class B(A): pass #@
  191. ''')
  192. with self.assertRaises(exceptions._NonDeducibleTypeHierarchy):
  193. helpers.is_subtype(cls_a, cls_b)
  194. with self.assertRaises(exceptions._NonDeducibleTypeHierarchy):
  195. helpers.is_supertype(cls_a, cls_b)
  196. def test_is_subtype_supertype_unrelated_classes(self):
  197. cls_a, cls_b = builder.extract_node('''
  198. class A(object): pass #@
  199. class B(object): pass #@
  200. ''')
  201. self.assertFalse(helpers.is_subtype(cls_a, cls_b))
  202. self.assertFalse(helpers.is_subtype(cls_b, cls_a))
  203. self.assertFalse(helpers.is_supertype(cls_a, cls_b))
  204. self.assertFalse(helpers.is_supertype(cls_b, cls_a))
  205. def test_is_subtype_supertype_classes_no_type_ancestor(self):
  206. cls_a = builder.extract_node('''
  207. class A(object): #@
  208. pass
  209. ''')
  210. builtin_type = self._extract('type')
  211. self.assertFalse(helpers.is_supertype(builtin_type, cls_a))
  212. self.assertFalse(helpers.is_subtype(cls_a, builtin_type))
  213. def test_is_subtype_supertype_classes_metaclasses(self):
  214. cls_a = builder.extract_node('''
  215. class A(type): #@
  216. pass
  217. ''')
  218. builtin_type = self._extract('type')
  219. self.assertTrue(helpers.is_supertype(builtin_type, cls_a))
  220. self.assertTrue(helpers.is_subtype(cls_a, builtin_type))
  221. if __name__ == '__main__':
  222. unittest.main()