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_objects.py 19KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507
  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. from astroid import bases
  7. from astroid import builder
  8. from astroid import exceptions
  9. from astroid import nodes
  10. from astroid import objects
  11. from astroid import test_utils
  12. class ObjectsTest(unittest.TestCase):
  13. def test_frozenset(self):
  14. node = builder.extract_node("""
  15. frozenset({1: 2, 2: 3}) #@
  16. """)
  17. inferred = next(node.infer())
  18. self.assertIsInstance(inferred, objects.FrozenSet)
  19. self.assertEqual(inferred.pytype(), "%s.frozenset" % bases.BUILTINS)
  20. itered = inferred.itered()
  21. self.assertEqual(len(itered), 2)
  22. self.assertIsInstance(itered[0], nodes.Const)
  23. self.assertEqual([const.value for const in itered], [1, 2])
  24. proxied = inferred._proxied
  25. self.assertEqual(inferred.qname(), "%s.frozenset" % bases.BUILTINS)
  26. self.assertIsInstance(proxied, nodes.ClassDef)
  27. class SuperTests(unittest.TestCase):
  28. def test_inferring_super_outside_methods(self):
  29. ast_nodes = builder.extract_node('''
  30. class Module(object):
  31. pass
  32. class StaticMethod(object):
  33. @staticmethod
  34. def static():
  35. # valid, but we don't bother with it.
  36. return super(StaticMethod, StaticMethod) #@
  37. # super outside methods aren't inferred
  38. super(Module, Module) #@
  39. # no argument super is not recognised outside methods as well.
  40. super() #@
  41. ''')
  42. in_static = next(ast_nodes[0].value.infer())
  43. self.assertIsInstance(in_static, bases.Instance)
  44. self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS)
  45. module_level = next(ast_nodes[1].infer())
  46. self.assertIsInstance(module_level, bases.Instance)
  47. self.assertEqual(in_static.qname(), "%s.super" % bases.BUILTINS)
  48. no_arguments = next(ast_nodes[2].infer())
  49. self.assertIsInstance(no_arguments, bases.Instance)
  50. self.assertEqual(no_arguments.qname(), "%s.super" % bases.BUILTINS)
  51. def test_inferring_unbound_super_doesnt_work(self):
  52. node = builder.extract_node('''
  53. class Test(object):
  54. def __init__(self):
  55. super(Test) #@
  56. ''')
  57. unbounded = next(node.infer())
  58. self.assertIsInstance(unbounded, bases.Instance)
  59. self.assertEqual(unbounded.qname(), "%s.super" % bases.BUILTINS)
  60. def test_use_default_inference_on_not_inferring_args(self):
  61. ast_nodes = builder.extract_node('''
  62. class Test(object):
  63. def __init__(self):
  64. super(Lala, self) #@
  65. super(Test, lala) #@
  66. ''')
  67. first = next(ast_nodes[0].infer())
  68. self.assertIsInstance(first, bases.Instance)
  69. self.assertEqual(first.qname(), "%s.super" % bases.BUILTINS)
  70. second = next(ast_nodes[1].infer())
  71. self.assertIsInstance(second, bases.Instance)
  72. self.assertEqual(second.qname(), "%s.super" % bases.BUILTINS)
  73. @test_utils.require_version(maxver='3.0')
  74. def test_super_on_old_style_class(self):
  75. # super doesn't work on old style class, but leave
  76. # that as an error for pylint. We'll infer Super objects,
  77. # but every call will result in a failure at some point.
  78. node = builder.extract_node('''
  79. class OldStyle:
  80. def __init__(self):
  81. super(OldStyle, self) #@
  82. ''')
  83. old = next(node.infer())
  84. self.assertIsInstance(old, objects.Super)
  85. self.assertIsInstance(old.mro_pointer, nodes.ClassDef)
  86. self.assertEqual(old.mro_pointer.name, 'OldStyle')
  87. with self.assertRaises(exceptions.SuperError) as cm:
  88. old.super_mro()
  89. self.assertEqual(str(cm.exception),
  90. "Unable to call super on old-style classes.")
  91. @test_utils.require_version(minver='3.0')
  92. def test_no_arguments_super(self):
  93. ast_nodes = builder.extract_node('''
  94. class First(object): pass
  95. class Second(First):
  96. def test(self):
  97. super() #@
  98. @classmethod
  99. def test_classmethod(cls):
  100. super() #@
  101. ''')
  102. first = next(ast_nodes[0].infer())
  103. self.assertIsInstance(first, objects.Super)
  104. self.assertIsInstance(first.type, bases.Instance)
  105. self.assertEqual(first.type.name, 'Second')
  106. self.assertIsInstance(first.mro_pointer, nodes.ClassDef)
  107. self.assertEqual(first.mro_pointer.name, 'Second')
  108. second = next(ast_nodes[1].infer())
  109. self.assertIsInstance(second, objects.Super)
  110. self.assertIsInstance(second.type, nodes.ClassDef)
  111. self.assertEqual(second.type.name, 'Second')
  112. self.assertIsInstance(second.mro_pointer, nodes.ClassDef)
  113. self.assertEqual(second.mro_pointer.name, 'Second')
  114. def test_super_simple_cases(self):
  115. ast_nodes = builder.extract_node('''
  116. class First(object): pass
  117. class Second(First): pass
  118. class Third(First):
  119. def test(self):
  120. super(Third, self) #@
  121. super(Second, self) #@
  122. # mro position and the type
  123. super(Third, Third) #@
  124. super(Third, Second) #@
  125. super(Fourth, Fourth) #@
  126. class Fourth(Third):
  127. pass
  128. ''')
  129. # .type is the object which provides the mro.
  130. # .mro_pointer is the position in the mro from where
  131. # the lookup should be done.
  132. # super(Third, self)
  133. first = next(ast_nodes[0].infer())
  134. self.assertIsInstance(first, objects.Super)
  135. self.assertIsInstance(first.type, bases.Instance)
  136. self.assertEqual(first.type.name, 'Third')
  137. self.assertIsInstance(first.mro_pointer, nodes.ClassDef)
  138. self.assertEqual(first.mro_pointer.name, 'Third')
  139. # super(Second, self)
  140. second = next(ast_nodes[1].infer())
  141. self.assertIsInstance(second, objects.Super)
  142. self.assertIsInstance(second.type, bases.Instance)
  143. self.assertEqual(second.type.name, 'Third')
  144. self.assertIsInstance(first.mro_pointer, nodes.ClassDef)
  145. self.assertEqual(second.mro_pointer.name, 'Second')
  146. # super(Third, Third)
  147. third = next(ast_nodes[2].infer())
  148. self.assertIsInstance(third, objects.Super)
  149. self.assertIsInstance(third.type, nodes.ClassDef)
  150. self.assertEqual(third.type.name, 'Third')
  151. self.assertIsInstance(third.mro_pointer, nodes.ClassDef)
  152. self.assertEqual(third.mro_pointer.name, 'Third')
  153. # super(Third, second)
  154. fourth = next(ast_nodes[3].infer())
  155. self.assertIsInstance(fourth, objects.Super)
  156. self.assertIsInstance(fourth.type, nodes.ClassDef)
  157. self.assertEqual(fourth.type.name, 'Second')
  158. self.assertIsInstance(fourth.mro_pointer, nodes.ClassDef)
  159. self.assertEqual(fourth.mro_pointer.name, 'Third')
  160. # Super(Fourth, Fourth)
  161. fifth = next(ast_nodes[4].infer())
  162. self.assertIsInstance(fifth, objects.Super)
  163. self.assertIsInstance(fifth.type, nodes.ClassDef)
  164. self.assertEqual(fifth.type.name, 'Fourth')
  165. self.assertIsInstance(fifth.mro_pointer, nodes.ClassDef)
  166. self.assertEqual(fifth.mro_pointer.name, 'Fourth')
  167. def test_super_infer(self):
  168. node = builder.extract_node('''
  169. class Super(object):
  170. def __init__(self):
  171. super(Super, self) #@
  172. ''')
  173. inferred = next(node.infer())
  174. self.assertIsInstance(inferred, objects.Super)
  175. reinferred = next(inferred.infer())
  176. self.assertIsInstance(reinferred, objects.Super)
  177. self.assertIs(inferred, reinferred)
  178. def test_inferring_invalid_supers(self):
  179. ast_nodes = builder.extract_node('''
  180. class Super(object):
  181. def __init__(self):
  182. # MRO pointer is not a type
  183. super(1, self) #@
  184. # MRO type is not a subtype
  185. super(Super, 1) #@
  186. # self is not a subtype of Bupper
  187. super(Bupper, self) #@
  188. class Bupper(Super):
  189. pass
  190. ''')
  191. first = next(ast_nodes[0].infer())
  192. self.assertIsInstance(first, objects.Super)
  193. with self.assertRaises(exceptions.SuperError) as cm:
  194. first.super_mro()
  195. self.assertIsInstance(cm.exception.super_.mro_pointer, nodes.Const)
  196. self.assertEqual(cm.exception.super_.mro_pointer.value, 1)
  197. for node, invalid_type in zip(ast_nodes[1:],
  198. (nodes.Const, bases.Instance)):
  199. inferred = next(node.infer())
  200. self.assertIsInstance(inferred, objects.Super, node)
  201. with self.assertRaises(exceptions.SuperError) as cm:
  202. inferred.super_mro()
  203. self.assertIsInstance(cm.exception.super_.type, invalid_type)
  204. def test_proxied(self):
  205. node = builder.extract_node('''
  206. class Super(object):
  207. def __init__(self):
  208. super(Super, self) #@
  209. ''')
  210. inferred = next(node.infer())
  211. proxied = inferred._proxied
  212. self.assertEqual(proxied.qname(), "%s.super" % bases.BUILTINS)
  213. self.assertIsInstance(proxied, nodes.ClassDef)
  214. def test_super_bound_model(self):
  215. ast_nodes = builder.extract_node('''
  216. class First(object):
  217. def method(self):
  218. pass
  219. @classmethod
  220. def class_method(cls):
  221. pass
  222. class Super_Type_Type(First):
  223. def method(self):
  224. super(Super_Type_Type, Super_Type_Type).method #@
  225. super(Super_Type_Type, Super_Type_Type).class_method #@
  226. @classmethod
  227. def class_method(cls):
  228. super(Super_Type_Type, Super_Type_Type).method #@
  229. super(Super_Type_Type, Super_Type_Type).class_method #@
  230. class Super_Type_Object(First):
  231. def method(self):
  232. super(Super_Type_Object, self).method #@
  233. super(Super_Type_Object, self).class_method #@
  234. ''')
  235. # Super(type, type) is the same for both functions and classmethods.
  236. first = next(ast_nodes[0].infer())
  237. self.assertIsInstance(first, nodes.FunctionDef)
  238. self.assertEqual(first.name, 'method')
  239. second = next(ast_nodes[1].infer())
  240. self.assertIsInstance(second, bases.BoundMethod)
  241. self.assertEqual(second.bound.name, 'First')
  242. self.assertEqual(second.type, 'classmethod')
  243. third = next(ast_nodes[2].infer())
  244. self.assertIsInstance(third, nodes.FunctionDef)
  245. self.assertEqual(third.name, 'method')
  246. fourth = next(ast_nodes[3].infer())
  247. self.assertIsInstance(fourth, bases.BoundMethod)
  248. self.assertEqual(fourth.bound.name, 'First')
  249. self.assertEqual(fourth.type, 'classmethod')
  250. # Super(type, obj) can lead to different attribute bindings
  251. # depending on the type of the place where super was called.
  252. fifth = next(ast_nodes[4].infer())
  253. self.assertIsInstance(fifth, bases.BoundMethod)
  254. self.assertEqual(fifth.bound.name, 'First')
  255. self.assertEqual(fifth.type, 'method')
  256. sixth = next(ast_nodes[5].infer())
  257. self.assertIsInstance(sixth, bases.BoundMethod)
  258. self.assertEqual(sixth.bound.name, 'First')
  259. self.assertEqual(sixth.type, 'classmethod')
  260. def test_super_getattr_single_inheritance(self):
  261. ast_nodes = builder.extract_node('''
  262. class First(object):
  263. def test(self): pass
  264. class Second(First):
  265. def test2(self): pass
  266. class Third(Second):
  267. test3 = 42
  268. def __init__(self):
  269. super(Third, self).test2 #@
  270. super(Third, self).test #@
  271. # test3 is local, no MRO lookup is done.
  272. super(Third, self).test3 #@
  273. super(Third, self) #@
  274. # Unbounds.
  275. super(Third, Third).test2 #@
  276. super(Third, Third).test #@
  277. ''')
  278. first = next(ast_nodes[0].infer())
  279. self.assertIsInstance(first, bases.BoundMethod)
  280. self.assertEqual(first.bound.name, 'Second')
  281. second = next(ast_nodes[1].infer())
  282. self.assertIsInstance(second, bases.BoundMethod)
  283. self.assertEqual(second.bound.name, 'First')
  284. with self.assertRaises(exceptions.InferenceError):
  285. next(ast_nodes[2].infer())
  286. fourth = next(ast_nodes[3].infer())
  287. with self.assertRaises(exceptions.AttributeInferenceError):
  288. fourth.getattr('test3')
  289. with self.assertRaises(exceptions.AttributeInferenceError):
  290. next(fourth.igetattr('test3'))
  291. first_unbound = next(ast_nodes[4].infer())
  292. self.assertIsInstance(first_unbound, nodes.FunctionDef)
  293. self.assertEqual(first_unbound.name, 'test2')
  294. self.assertEqual(first_unbound.parent.name, 'Second')
  295. second_unbound = next(ast_nodes[5].infer())
  296. self.assertIsInstance(second_unbound, nodes.FunctionDef)
  297. self.assertEqual(second_unbound.name, 'test')
  298. self.assertEqual(second_unbound.parent.name, 'First')
  299. def test_super_invalid_mro(self):
  300. node = builder.extract_node('''
  301. class A(object):
  302. test = 42
  303. class Super(A, A):
  304. def __init__(self):
  305. super(Super, self) #@
  306. ''')
  307. inferred = next(node.infer())
  308. with self.assertRaises(exceptions.AttributeInferenceError):
  309. next(inferred.getattr('test'))
  310. def test_super_complex_mro(self):
  311. ast_nodes = builder.extract_node('''
  312. class A(object):
  313. def spam(self): return "A"
  314. def foo(self): return "A"
  315. @staticmethod
  316. def static(self): pass
  317. class B(A):
  318. def boo(self): return "B"
  319. def spam(self): return "B"
  320. class C(A):
  321. def boo(self): return "C"
  322. class E(C, B):
  323. def __init__(self):
  324. super(E, self).boo #@
  325. super(C, self).boo #@
  326. super(E, self).spam #@
  327. super(E, self).foo #@
  328. super(E, self).static #@
  329. ''')
  330. first = next(ast_nodes[0].infer())
  331. self.assertIsInstance(first, bases.BoundMethod)
  332. self.assertEqual(first.bound.name, 'C')
  333. second = next(ast_nodes[1].infer())
  334. self.assertIsInstance(second, bases.BoundMethod)
  335. self.assertEqual(second.bound.name, 'B')
  336. third = next(ast_nodes[2].infer())
  337. self.assertIsInstance(third, bases.BoundMethod)
  338. self.assertEqual(third.bound.name, 'B')
  339. fourth = next(ast_nodes[3].infer())
  340. self.assertEqual(fourth.bound.name, 'A')
  341. static = next(ast_nodes[4].infer())
  342. self.assertIsInstance(static, nodes.FunctionDef)
  343. self.assertEqual(static.parent.scope().name, 'A')
  344. def test_super_data_model(self):
  345. ast_nodes = builder.extract_node('''
  346. class X(object): pass
  347. class A(X):
  348. def __init__(self):
  349. super(A, self) #@
  350. super(A, A) #@
  351. super(X, A) #@
  352. ''')
  353. first = next(ast_nodes[0].infer())
  354. thisclass = first.getattr('__thisclass__')[0]
  355. self.assertIsInstance(thisclass, nodes.ClassDef)
  356. self.assertEqual(thisclass.name, 'A')
  357. selfclass = first.getattr('__self_class__')[0]
  358. self.assertIsInstance(selfclass, nodes.ClassDef)
  359. self.assertEqual(selfclass.name, 'A')
  360. self_ = first.getattr('__self__')[0]
  361. self.assertIsInstance(self_, bases.Instance)
  362. self.assertEqual(self_.name, 'A')
  363. cls = first.getattr('__class__')[0]
  364. self.assertEqual(cls, first._proxied)
  365. second = next(ast_nodes[1].infer())
  366. thisclass = second.getattr('__thisclass__')[0]
  367. self.assertEqual(thisclass.name, 'A')
  368. self_ = second.getattr('__self__')[0]
  369. self.assertIsInstance(self_, nodes.ClassDef)
  370. self.assertEqual(self_.name, 'A')
  371. third = next(ast_nodes[2].infer())
  372. thisclass = third.getattr('__thisclass__')[0]
  373. self.assertEqual(thisclass.name, 'X')
  374. selfclass = third.getattr('__self_class__')[0]
  375. self.assertEqual(selfclass.name, 'A')
  376. def assertEqualMro(self, klass, expected_mro):
  377. self.assertEqual(
  378. [member.name for member in klass.super_mro()],
  379. expected_mro)
  380. def test_super_mro(self):
  381. ast_nodes = builder.extract_node('''
  382. class A(object): pass
  383. class B(A): pass
  384. class C(A): pass
  385. class E(C, B):
  386. def __init__(self):
  387. super(E, self) #@
  388. super(C, self) #@
  389. super(B, self) #@
  390. super(B, 1) #@
  391. super(1, B) #@
  392. ''')
  393. first = next(ast_nodes[0].infer())
  394. self.assertEqualMro(first, ['C', 'B', 'A', 'object'])
  395. second = next(ast_nodes[1].infer())
  396. self.assertEqualMro(second, ['B', 'A', 'object'])
  397. third = next(ast_nodes[2].infer())
  398. self.assertEqualMro(third, ['A', 'object'])
  399. fourth = next(ast_nodes[3].infer())
  400. with self.assertRaises(exceptions.SuperError):
  401. fourth.super_mro()
  402. fifth = next(ast_nodes[4].infer())
  403. with self.assertRaises(exceptions.SuperError):
  404. fifth.super_mro()
  405. def test_super_yes_objects(self):
  406. ast_nodes = builder.extract_node('''
  407. from collections import Missing
  408. class A(object):
  409. def __init__(self):
  410. super(Missing, self) #@
  411. super(A, Missing) #@
  412. ''')
  413. first = next(ast_nodes[0].infer())
  414. self.assertIsInstance(first, bases.Instance)
  415. second = next(ast_nodes[1].infer())
  416. self.assertIsInstance(second, bases.Instance)
  417. def test_super_invalid_types(self):
  418. node = builder.extract_node('''
  419. import collections
  420. class A(object):
  421. def __init__(self):
  422. super(A, collections) #@
  423. ''')
  424. inferred = next(node.infer())
  425. with self.assertRaises(exceptions.SuperError):
  426. inferred.super_mro()
  427. with self.assertRaises(exceptions.SuperError):
  428. inferred.super_mro()
  429. def test_super_properties(self):
  430. node = builder.extract_node('''
  431. class Foo(object):
  432. @property
  433. def dict(self):
  434. return 42
  435. class Bar(Foo):
  436. @property
  437. def dict(self):
  438. return super(Bar, self).dict
  439. Bar().dict
  440. ''')
  441. inferred = next(node.infer())
  442. self.assertIsInstance(inferred, nodes.Const)
  443. self.assertEqual(inferred.value, 42)
  444. if __name__ == '__main__':
  445. unittest.main()