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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890
  1. # Copyright (c) 2013-2014 Google, Inc.
  2. # Copyright (c) 2014-2016 Claudiu Popa <pcmanticore@gmail.com>
  3. # Copyright (c) 2015 Philip Lorenz <philip@bithub.de>
  4. # Copyright (c) 2015 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
  5. # Copyright (c) 2015 raylu <lurayl@gmail.com>
  6. # Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com>
  7. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  8. # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
  9. """Tests for basic functionality in astroid.brain."""
  10. try:
  11. import multiprocessing # pylint: disable=unused-import
  12. HAS_MULTIPROCESSING = True
  13. except ImportError:
  14. HAS_MULTIPROCESSING = False
  15. import sys
  16. import unittest
  17. try:
  18. import enum # pylint: disable=unused-import
  19. HAS_ENUM = True
  20. except ImportError:
  21. try:
  22. import enum34 as enum # pylint: disable=unused-import
  23. HAS_ENUM = True
  24. except ImportError:
  25. HAS_ENUM = False
  26. try:
  27. import nose # pylint: disable=unused-import
  28. HAS_NOSE = True
  29. except ImportError:
  30. HAS_NOSE = False
  31. try:
  32. import dateutil # pylint: disable=unused-import
  33. HAS_DATEUTIL = True
  34. except ImportError:
  35. HAS_DATEUTIL = False
  36. try:
  37. import pytest
  38. HAS_PYTEST = True
  39. except ImportError:
  40. HAS_PYTEST = False
  41. try:
  42. import attr as attr_module # pylint: disable=unused-import
  43. HAS_ATTR = True
  44. except ImportError:
  45. HAS_ATTR = False
  46. import six
  47. from astroid import MANAGER
  48. from astroid import bases
  49. from astroid import builder
  50. from astroid import nodes
  51. from astroid import util
  52. from astroid import test_utils
  53. import astroid
  54. class HashlibTest(unittest.TestCase):
  55. def test_hashlib(self):
  56. """Tests that brain extensions for hashlib work."""
  57. hashlib_module = MANAGER.ast_from_module_name('hashlib')
  58. for class_name in ['md5', 'sha1']:
  59. class_obj = hashlib_module[class_name]
  60. self.assertIn('update', class_obj)
  61. self.assertIn('digest', class_obj)
  62. self.assertIn('hexdigest', class_obj)
  63. self.assertIn('block_size', class_obj)
  64. self.assertIn('digest_size', class_obj)
  65. self.assertEqual(len(class_obj['__init__'].args.args), 2)
  66. self.assertEqual(len(class_obj['__init__'].args.defaults), 1)
  67. self.assertEqual(len(class_obj['update'].args.args), 2)
  68. self.assertEqual(len(class_obj['digest'].args.args), 1)
  69. self.assertEqual(len(class_obj['hexdigest'].args.args), 1)
  70. class CollectionsDequeTests(unittest.TestCase):
  71. def _inferred_queue_instance(self):
  72. node = builder.extract_node("""
  73. import collections
  74. q = collections.deque([])
  75. q
  76. """)
  77. return next(node.infer())
  78. def test_deque(self):
  79. inferred = self._inferred_queue_instance()
  80. self.assertTrue(inferred.getattr('__len__'))
  81. @test_utils.require_version(minver='3.5')
  82. def test_deque_py35methods(self):
  83. inferred = self._inferred_queue_instance()
  84. self.assertIn('copy', inferred.locals)
  85. self.assertIn('insert', inferred.locals)
  86. self.assertIn('index', inferred.locals)
  87. class NamedTupleTest(unittest.TestCase):
  88. def test_namedtuple_base(self):
  89. klass = builder.extract_node("""
  90. from collections import namedtuple
  91. class X(namedtuple("X", ["a", "b", "c"])):
  92. pass
  93. """)
  94. self.assertEqual(
  95. [anc.name for anc in klass.ancestors()],
  96. ['X', 'tuple', 'object'])
  97. for anc in klass.ancestors():
  98. self.assertFalse(anc.parent is None)
  99. def test_namedtuple_inference(self):
  100. klass = builder.extract_node("""
  101. from collections import namedtuple
  102. name = "X"
  103. fields = ["a", "b", "c"]
  104. class X(namedtuple(name, fields)):
  105. pass
  106. """)
  107. base = next(base for base in klass.ancestors()
  108. if base.name == 'X')
  109. self.assertSetEqual({"a", "b", "c"}, set(base.instance_attrs))
  110. def test_namedtuple_inference_failure(self):
  111. klass = builder.extract_node("""
  112. from collections import namedtuple
  113. def foo(fields):
  114. return __(namedtuple("foo", fields))
  115. """)
  116. self.assertIs(util.Uninferable, next(klass.infer()))
  117. def test_namedtuple_advanced_inference(self):
  118. # urlparse return an object of class ParseResult, which has a
  119. # namedtuple call and a mixin as base classes
  120. result = builder.extract_node("""
  121. import six
  122. result = __(six.moves.urllib.parse.urlparse('gopher://'))
  123. """)
  124. instance = next(result.infer())
  125. self.assertGreaterEqual(len(instance.getattr('scheme')), 1)
  126. self.assertGreaterEqual(len(instance.getattr('port')), 1)
  127. with self.assertRaises(astroid.AttributeInferenceError):
  128. instance.getattr('foo')
  129. self.assertGreaterEqual(len(instance.getattr('geturl')), 1)
  130. self.assertEqual(instance.name, 'ParseResult')
  131. def test_namedtuple_instance_attrs(self):
  132. result = builder.extract_node('''
  133. from collections import namedtuple
  134. namedtuple('a', 'a b c')(1, 2, 3) #@
  135. ''')
  136. inferred = next(result.infer())
  137. for name, attr in inferred.instance_attrs.items():
  138. self.assertEqual(attr[0].attrname, name)
  139. def test_namedtuple_uninferable_fields(self):
  140. node = builder.extract_node('''
  141. x = [A] * 2
  142. from collections import namedtuple
  143. l = namedtuple('a', x)
  144. l(1)
  145. ''')
  146. inferred = next(node.infer())
  147. self.assertIs(util.Uninferable, inferred)
  148. def test_namedtuple_access_class_fields(self):
  149. node = builder.extract_node("""
  150. from collections import namedtuple
  151. Tuple = namedtuple("Tuple", "field other")
  152. Tuple #@
  153. """)
  154. inferred = next(node.infer())
  155. self.assertIn('field', inferred.locals)
  156. self.assertIn('other', inferred.locals)
  157. def test_namedtuple_rename_keywords(self):
  158. node = builder.extract_node("""
  159. from collections import namedtuple
  160. Tuple = namedtuple("Tuple", "abc def", rename=True)
  161. Tuple #@
  162. """)
  163. inferred = next(node.infer())
  164. self.assertIn('abc', inferred.locals)
  165. self.assertIn('_1', inferred.locals)
  166. def test_namedtuple_rename_duplicates(self):
  167. node = builder.extract_node("""
  168. from collections import namedtuple
  169. Tuple = namedtuple("Tuple", "abc abc abc", rename=True)
  170. Tuple #@
  171. """)
  172. inferred = next(node.infer())
  173. self.assertIn('abc', inferred.locals)
  174. self.assertIn('_1', inferred.locals)
  175. self.assertIn('_2', inferred.locals)
  176. def test_namedtuple_rename_uninferable(self):
  177. node = builder.extract_node("""
  178. from collections import namedtuple
  179. Tuple = namedtuple("Tuple", "a b c", rename=UNINFERABLE)
  180. Tuple #@
  181. """)
  182. inferred = next(node.infer())
  183. self.assertIn('a', inferred.locals)
  184. self.assertIn('b', inferred.locals)
  185. self.assertIn('c', inferred.locals)
  186. def test_namedtuple_func_form(self):
  187. node = builder.extract_node("""
  188. from collections import namedtuple
  189. Tuple = namedtuple(typename="Tuple", field_names="a b c", rename=UNINFERABLE)
  190. Tuple #@
  191. """)
  192. inferred = next(node.infer())
  193. self.assertEqual(inferred.name, 'Tuple')
  194. self.assertIn('a', inferred.locals)
  195. self.assertIn('b', inferred.locals)
  196. self.assertIn('c', inferred.locals)
  197. def test_namedtuple_func_form_args_and_kwargs(self):
  198. node = builder.extract_node("""
  199. from collections import namedtuple
  200. Tuple = namedtuple("Tuple", field_names="a b c", rename=UNINFERABLE)
  201. Tuple #@
  202. """)
  203. inferred = next(node.infer())
  204. self.assertEqual(inferred.name, 'Tuple')
  205. self.assertIn('a', inferred.locals)
  206. self.assertIn('b', inferred.locals)
  207. self.assertIn('c', inferred.locals)
  208. class DefaultDictTest(unittest.TestCase):
  209. def test_1(self):
  210. node = builder.extract_node('''
  211. from collections import defaultdict
  212. X = defaultdict(int)
  213. X[0]
  214. ''')
  215. inferred = next(node.infer())
  216. self.assertIs(util.Uninferable, inferred)
  217. class ModuleExtenderTest(unittest.TestCase):
  218. def testExtensionModules(self):
  219. transformer = MANAGER._transform
  220. for extender, _ in transformer.transforms[nodes.Module]:
  221. n = nodes.Module('__main__', None)
  222. extender(n)
  223. @unittest.skipUnless(HAS_NOSE, "This test requires nose library.")
  224. class NoseBrainTest(unittest.TestCase):
  225. def test_nose_tools(self):
  226. methods = builder.extract_node("""
  227. from nose.tools import assert_equal
  228. from nose.tools import assert_equals
  229. from nose.tools import assert_true
  230. assert_equal = assert_equal #@
  231. assert_true = assert_true #@
  232. assert_equals = assert_equals #@
  233. """)
  234. assert_equal = next(methods[0].value.infer())
  235. assert_true = next(methods[1].value.infer())
  236. assert_equals = next(methods[2].value.infer())
  237. self.assertIsInstance(assert_equal, astroid.BoundMethod)
  238. self.assertIsInstance(assert_true, astroid.BoundMethod)
  239. self.assertIsInstance(assert_equals, astroid.BoundMethod)
  240. self.assertEqual(assert_equal.qname(),
  241. 'unittest.case.TestCase.assertEqual')
  242. self.assertEqual(assert_true.qname(),
  243. 'unittest.case.TestCase.assertTrue')
  244. self.assertEqual(assert_equals.qname(),
  245. 'unittest.case.TestCase.assertEqual')
  246. class SixBrainTest(unittest.TestCase):
  247. def test_attribute_access(self):
  248. ast_nodes = builder.extract_node('''
  249. import six
  250. six.moves.http_client #@
  251. six.moves.urllib_parse #@
  252. six.moves.urllib_error #@
  253. six.moves.urllib.request #@
  254. ''')
  255. http_client = next(ast_nodes[0].infer())
  256. self.assertIsInstance(http_client, nodes.Module)
  257. self.assertEqual(http_client.name,
  258. 'http.client' if six.PY3 else 'httplib')
  259. urllib_parse = next(ast_nodes[1].infer())
  260. if six.PY3:
  261. self.assertIsInstance(urllib_parse, nodes.Module)
  262. self.assertEqual(urllib_parse.name, 'urllib.parse')
  263. else:
  264. # On Python 2, this is a fake module, the same behaviour
  265. # being mimicked in brain's tip for six.moves.
  266. self.assertIsInstance(urllib_parse, astroid.Instance)
  267. urljoin = next(urllib_parse.igetattr('urljoin'))
  268. urlencode = next(urllib_parse.igetattr('urlencode'))
  269. if six.PY2:
  270. # In reality it's a function, but our implementations
  271. # transforms it into a method.
  272. self.assertIsInstance(urljoin, astroid.FunctionDef)
  273. self.assertEqual(urljoin.qname(), 'urlparse.urljoin')
  274. self.assertIsInstance(urlencode, astroid.FunctionDef)
  275. self.assertEqual(urlencode.qname(), 'urllib.urlencode')
  276. else:
  277. self.assertIsInstance(urljoin, nodes.FunctionDef)
  278. self.assertEqual(urljoin.qname(), 'urllib.parse.urljoin')
  279. self.assertIsInstance(urlencode, nodes.FunctionDef)
  280. self.assertEqual(urlencode.qname(), 'urllib.parse.urlencode')
  281. urllib_error = next(ast_nodes[2].infer())
  282. if six.PY3:
  283. self.assertIsInstance(urllib_error, nodes.Module)
  284. self.assertEqual(urllib_error.name, 'urllib.error')
  285. else:
  286. # On Python 2, this is a fake module, the same behaviour
  287. # being mimicked in brain's tip for six.moves.
  288. self.assertIsInstance(urllib_error, astroid.Instance)
  289. urlerror = next(urllib_error.igetattr('URLError'))
  290. self.assertIsInstance(urlerror, nodes.ClassDef)
  291. content_too_short = next(urllib_error.igetattr('ContentTooShortError'))
  292. self.assertIsInstance(content_too_short, nodes.ClassDef)
  293. urllib_request = next(ast_nodes[3].infer())
  294. if six.PY3:
  295. self.assertIsInstance(urllib_request, nodes.Module)
  296. self.assertEqual(urllib_request.name, 'urllib.request')
  297. else:
  298. self.assertIsInstance(urllib_request, astroid.Instance)
  299. urlopen = next(urllib_request.igetattr('urlopen'))
  300. urlretrieve = next(urllib_request.igetattr('urlretrieve'))
  301. if six.PY2:
  302. # In reality it's a function, but our implementations
  303. # transforms it into a method.
  304. self.assertIsInstance(urlopen, astroid.FunctionDef)
  305. self.assertEqual(urlopen.qname(), 'urllib2.urlopen')
  306. self.assertIsInstance(urlretrieve, astroid.FunctionDef)
  307. self.assertEqual(urlretrieve.qname(), 'urllib.urlretrieve')
  308. else:
  309. self.assertIsInstance(urlopen, nodes.FunctionDef)
  310. self.assertEqual(urlopen.qname(), 'urllib.request.urlopen')
  311. self.assertIsInstance(urlretrieve, nodes.FunctionDef)
  312. self.assertEqual(urlretrieve.qname(), 'urllib.request.urlretrieve')
  313. def test_from_imports(self):
  314. ast_node = builder.extract_node('''
  315. from six.moves import http_client
  316. http_client.HTTPSConnection #@
  317. ''')
  318. inferred = next(ast_node.infer())
  319. self.assertIsInstance(inferred, nodes.ClassDef)
  320. if six.PY3:
  321. qname = 'http.client.HTTPSConnection'
  322. else:
  323. qname = 'httplib.HTTPSConnection'
  324. self.assertEqual(inferred.qname(), qname)
  325. @unittest.skipIf(six.PY2,
  326. "The python 2 six brain uses dummy classes")
  327. def test_from_submodule_imports(self):
  328. """Make sure ulrlib submodules can be imported from
  329. See PyCQA/pylint#1640 for relevant issue
  330. """
  331. ast_node = builder.extract_node('''
  332. from six.moves.urllib.parse import urlparse
  333. urlparse #@
  334. ''')
  335. inferred = next(ast_node.infer())
  336. self.assertIsInstance(inferred, nodes.FunctionDef)
  337. @unittest.skipUnless(HAS_MULTIPROCESSING,
  338. 'multiprocesing is required for this test, but '
  339. 'on some platforms it is missing '
  340. '(Jython for instance)')
  341. class MultiprocessingBrainTest(unittest.TestCase):
  342. def test_multiprocessing_module_attributes(self):
  343. # Test that module attributes are working,
  344. # especially on Python 3.4+, where they are obtained
  345. # from a context.
  346. module = builder.extract_node("""
  347. import multiprocessing
  348. """)
  349. module = module.do_import_module('multiprocessing')
  350. cpu_count = next(module.igetattr('cpu_count'))
  351. if sys.version_info < (3, 4):
  352. self.assertIsInstance(cpu_count, nodes.FunctionDef)
  353. else:
  354. self.assertIsInstance(cpu_count, astroid.BoundMethod)
  355. def test_module_name(self):
  356. module = builder.extract_node("""
  357. import multiprocessing
  358. multiprocessing.SyncManager()
  359. """)
  360. inferred_sync_mgr = next(module.infer())
  361. module = inferred_sync_mgr.root()
  362. self.assertEqual(module.name, 'multiprocessing.managers')
  363. def test_multiprocessing_manager(self):
  364. # Test that we have the proper attributes
  365. # for a multiprocessing.managers.SyncManager
  366. module = builder.parse("""
  367. import multiprocessing
  368. manager = multiprocessing.Manager()
  369. queue = manager.Queue()
  370. joinable_queue = manager.JoinableQueue()
  371. event = manager.Event()
  372. rlock = manager.RLock()
  373. bounded_semaphore = manager.BoundedSemaphore()
  374. condition = manager.Condition()
  375. barrier = manager.Barrier()
  376. pool = manager.Pool()
  377. list = manager.list()
  378. dict = manager.dict()
  379. value = manager.Value()
  380. array = manager.Array()
  381. namespace = manager.Namespace()
  382. """)
  383. queue = next(module['queue'].infer())
  384. self.assertEqual(queue.qname(),
  385. "{}.Queue".format(six.moves.queue.__name__))
  386. joinable_queue = next(module['joinable_queue'].infer())
  387. self.assertEqual(joinable_queue.qname(),
  388. "{}.Queue".format(six.moves.queue.__name__))
  389. event = next(module['event'].infer())
  390. event_name = "threading.{}".format("Event" if six.PY3 else "_Event")
  391. self.assertEqual(event.qname(), event_name)
  392. rlock = next(module['rlock'].infer())
  393. rlock_name = "threading._RLock"
  394. self.assertEqual(rlock.qname(), rlock_name)
  395. bounded_semaphore = next(module['bounded_semaphore'].infer())
  396. semaphore_name = "threading.{}".format(
  397. "BoundedSemaphore" if six.PY3 else "_BoundedSemaphore")
  398. self.assertEqual(bounded_semaphore.qname(), semaphore_name)
  399. pool = next(module['pool'].infer())
  400. pool_name = "multiprocessing.pool.Pool"
  401. self.assertEqual(pool.qname(), pool_name)
  402. for attr in ('list', 'dict'):
  403. obj = next(module[attr].infer())
  404. self.assertEqual(obj.qname(),
  405. "{}.{}".format(bases.BUILTINS, attr))
  406. array = next(module['array'].infer())
  407. self.assertEqual(array.qname(), "array.array")
  408. manager = next(module['manager'].infer())
  409. # Verify that we have these attributes
  410. self.assertTrue(manager.getattr('start'))
  411. self.assertTrue(manager.getattr('shutdown'))
  412. class ThreadingBrainTest(unittest.TestCase):
  413. def test_lock(self):
  414. self._test_lock_object('Lock')
  415. def test_rlock(self):
  416. self._test_lock_object('RLock')
  417. def test_semaphore(self):
  418. self._test_lock_object('Semaphore')
  419. def test_boundedsemaphore(self):
  420. self._test_lock_object('BoundedSemaphore')
  421. def _test_lock_object(self, object_name):
  422. lock_instance = builder.extract_node("""
  423. import threading
  424. threading.{0}()
  425. """.format(object_name))
  426. inferred = next(lock_instance.infer())
  427. self.assert_is_valid_lock(inferred)
  428. def assert_is_valid_lock(self, inferred):
  429. self.assertIsInstance(inferred, astroid.Instance)
  430. self.assertEqual(inferred.root().name, 'threading')
  431. for method in {'acquire', 'release', '__enter__', '__exit__'}:
  432. self.assertIsInstance(next(inferred.igetattr(method)), astroid.BoundMethod)
  433. @unittest.skipUnless(HAS_ENUM,
  434. 'The enum module was only added in Python 3.4. Support for '
  435. 'older Python versions may be available through the enum34 '
  436. 'compatibility module.')
  437. class EnumBrainTest(unittest.TestCase):
  438. def test_simple_enum(self):
  439. module = builder.parse("""
  440. import enum
  441. class MyEnum(enum.Enum):
  442. one = "one"
  443. two = "two"
  444. def mymethod(self, x):
  445. return 5
  446. """)
  447. enumeration = next(module['MyEnum'].infer())
  448. one = enumeration['one']
  449. self.assertEqual(one.pytype(), '.MyEnum.one')
  450. property_type = '{}.property'.format(bases.BUILTINS)
  451. for propname in ('name', 'value'):
  452. prop = next(iter(one.getattr(propname)))
  453. self.assertIn(property_type, prop.decoratornames())
  454. meth = one.getattr('mymethod')[0]
  455. self.assertIsInstance(meth, astroid.FunctionDef)
  456. def test_looks_like_enum_false_positive(self):
  457. # Test that a class named Enumeration is not considered a builtin enum.
  458. module = builder.parse('''
  459. class Enumeration(object):
  460. def __init__(self, name, enum_list):
  461. pass
  462. test = 42
  463. ''')
  464. enumeration = module['Enumeration']
  465. test = next(enumeration.igetattr('test'))
  466. self.assertEqual(test.value, 42)
  467. def test_enum_multiple_base_classes(self):
  468. module = builder.parse("""
  469. import enum
  470. class Mixin:
  471. pass
  472. class MyEnum(Mixin, enum.Enum):
  473. one = 1
  474. """)
  475. enumeration = next(module['MyEnum'].infer())
  476. one = enumeration['one']
  477. clazz = one.getattr('__class__')[0]
  478. self.assertTrue(clazz.is_subtype_of('.Mixin'),
  479. 'Enum instance should share base classes with generating class')
  480. def test_int_enum(self):
  481. module = builder.parse("""
  482. import enum
  483. class MyEnum(enum.IntEnum):
  484. one = 1
  485. """)
  486. enumeration = next(module['MyEnum'].infer())
  487. one = enumeration['one']
  488. clazz = one.getattr('__class__')[0]
  489. int_type = '{}.{}'.format(bases.BUILTINS, 'int')
  490. self.assertTrue(clazz.is_subtype_of(int_type),
  491. 'IntEnum based enums should be a subtype of int')
  492. def test_enum_func_form_is_class_not_instance(self):
  493. cls, instance = builder.extract_node('''
  494. from enum import Enum
  495. f = Enum('Audience', ['a', 'b', 'c'])
  496. f #@
  497. f(1) #@
  498. ''')
  499. inferred_cls = next(cls.infer())
  500. self.assertIsInstance(inferred_cls, bases.Instance)
  501. inferred_instance = next(instance.infer())
  502. self.assertIsInstance(inferred_instance, bases.Instance)
  503. self.assertIsInstance(next(inferred_instance.igetattr('name')), nodes.Const)
  504. self.assertIsInstance(next(inferred_instance.igetattr('value')), nodes.Const)
  505. def test_enum_func_form_iterable(self):
  506. instance = builder.extract_node('''
  507. from enum import Enum
  508. Animal = Enum('Animal', 'ant bee cat dog')
  509. Animal
  510. ''')
  511. inferred = next(instance.infer())
  512. self.assertIsInstance(inferred, astroid.Instance)
  513. self.assertTrue(inferred.getattr('__iter__'))
  514. def test_enum_func_form_subscriptable(self):
  515. instance, name = builder.extract_node('''
  516. from enum import Enum
  517. Animal = Enum('Animal', 'ant bee cat dog')
  518. Animal['ant'] #@
  519. Animal['ant'].name #@
  520. ''')
  521. instance = next(instance.infer())
  522. self.assertIsInstance(instance, astroid.Instance)
  523. inferred = next(name.infer())
  524. self.assertIsInstance(inferred, astroid.Const)
  525. def test_enum_func_form_has_dunder_members(self):
  526. instance = builder.extract_node('''
  527. from enum import Enum
  528. Animal = Enum('Animal', 'ant bee cat dog')
  529. for i in Animal.__members__:
  530. i #@
  531. ''')
  532. instance = next(instance.infer())
  533. self.assertIsInstance(instance, astroid.Const)
  534. self.assertIsInstance(instance.value, str)
  535. @unittest.skipUnless(HAS_DATEUTIL, "This test requires the dateutil library.")
  536. class DateutilBrainTest(unittest.TestCase):
  537. def test_parser(self):
  538. module = builder.parse("""
  539. from dateutil.parser import parse
  540. d = parse('2000-01-01')
  541. """)
  542. d_type = next(module['d'].infer())
  543. self.assertEqual(d_type.qname(), "datetime.datetime")
  544. @unittest.skipUnless(HAS_PYTEST, "This test requires the pytest library.")
  545. class PytestBrainTest(unittest.TestCase):
  546. def test_pytest(self):
  547. ast_node = builder.extract_node('''
  548. import pytest
  549. pytest #@
  550. ''')
  551. module = next(ast_node.infer())
  552. attrs = ['deprecated_call', 'warns', 'exit', 'fail', 'skip',
  553. 'importorskip', 'xfail', 'mark', 'raises', 'freeze_includes',
  554. 'set_trace', 'fixture', 'yield_fixture']
  555. if pytest.__version__.split('.')[0] == '3':
  556. attrs += ['approx', 'register_assert_rewrite']
  557. for attr in attrs:
  558. self.assertIn(attr, module)
  559. def streams_are_fine():
  560. """Check if streams are being overwritten,
  561. for example, by pytest
  562. stream inference will not work if they are overwritten
  563. PY3 only
  564. """
  565. import io
  566. for stream in (sys.stdout, sys.stderr, sys.stdin):
  567. if not isinstance(stream, io.IOBase):
  568. return False
  569. return True
  570. class IOBrainTest(unittest.TestCase):
  571. @unittest.skipUnless(
  572. six.PY3 and streams_are_fine(),
  573. "Needs Python 3 io model / doesn't work with plain pytest."
  574. "use pytest -s for this test to work")
  575. def test_sys_streams(self):
  576. for name in {'stdout', 'stderr', 'stdin'}:
  577. node = astroid.extract_node('''
  578. import sys
  579. sys.{}
  580. '''.format(name))
  581. inferred = next(node.infer())
  582. buffer_attr = next(inferred.igetattr('buffer'))
  583. self.assertIsInstance(buffer_attr, astroid.Instance)
  584. self.assertEqual(buffer_attr.name, 'BufferedWriter')
  585. raw = next(buffer_attr.igetattr('raw'))
  586. self.assertIsInstance(raw, astroid.Instance)
  587. self.assertEqual(raw.name, 'FileIO')
  588. @test_utils.require_version('3.6')
  589. class TypingBrain(unittest.TestCase):
  590. def test_namedtuple_base(self):
  591. klass = builder.extract_node("""
  592. from typing import NamedTuple
  593. class X(NamedTuple("X", [("a", int), ("b", str), ("c", bytes)])):
  594. pass
  595. """)
  596. self.assertEqual(
  597. [anc.name for anc in klass.ancestors()],
  598. ['X', 'tuple', 'object'])
  599. for anc in klass.ancestors():
  600. self.assertFalse(anc.parent is None)
  601. def test_namedtuple_inference(self):
  602. klass = builder.extract_node("""
  603. from typing import NamedTuple
  604. class X(NamedTuple("X", [("a", int), ("b", str), ("c", bytes)])):
  605. pass
  606. """)
  607. base = next(base for base in klass.ancestors()
  608. if base.name == 'X')
  609. self.assertSetEqual({"a", "b", "c"}, set(base.instance_attrs))
  610. def test_namedtuple_inference_nonliteral(self):
  611. # Note: NamedTuples in mypy only work with literals.
  612. klass = builder.extract_node("""
  613. from typing import NamedTuple
  614. name = "X"
  615. fields = [("a", int), ("b", str), ("c", bytes)]
  616. NamedTuple(name, fields)
  617. """)
  618. inferred = next(klass.infer())
  619. self.assertIsInstance(inferred, astroid.Instance)
  620. self.assertEqual(inferred.qname(), "typing.NamedTuple")
  621. def test_namedtuple_instance_attrs(self):
  622. result = builder.extract_node('''
  623. from typing import NamedTuple
  624. NamedTuple("A", [("a", int), ("b", str), ("c", bytes)])(1, 2, 3) #@
  625. ''')
  626. inferred = next(result.infer())
  627. for name, attr in inferred.instance_attrs.items():
  628. self.assertEqual(attr[0].attrname, name)
  629. def test_namedtuple_simple(self):
  630. result = builder.extract_node('''
  631. from typing import NamedTuple
  632. NamedTuple("A", [("a", int), ("b", str), ("c", bytes)])
  633. ''')
  634. inferred = next(result.infer())
  635. self.assertIsInstance(inferred, nodes.ClassDef)
  636. self.assertSetEqual({"a", "b", "c"}, set(inferred.instance_attrs))
  637. def test_namedtuple_few_args(self):
  638. result = builder.extract_node('''
  639. from typing import NamedTuple
  640. NamedTuple("A")
  641. ''')
  642. inferred = next(result.infer())
  643. self.assertIsInstance(inferred, astroid.Instance)
  644. self.assertEqual(inferred.qname(), "typing.NamedTuple")
  645. def test_namedtuple_few_fields(self):
  646. result = builder.extract_node('''
  647. from typing import NamedTuple
  648. NamedTuple("A", [("a",), ("b", str), ("c", bytes)])
  649. ''')
  650. inferred = next(result.infer())
  651. self.assertIsInstance(inferred, astroid.Instance)
  652. self.assertEqual(inferred.qname(), "typing.NamedTuple")
  653. def test_namedtuple_class_form(self):
  654. result = builder.extract_node('''
  655. from typing import NamedTuple
  656. class Example(NamedTuple):
  657. mything: int
  658. Example(mything=1)
  659. ''')
  660. inferred = next(result.infer())
  661. self.assertIsInstance(inferred, astroid.Instance)
  662. class ReBrainTest(unittest.TestCase):
  663. def test_regex_flags(self):
  664. import re
  665. names = [name for name in dir(re) if name.isupper()]
  666. re_ast = MANAGER.ast_from_module_name('re')
  667. for name in names:
  668. self.assertIn(name, re_ast)
  669. self.assertEqual(next(re_ast[name].infer()).value, getattr(re, name))
  670. @test_utils.require_version('3.6')
  671. class BrainFStrings(unittest.TestCase):
  672. def test_no_crash_on_const_reconstruction(self):
  673. node = builder.extract_node('''
  674. max_width = 10
  675. test1 = f'{" ":{max_width+4}}'
  676. print(f'"{test1}"')
  677. test2 = f'[{"7":>{max_width}}:0]'
  678. test2
  679. ''')
  680. inferred = next(node.infer())
  681. self.assertIs(inferred, util.Uninferable)
  682. @test_utils.require_version('3.6')
  683. class BrainNamedtupleAnnAssignTest(unittest.TestCase):
  684. def test_no_crash_on_ann_assign_in_namedtuple(self):
  685. node = builder.extract_node('''
  686. from enum import Enum
  687. from typing import Optional
  688. class A(Enum):
  689. B: str = 'B'
  690. ''')
  691. inferred = next(node.infer())
  692. self.assertIsInstance(inferred, nodes.ClassDef)
  693. class BrainUUIDTest(unittest.TestCase):
  694. def test_uuid_has_int_member(self):
  695. node = builder.extract_node('''
  696. import uuid
  697. u = uuid.UUID('{12345678-1234-5678-1234-567812345678}')
  698. u.int
  699. ''')
  700. inferred = next(node.infer())
  701. self.assertIsInstance(inferred, nodes.Const)
  702. @unittest.skipUnless(HAS_ATTR, "These tests require the attr library")
  703. class AttrsTest(unittest.TestCase):
  704. def test_attr_transform(self):
  705. module = astroid.parse("""
  706. import attr
  707. @attr.s
  708. class Foo:
  709. d = attr.ib(attr.Factory(dict))
  710. f = Foo()
  711. f.d['answer'] = 42
  712. """)
  713. should_be_attribute = next(module.getattr('f')[0].infer()).getattr('d')[0]
  714. self.assertIsInstance(should_be_attribute, astroid.Unknown)
  715. def test_special_attributes(self):
  716. """Make sure special attrs attributes exist"""
  717. code = """
  718. import attr
  719. @attr.s
  720. class Foo:
  721. pass
  722. Foo()
  723. """
  724. foo_inst = next(astroid.extract_node(code).infer())
  725. [attr_node] = foo_inst.getattr("__attrs_attrs__")
  726. # Prevents https://github.com/PyCQA/pylint/issues/1884
  727. assert isinstance(attr_node, nodes.Unknown)
  728. def test_dont_consider_assignments_but_without_attrs(self):
  729. code = '''
  730. import attr
  731. class Cls: pass
  732. @attr.s
  733. class Foo:
  734. temp = Cls()
  735. temp.prop = 5
  736. bar_thing = attr.ib(default=temp)
  737. Foo()
  738. '''
  739. next(astroid.extract_node(code).infer())
  740. if __name__ == '__main__':
  741. unittest.main()