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_nodes.py 30KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862
  1. # Copyright (c) 2006-2007, 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
  2. # Copyright (c) 2013-2016 Claudiu Popa <pcmanticore@gmail.com>
  3. # Copyright (c) 2014 Google, Inc.
  4. # Copyright (c) 2015 Florian Bruhin <me@the-compiler.org>
  5. # Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com>
  6. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  7. # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
  8. """tests for specific behaviour of astroid nodes
  9. """
  10. import os
  11. import sys
  12. import textwrap
  13. import unittest
  14. import warnings
  15. import six
  16. import astroid
  17. from astroid import bases
  18. from astroid import builder
  19. from astroid import context as contextmod
  20. from astroid import exceptions
  21. from astroid import node_classes
  22. from astroid import nodes
  23. from astroid import parse
  24. from astroid import util
  25. from astroid import test_utils
  26. from astroid import transforms
  27. from astroid.tests import resources
  28. abuilder = builder.AstroidBuilder()
  29. BUILTINS = six.moves.builtins.__name__
  30. class AsStringTest(resources.SysPathSetup, unittest.TestCase):
  31. def test_tuple_as_string(self):
  32. def build(string):
  33. return abuilder.string_build(string).body[0].value
  34. self.assertEqual(build('1,').as_string(), '(1, )')
  35. self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)')
  36. self.assertEqual(build('(1, )').as_string(), '(1, )')
  37. self.assertEqual(build('1, 2, 3').as_string(), '(1, 2, 3)')
  38. @test_utils.require_version(minver='3.0')
  39. def test_func_signature_issue_185(self):
  40. code = textwrap.dedent('''
  41. def test(a, b, c=42, *, x=42, **kwargs):
  42. print(a, b, c, args)
  43. ''')
  44. node = parse(code)
  45. self.assertEqual(node.as_string().strip(), code.strip())
  46. def test_as_string_for_list_containing_uninferable(self):
  47. node = builder.extract_node('''
  48. def foo():
  49. bar = [arg] * 1
  50. ''')
  51. binop = node.body[0].value
  52. inferred = next(binop.infer())
  53. self.assertEqual(inferred.as_string(), '[Uninferable]')
  54. self.assertEqual(binop.as_string(), '([arg]) * (1)')
  55. def test_frozenset_as_string(self):
  56. ast_nodes = builder.extract_node('''
  57. frozenset((1, 2, 3)) #@
  58. frozenset({1, 2, 3}) #@
  59. frozenset([1, 2, 3,]) #@
  60. frozenset(None) #@
  61. frozenset(1) #@
  62. ''')
  63. ast_nodes = [next(node.infer()) for node in ast_nodes]
  64. self.assertEqual(ast_nodes[0].as_string(), 'frozenset((1, 2, 3))')
  65. self.assertEqual(ast_nodes[1].as_string(), 'frozenset({1, 2, 3})')
  66. self.assertEqual(ast_nodes[2].as_string(), 'frozenset([1, 2, 3])')
  67. self.assertNotEqual(ast_nodes[3].as_string(), 'frozenset(None)')
  68. self.assertNotEqual(ast_nodes[4].as_string(), 'frozenset(1)')
  69. def test_varargs_kwargs_as_string(self):
  70. ast = abuilder.string_build('raise_string(*args, **kwargs)').body[0]
  71. self.assertEqual(ast.as_string(), 'raise_string(*args, **kwargs)')
  72. def test_module_as_string(self):
  73. """check as_string on a whole module prepared to be returned identically
  74. """
  75. module = resources.build_file('data/module.py', 'data.module')
  76. with open(resources.find('data/module.py'), 'r') as fobj:
  77. self.assertMultiLineEqual(module.as_string(), fobj.read())
  78. def test_module2_as_string(self):
  79. """check as_string on a whole module prepared to be returned identically
  80. """
  81. module2 = resources.build_file('data/module2.py', 'data.module2')
  82. with open(resources.find('data/module2.py'), 'r') as fobj:
  83. self.assertMultiLineEqual(module2.as_string(), fobj.read())
  84. def test_as_string(self):
  85. """check as_string for python syntax >= 2.7"""
  86. code = '''one_two = {1, 2}
  87. b = {v: k for (k, v) in enumerate('string')}
  88. cdd = {k for k in b}\n\n'''
  89. ast = abuilder.string_build(code)
  90. self.assertMultiLineEqual(ast.as_string(), code)
  91. @test_utils.require_version('3.0')
  92. def test_3k_as_string(self):
  93. """check as_string for python 3k syntax"""
  94. code = '''print()
  95. def function(var):
  96. nonlocal counter
  97. try:
  98. hello
  99. except NameError as nexc:
  100. (*hell, o) = b'hello'
  101. raise AttributeError from nexc
  102. \n'''
  103. ast = abuilder.string_build(code)
  104. self.assertEqual(ast.as_string(), code)
  105. @test_utils.require_version('3.0')
  106. @unittest.expectedFailure
  107. def test_3k_annotations_and_metaclass(self):
  108. code_annotations = textwrap.dedent('''
  109. def function(var:int):
  110. nonlocal counter
  111. class Language(metaclass=Natural):
  112. """natural language"""
  113. ''')
  114. ast = abuilder.string_build(code_annotations)
  115. self.assertEqual(ast.as_string(), code_annotations)
  116. def test_ellipsis(self):
  117. ast = abuilder.string_build('a[...]').body[0]
  118. self.assertEqual(ast.as_string(), 'a[...]')
  119. def test_slices(self):
  120. for code in ('a[0]', 'a[1:3]', 'a[:-1:step]', 'a[:,newaxis]',
  121. 'a[newaxis,:]', 'del L[::2]', 'del A[1]', 'del Br[:]'):
  122. ast = abuilder.string_build(code).body[0]
  123. self.assertEqual(ast.as_string(), code)
  124. def test_slice_and_subscripts(self):
  125. code = """a[:1] = bord[2:]
  126. a[:1] = bord[2:]
  127. del bree[3:d]
  128. bord[2:]
  129. del av[d::f], a[df:]
  130. a[:1] = bord[2:]
  131. del SRC[::1,newaxis,1:]
  132. tous[vals] = 1010
  133. del thousand[key]
  134. del a[::2], a[:-1:step]
  135. del Fee.form[left:]
  136. aout.vals = miles.of_stuff
  137. del (ccok, (name.thing, foo.attrib.value)), Fee.form[left:]
  138. if all[1] == bord[0:]:
  139. pass\n\n"""
  140. ast = abuilder.string_build(code)
  141. self.assertEqual(ast.as_string(), code)
  142. class _NodeTest(unittest.TestCase):
  143. """test transformation of If Node"""
  144. CODE = None
  145. @property
  146. def astroid(self):
  147. try:
  148. return self.__class__.__dict__['CODE_Astroid']
  149. except KeyError:
  150. module = builder.parse(self.CODE)
  151. self.__class__.CODE_Astroid = module
  152. return module
  153. class IfNodeTest(_NodeTest):
  154. """test transformation of If Node"""
  155. CODE = """
  156. if 0:
  157. print()
  158. if True:
  159. print()
  160. else:
  161. pass
  162. if "":
  163. print()
  164. elif []:
  165. raise
  166. if 1:
  167. print()
  168. elif True:
  169. print()
  170. elif func():
  171. pass
  172. else:
  173. raise
  174. """
  175. def test_if_elif_else_node(self):
  176. """test transformation for If node"""
  177. self.assertEqual(len(self.astroid.body), 4)
  178. for stmt in self.astroid.body:
  179. self.assertIsInstance(stmt, nodes.If)
  180. self.assertFalse(self.astroid.body[0].orelse) # simple If
  181. self.assertIsInstance(self.astroid.body[1].orelse[0], nodes.Pass) # If / else
  182. self.assertIsInstance(self.astroid.body[2].orelse[0], nodes.If) # If / elif
  183. self.assertIsInstance(self.astroid.body[3].orelse[0].orelse[0], nodes.If)
  184. def test_block_range(self):
  185. # XXX ensure expected values
  186. self.assertEqual(self.astroid.block_range(1), (0, 22))
  187. self.assertEqual(self.astroid.block_range(10), (0, 22)) # XXX (10, 22) ?
  188. self.assertEqual(self.astroid.body[1].block_range(5), (5, 6))
  189. self.assertEqual(self.astroid.body[1].block_range(6), (6, 6))
  190. self.assertEqual(self.astroid.body[1].orelse[0].block_range(7), (7, 8))
  191. self.assertEqual(self.astroid.body[1].orelse[0].block_range(8), (8, 8))
  192. class TryExceptNodeTest(_NodeTest):
  193. CODE = """
  194. try:
  195. print ('pouet')
  196. except IOError:
  197. pass
  198. except UnicodeError:
  199. print()
  200. else:
  201. print()
  202. """
  203. def test_block_range(self):
  204. # XXX ensure expected values
  205. self.assertEqual(self.astroid.body[0].block_range(1), (1, 8))
  206. self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
  207. self.assertEqual(self.astroid.body[0].block_range(3), (3, 8))
  208. self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
  209. self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
  210. self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
  211. self.assertEqual(self.astroid.body[0].block_range(7), (7, 7))
  212. self.assertEqual(self.astroid.body[0].block_range(8), (8, 8))
  213. class TryFinallyNodeTest(_NodeTest):
  214. CODE = """
  215. try:
  216. print ('pouet')
  217. finally:
  218. print ('pouet')
  219. """
  220. def test_block_range(self):
  221. # XXX ensure expected values
  222. self.assertEqual(self.astroid.body[0].block_range(1), (1, 4))
  223. self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
  224. self.assertEqual(self.astroid.body[0].block_range(3), (3, 4))
  225. self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
  226. class TryExceptFinallyNodeTest(_NodeTest):
  227. CODE = """
  228. try:
  229. print('pouet')
  230. except Exception:
  231. print ('oops')
  232. finally:
  233. print ('pouet')
  234. """
  235. def test_block_range(self):
  236. # XXX ensure expected values
  237. self.assertEqual(self.astroid.body[0].block_range(1), (1, 6))
  238. self.assertEqual(self.astroid.body[0].block_range(2), (2, 2))
  239. self.assertEqual(self.astroid.body[0].block_range(3), (3, 4))
  240. self.assertEqual(self.astroid.body[0].block_range(4), (4, 4))
  241. self.assertEqual(self.astroid.body[0].block_range(5), (5, 5))
  242. self.assertEqual(self.astroid.body[0].block_range(6), (6, 6))
  243. @unittest.skipIf(six.PY3, "Python 2 specific test.")
  244. class TryExcept2xNodeTest(_NodeTest):
  245. CODE = """
  246. try:
  247. hello
  248. except AttributeError, (retval, desc):
  249. pass
  250. """
  251. def test_tuple_attribute(self):
  252. handler = self.astroid.body[0].handlers[0]
  253. self.assertIsInstance(handler.name, nodes.Tuple)
  254. class ImportNodeTest(resources.SysPathSetup, unittest.TestCase):
  255. def setUp(self):
  256. super(ImportNodeTest, self).setUp()
  257. self.module = resources.build_file('data/module.py', 'data.module')
  258. self.module2 = resources.build_file('data/module2.py', 'data.module2')
  259. def test_import_self_resolve(self):
  260. myos = next(self.module2.igetattr('myos'))
  261. self.assertTrue(isinstance(myos, nodes.Module), myos)
  262. self.assertEqual(myos.name, 'os')
  263. self.assertEqual(myos.qname(), 'os')
  264. self.assertEqual(myos.pytype(), '%s.module' % BUILTINS)
  265. def test_from_self_resolve(self):
  266. namenode = next(self.module.igetattr('NameNode'))
  267. self.assertTrue(isinstance(namenode, nodes.ClassDef), namenode)
  268. self.assertEqual(namenode.root().name, 'astroid.node_classes')
  269. self.assertEqual(namenode.qname(), 'astroid.node_classes.Name')
  270. self.assertEqual(namenode.pytype(), '%s.type' % BUILTINS)
  271. abspath = next(self.module2.igetattr('abspath'))
  272. self.assertTrue(isinstance(abspath, nodes.FunctionDef), abspath)
  273. self.assertEqual(abspath.root().name, 'os.path')
  274. self.assertEqual(abspath.qname(), 'os.path.abspath')
  275. self.assertEqual(abspath.pytype(), '%s.function' % BUILTINS)
  276. def test_real_name(self):
  277. from_ = self.module['NameNode']
  278. self.assertEqual(from_.real_name('NameNode'), 'Name')
  279. imp_ = self.module['os']
  280. self.assertEqual(imp_.real_name('os'), 'os')
  281. self.assertRaises(exceptions.AttributeInferenceError, imp_.real_name, 'os.path')
  282. imp_ = self.module['NameNode']
  283. self.assertEqual(imp_.real_name('NameNode'), 'Name')
  284. self.assertRaises(exceptions.AttributeInferenceError, imp_.real_name, 'Name')
  285. imp_ = self.module2['YO']
  286. self.assertEqual(imp_.real_name('YO'), 'YO')
  287. self.assertRaises(exceptions.AttributeInferenceError, imp_.real_name, 'data')
  288. def test_as_string(self):
  289. ast = self.module['modutils']
  290. self.assertEqual(ast.as_string(), "from astroid import modutils")
  291. ast = self.module['NameNode']
  292. self.assertEqual(ast.as_string(), "from astroid.node_classes import Name as NameNode")
  293. ast = self.module['os']
  294. self.assertEqual(ast.as_string(), "import os.path")
  295. code = """from . import here
  296. from .. import door
  297. from .store import bread
  298. from ..cave import wine\n\n"""
  299. ast = abuilder.string_build(code)
  300. self.assertMultiLineEqual(ast.as_string(), code)
  301. def test_bad_import_inference(self):
  302. # Explication of bug
  303. '''When we import PickleError from nonexistent, a call to the infer
  304. method of this From node will be made by unpack_infer.
  305. inference.infer_from will try to import this module, which will fail and
  306. raise a InferenceException (by mixins.do_import_module). The infer_name
  307. will catch this exception and yield and Uninferable instead.
  308. '''
  309. code = '''
  310. try:
  311. from pickle import PickleError
  312. except ImportError:
  313. from nonexistent import PickleError
  314. try:
  315. pass
  316. except PickleError:
  317. pass
  318. '''
  319. module = builder.parse(code)
  320. handler_type = module.body[1].handlers[0].type
  321. excs = list(node_classes.unpack_infer(handler_type))
  322. # The number of returned object can differ on Python 2
  323. # and Python 3. In one version, an additional item will
  324. # be returned, from the _pickle module, which is not
  325. # present in the other version.
  326. self.assertIsInstance(excs[0], nodes.ClassDef)
  327. self.assertEqual(excs[0].name, 'PickleError')
  328. self.assertIs(excs[-1], util.Uninferable)
  329. def test_absolute_import(self):
  330. module = resources.build_file('data/absimport.py')
  331. ctx = contextmod.InferenceContext()
  332. # will fail if absolute import failed
  333. ctx.lookupname = 'message'
  334. next(module['message'].infer(ctx))
  335. ctx.lookupname = 'email'
  336. m = next(module['email'].infer(ctx))
  337. self.assertFalse(m.file.startswith(os.path.join('data', 'email.py')))
  338. def test_more_absolute_import(self):
  339. module = resources.build_file('data/module1abs/__init__.py', 'data.module1abs')
  340. self.assertIn('sys', module.locals)
  341. class CmpNodeTest(unittest.TestCase):
  342. def test_as_string(self):
  343. ast = abuilder.string_build("a == 2").body[0]
  344. self.assertEqual(ast.as_string(), "a == 2")
  345. class ConstNodeTest(unittest.TestCase):
  346. def _test(self, value):
  347. # pylint: disable=no-member; union type in const_factory, this shouldn't happen
  348. node = nodes.const_factory(value)
  349. self.assertIsInstance(node._proxied, nodes.ClassDef)
  350. self.assertEqual(node._proxied.name, value.__class__.__name__)
  351. self.assertIs(node.value, value)
  352. self.assertTrue(node._proxied.parent)
  353. self.assertEqual(node._proxied.root().name, value.__class__.__module__)
  354. def test_none(self):
  355. self._test(None)
  356. def test_bool(self):
  357. self._test(True)
  358. def test_int(self):
  359. self._test(1)
  360. def test_float(self):
  361. self._test(1.0)
  362. def test_complex(self):
  363. self._test(1.0j)
  364. def test_str(self):
  365. self._test('a')
  366. def test_unicode(self):
  367. self._test(u'a')
  368. class NameNodeTest(unittest.TestCase):
  369. def test_assign_to_True(self):
  370. """test that True and False assignments don't crash"""
  371. code = """
  372. True = False
  373. def hello(False):
  374. pass
  375. del True
  376. """
  377. if sys.version_info >= (3, 0):
  378. with self.assertRaises(exceptions.AstroidBuildingError):
  379. builder.parse(code)
  380. else:
  381. ast = builder.parse(code)
  382. assign_true = ast['True']
  383. self.assertIsInstance(assign_true, nodes.AssignName)
  384. self.assertEqual(assign_true.name, "True")
  385. del_true = ast.body[2].targets[0]
  386. self.assertIsInstance(del_true, nodes.DelName)
  387. self.assertEqual(del_true.name, "True")
  388. class AnnAssignNodeTest(unittest.TestCase):
  389. @test_utils.require_version(minver='3.6')
  390. def test_primitive(self):
  391. code = textwrap.dedent("""
  392. test: int = 5
  393. """)
  394. assign = builder.extract_node(code)
  395. self.assertIsInstance(assign, nodes.AnnAssign)
  396. self.assertEqual(assign.target.name, "test")
  397. self.assertEqual(assign.annotation.name, "int")
  398. self.assertEqual(assign.value.value, 5)
  399. self.assertEqual(assign.simple, 1)
  400. @test_utils.require_version(minver='3.6')
  401. def test_primitive_without_initial_value(self):
  402. code = textwrap.dedent("""
  403. test: str
  404. """)
  405. assign = builder.extract_node(code)
  406. self.assertIsInstance(assign, nodes.AnnAssign)
  407. self.assertEqual(assign.target.name, "test")
  408. self.assertEqual(assign.annotation.name, "str")
  409. self.assertEqual(assign.value, None)
  410. @test_utils.require_version(minver='3.6')
  411. def test_complex(self):
  412. code = textwrap.dedent("""
  413. test: Dict[List[str]] = {}
  414. """)
  415. assign = builder.extract_node(code)
  416. self.assertIsInstance(assign, nodes.AnnAssign)
  417. self.assertEqual(assign.target.name, "test")
  418. self.assertIsInstance(assign.annotation, astroid.Subscript)
  419. self.assertIsInstance(assign.value, astroid.Dict)
  420. @test_utils.require_version(minver='3.6')
  421. def test_as_string(self):
  422. code = textwrap.dedent("""
  423. print()
  424. test: int = 5
  425. test2: str
  426. test3: List[Dict[(str, str)]] = []
  427. """)
  428. ast = abuilder.string_build(code)
  429. self.assertEqual(ast.as_string().strip(), code.strip())
  430. class ArgumentsNodeTC(unittest.TestCase):
  431. def test_linenumbering(self):
  432. ast = builder.parse('''
  433. def func(a,
  434. b): pass
  435. x = lambda x: None
  436. ''')
  437. self.assertEqual(ast['func'].args.fromlineno, 2)
  438. self.assertFalse(ast['func'].args.is_statement)
  439. xlambda = next(ast['x'].infer())
  440. self.assertEqual(xlambda.args.fromlineno, 4)
  441. self.assertEqual(xlambda.args.tolineno, 4)
  442. self.assertFalse(xlambda.args.is_statement)
  443. if sys.version_info < (3, 0):
  444. self.assertEqual(ast['func'].args.tolineno, 3)
  445. else:
  446. self.skipTest('FIXME http://bugs.python.org/issue10445 '
  447. '(no line number on function args)')
  448. @test_utils.require_version(minver='3.0')
  449. def test_kwoargs(self):
  450. ast = builder.parse('''
  451. def func(*, x):
  452. pass
  453. ''')
  454. args = ast['func'].args
  455. self.assertTrue(args.is_argument('x'))
  456. class UnboundMethodNodeTest(unittest.TestCase):
  457. def test_no_super_getattr(self):
  458. # This is a test for issue
  459. # https://bitbucket.org/logilab/astroid/issue/91, which tests
  460. # that UnboundMethod doesn't call super when doing .getattr.
  461. ast = builder.parse('''
  462. class A(object):
  463. def test(self):
  464. pass
  465. meth = A.test
  466. ''')
  467. node = next(ast['meth'].infer())
  468. with self.assertRaises(exceptions.AttributeInferenceError):
  469. node.getattr('__missssing__')
  470. name = node.getattr('__name__')[0]
  471. self.assertIsInstance(name, nodes.Const)
  472. self.assertEqual(name.value, 'test')
  473. class BoundMethodNodeTest(unittest.TestCase):
  474. def test_is_property(self):
  475. ast = builder.parse('''
  476. import abc
  477. def cached_property():
  478. # Not a real decorator, but we don't care
  479. pass
  480. def reify():
  481. # Same as cached_property
  482. pass
  483. def lazy_property():
  484. pass
  485. def lazyproperty():
  486. pass
  487. def lazy(): pass
  488. class A(object):
  489. @property
  490. def builtin_property(self):
  491. return 42
  492. @abc.abstractproperty
  493. def abc_property(self):
  494. return 42
  495. @cached_property
  496. def cached_property(self): return 42
  497. @reify
  498. def reified(self): return 42
  499. @lazy_property
  500. def lazy_prop(self): return 42
  501. @lazyproperty
  502. def lazyprop(self): return 42
  503. def not_prop(self): pass
  504. @lazy
  505. def decorated_with_lazy(self): return 42
  506. cls = A()
  507. builtin_property = cls.builtin_property
  508. abc_property = cls.abc_property
  509. cached_p = cls.cached_property
  510. reified = cls.reified
  511. not_prop = cls.not_prop
  512. lazy_prop = cls.lazy_prop
  513. lazyprop = cls.lazyprop
  514. decorated_with_lazy = cls.decorated_with_lazy
  515. ''')
  516. for prop in ('builtin_property', 'abc_property', 'cached_p', 'reified',
  517. 'lazy_prop', 'lazyprop', 'decorated_with_lazy'):
  518. inferred = next(ast[prop].infer())
  519. self.assertIsInstance(inferred, nodes.Const, prop)
  520. self.assertEqual(inferred.value, 42, prop)
  521. inferred = next(ast['not_prop'].infer())
  522. self.assertIsInstance(inferred, bases.BoundMethod)
  523. class AliasesTest(unittest.TestCase):
  524. def setUp(self):
  525. self.transformer = transforms.TransformVisitor()
  526. def parse_transform(self, code):
  527. module = parse(code, apply_transforms=False)
  528. return self.transformer.visit(module)
  529. def test_aliases(self):
  530. def test_from(node):
  531. node.names = node.names + [('absolute_import', None)]
  532. return node
  533. def test_class(node):
  534. node.name = 'Bar'
  535. return node
  536. def test_function(node):
  537. node.name = 'another_test'
  538. return node
  539. def test_callfunc(node):
  540. if node.func.name == 'Foo':
  541. node.func.name = 'Bar'
  542. return node
  543. return None
  544. def test_assname(node):
  545. if node.name == 'foo':
  546. return nodes.AssignName('bar', node.lineno, node.col_offset,
  547. node.parent)
  548. return None
  549. def test_assattr(node):
  550. if node.attrname == 'a':
  551. node.attrname = 'b'
  552. return node
  553. return None
  554. def test_getattr(node):
  555. if node.attrname == 'a':
  556. node.attrname = 'b'
  557. return node
  558. return None
  559. def test_genexpr(node):
  560. if node.elt.value == 1:
  561. node.elt = nodes.Const(2, node.lineno, node.col_offset,
  562. node.parent)
  563. return node
  564. return None
  565. self.transformer.register_transform(nodes.From, test_from)
  566. self.transformer.register_transform(nodes.Class, test_class)
  567. self.transformer.register_transform(nodes.Function, test_function)
  568. self.transformer.register_transform(nodes.CallFunc, test_callfunc)
  569. self.transformer.register_transform(nodes.AssName, test_assname)
  570. self.transformer.register_transform(nodes.AssAttr, test_assattr)
  571. self.transformer.register_transform(nodes.Getattr, test_getattr)
  572. self.transformer.register_transform(nodes.GenExpr, test_genexpr)
  573. string = '''
  574. from __future__ import print_function
  575. class Foo: pass
  576. def test(a): return a
  577. foo = Foo()
  578. foo.a = test(42)
  579. foo.a
  580. (1 for _ in range(0, 42))
  581. '''
  582. module = self.parse_transform(string)
  583. self.assertEqual(len(module.body[0].names), 2)
  584. self.assertIsInstance(module.body[0], nodes.ImportFrom)
  585. self.assertEqual(module.body[1].name, 'Bar')
  586. self.assertIsInstance(module.body[1], nodes.ClassDef)
  587. self.assertEqual(module.body[2].name, 'another_test')
  588. self.assertIsInstance(module.body[2], nodes.FunctionDef)
  589. self.assertEqual(module.body[3].targets[0].name, 'bar')
  590. self.assertIsInstance(module.body[3].targets[0], nodes.AssignName)
  591. self.assertEqual(module.body[3].value.func.name, 'Bar')
  592. self.assertIsInstance(module.body[3].value, nodes.Call)
  593. self.assertEqual(module.body[4].targets[0].attrname, 'b')
  594. self.assertIsInstance(module.body[4].targets[0], nodes.AssignAttr)
  595. self.assertIsInstance(module.body[5], nodes.Expr)
  596. self.assertEqual(module.body[5].value.attrname, 'b')
  597. self.assertIsInstance(module.body[5].value, nodes.Attribute)
  598. self.assertEqual(module.body[6].value.elt.value, 2)
  599. self.assertIsInstance(module.body[6].value, nodes.GeneratorExp)
  600. @unittest.skipIf(six.PY3, "Python 3 doesn't have Repr nodes.")
  601. def test_repr(self):
  602. def test_backquote(node):
  603. node.value.name = 'bar'
  604. return node
  605. self.transformer.register_transform(nodes.Backquote, test_backquote)
  606. module = self.parse_transform('`foo`')
  607. self.assertEqual(module.body[0].value.value.name, 'bar')
  608. self.assertIsInstance(module.body[0].value, nodes.Repr)
  609. class DeprecationWarningsTest(unittest.TestCase):
  610. def test_asstype_warnings(self):
  611. string = '''
  612. class C: pass
  613. c = C()
  614. with warnings.catch_warnings(record=True) as w:
  615. pass
  616. '''
  617. module = parse(string)
  618. filter_stmts_mixin = module.body[0]
  619. assign_type_mixin = module.body[1].targets[0]
  620. parent_assign_type_mixin = module.body[2]
  621. with warnings.catch_warnings(record=True) as w:
  622. with test_utils.enable_warning(PendingDeprecationWarning):
  623. filter_stmts_mixin.ass_type()
  624. self.assertIsInstance(w[0].message, PendingDeprecationWarning)
  625. with warnings.catch_warnings(record=True) as w:
  626. with test_utils.enable_warning(PendingDeprecationWarning):
  627. assign_type_mixin.ass_type()
  628. self.assertIsInstance(w[0].message, PendingDeprecationWarning)
  629. with warnings.catch_warnings(record=True) as w:
  630. with test_utils.enable_warning(PendingDeprecationWarning):
  631. parent_assign_type_mixin.ass_type()
  632. self.assertIsInstance(w[0].message, PendingDeprecationWarning)
  633. def test_isinstance_warnings(self):
  634. msg_format = ("%r is deprecated and slated for removal in astroid "
  635. "2.0, use %r instead")
  636. for cls in (nodes.Discard, nodes.Backquote, nodes.AssName,
  637. nodes.AssAttr, nodes.Getattr, nodes.CallFunc, nodes.From):
  638. with warnings.catch_warnings(record=True) as w:
  639. with test_utils.enable_warning(PendingDeprecationWarning):
  640. isinstance(42, cls)
  641. self.assertIsInstance(w[0].message, PendingDeprecationWarning)
  642. actual_msg = msg_format % (cls.__class__.__name__, cls.__wrapped__.__name__)
  643. self.assertEqual(str(w[0].message), actual_msg)
  644. @test_utils.require_version('3.5')
  645. class Python35AsyncTest(unittest.TestCase):
  646. def test_async_await_keywords(self):
  647. async_def, async_for, async_with, await_node = builder.extract_node('''
  648. async def func(): #@
  649. async for i in range(10): #@
  650. f = __(await i)
  651. async with test(): #@
  652. pass
  653. ''')
  654. self.assertIsInstance(async_def, nodes.AsyncFunctionDef)
  655. self.assertIsInstance(async_for, nodes.AsyncFor)
  656. self.assertIsInstance(async_with, nodes.AsyncWith)
  657. self.assertIsInstance(await_node, nodes.Await)
  658. self.assertIsInstance(await_node.value, nodes.Name)
  659. def _test_await_async_as_string(self, code):
  660. ast_node = parse(code)
  661. self.assertEqual(ast_node.as_string().strip(), code.strip())
  662. def test_await_as_string(self):
  663. code = textwrap.dedent('''
  664. async def function():
  665. await 42
  666. ''')
  667. self._test_await_async_as_string(code)
  668. def test_asyncwith_as_string(self):
  669. code = textwrap.dedent('''
  670. async def function():
  671. async with (42):
  672. pass
  673. ''')
  674. self._test_await_async_as_string(code)
  675. def test_asyncfor_as_string(self):
  676. code = textwrap.dedent('''
  677. async def function():
  678. async for i in range(10):
  679. await 42
  680. ''')
  681. self._test_await_async_as_string(code)
  682. class ContextTest(unittest.TestCase):
  683. def test_subscript_load(self):
  684. node = builder.extract_node('f[1]')
  685. self.assertIs(node.ctx, astroid.Load)
  686. def test_subscript_del(self):
  687. node = builder.extract_node('del f[1]')
  688. self.assertIs(node.targets[0].ctx, astroid.Del)
  689. def test_subscript_store(self):
  690. node = builder.extract_node('f[1] = 2')
  691. subscript = node.targets[0]
  692. self.assertIs(subscript.ctx, astroid.Store)
  693. def test_list_load(self):
  694. node = builder.extract_node('[]')
  695. self.assertIs(node.ctx, astroid.Load)
  696. def test_list_del(self):
  697. node = builder.extract_node('del []')
  698. self.assertIs(node.targets[0].ctx, astroid.Del)
  699. def test_list_store(self):
  700. with self.assertRaises(exceptions.AstroidSyntaxError):
  701. builder.extract_node('[0] = 2')
  702. def test_tuple_load(self):
  703. node = builder.extract_node('(1, )')
  704. self.assertIs(node.ctx, astroid.Load)
  705. def test_tuple_store(self):
  706. with self.assertRaises(exceptions.AstroidSyntaxError):
  707. builder.extract_node('(1, ) = 3')
  708. @test_utils.require_version(minver='3.5')
  709. def test_starred_load(self):
  710. node = builder.extract_node('a = *b')
  711. starred = node.value
  712. self.assertIs(starred.ctx, astroid.Load)
  713. @test_utils.require_version(minver='3.0')
  714. def test_starred_store(self):
  715. node = builder.extract_node('a, *b = 1, 2')
  716. starred = node.targets[0].elts[1]
  717. self.assertIs(starred.ctx, astroid.Store)
  718. if __name__ == '__main__':
  719. unittest.main()