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.

rebuilder.py 38KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908
  1. # Copyright (c) 2009-2014 LOGILAB S.A. (Paris, FRANCE) <contact@logilab.fr>
  2. # Copyright (c) 2013-2016 Claudiu Popa <pcmanticore@gmail.com>
  3. # Copyright (c) 2013-2014 Google, Inc.
  4. # Copyright (c) 2015-2016 Cara Vinson <ceridwenv@gmail.com>
  5. # Licensed under the LGPL: https://www.gnu.org/licenses/old-licenses/lgpl-2.1.en.html
  6. # For details: https://github.com/PyCQA/astroid/blob/master/COPYING.LESSER
  7. """this module contains utilities for rebuilding a _ast tree in
  8. order to get a single Astroid representation
  9. """
  10. import sys
  11. import _ast
  12. import astroid
  13. from astroid import astpeephole
  14. from astroid import nodes
  15. _BIN_OP_CLASSES = {_ast.Add: '+',
  16. _ast.BitAnd: '&',
  17. _ast.BitOr: '|',
  18. _ast.BitXor: '^',
  19. _ast.Div: '/',
  20. _ast.FloorDiv: '//',
  21. _ast.Mod: '%',
  22. _ast.Mult: '*',
  23. _ast.Pow: '**',
  24. _ast.Sub: '-',
  25. _ast.LShift: '<<',
  26. _ast.RShift: '>>',
  27. }
  28. if sys.version_info >= (3, 5):
  29. _BIN_OP_CLASSES[_ast.MatMult] = '@'
  30. _BOOL_OP_CLASSES = {_ast.And: 'and',
  31. _ast.Or: 'or',
  32. }
  33. _UNARY_OP_CLASSES = {_ast.UAdd: '+',
  34. _ast.USub: '-',
  35. _ast.Not: 'not',
  36. _ast.Invert: '~',
  37. }
  38. _CMP_OP_CLASSES = {_ast.Eq: '==',
  39. _ast.Gt: '>',
  40. _ast.GtE: '>=',
  41. _ast.In: 'in',
  42. _ast.Is: 'is',
  43. _ast.IsNot: 'is not',
  44. _ast.Lt: '<',
  45. _ast.LtE: '<=',
  46. _ast.NotEq: '!=',
  47. _ast.NotIn: 'not in',
  48. }
  49. CONST_NAME_TRANSFORMS = {'None': None,
  50. 'True': True,
  51. 'False': False,
  52. }
  53. REDIRECT = {'arguments': 'Arguments',
  54. 'comprehension': 'Comprehension',
  55. "ListCompFor": 'Comprehension',
  56. "GenExprFor": 'Comprehension',
  57. 'excepthandler': 'ExceptHandler',
  58. 'keyword': 'Keyword',
  59. }
  60. PY3 = sys.version_info >= (3, 0)
  61. PY34 = sys.version_info >= (3, 4)
  62. CONTEXTS = {_ast.Load: astroid.Load,
  63. _ast.Store: astroid.Store,
  64. _ast.Del: astroid.Del,
  65. _ast.Param: astroid.Store}
  66. def _get_doc(node):
  67. try:
  68. if isinstance(node.body[0], _ast.Expr) and isinstance(node.body[0].value, _ast.Str):
  69. doc = node.body[0].value.s
  70. node.body = node.body[1:]
  71. return node, doc
  72. except IndexError:
  73. pass # ast built from scratch
  74. return node, None
  75. def _visit_or_none(node, attr, visitor, parent, visit='visit',
  76. **kws):
  77. """If the given node has an attribute, visits the attribute, and
  78. otherwise returns None.
  79. """
  80. value = getattr(node, attr, None)
  81. if value:
  82. return getattr(visitor, visit)(value, parent, **kws)
  83. return None
  84. def _get_context(node):
  85. return CONTEXTS.get(type(node.ctx), astroid.Load)
  86. class TreeRebuilder(object):
  87. """Rebuilds the _ast tree to become an Astroid tree"""
  88. def __init__(self, manager):
  89. self._manager = manager
  90. self._global_names = []
  91. self._import_from_nodes = []
  92. self._delayed_assattr = []
  93. self._visit_meths = {}
  94. self._peepholer = astpeephole.ASTPeepholeOptimizer()
  95. def visit_module(self, node, modname, modpath, package):
  96. """visit a Module node by returning a fresh instance of it"""
  97. node, doc = _get_doc(node)
  98. newnode = nodes.Module(name=modname, doc=doc, file=modpath, path=modpath,
  99. package=package, parent=None)
  100. newnode.postinit([self.visit(child, newnode) for child in node.body])
  101. return newnode
  102. def visit(self, node, parent):
  103. cls = node.__class__
  104. if cls in self._visit_meths:
  105. visit_method = self._visit_meths[cls]
  106. else:
  107. cls_name = cls.__name__
  108. visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower()
  109. visit_method = getattr(self, visit_name)
  110. self._visit_meths[cls] = visit_method
  111. return visit_method(node, parent)
  112. def _save_assignment(self, node, name=None):
  113. """save assignement situation since node.parent is not available yet"""
  114. if self._global_names and node.name in self._global_names[-1]:
  115. node.root().set_local(node.name, node)
  116. else:
  117. node.parent.set_local(node.name, node)
  118. def visit_arguments(self, node, parent):
  119. """visit a Arguments node by returning a fresh instance of it"""
  120. vararg, kwarg = node.vararg, node.kwarg
  121. if PY34:
  122. newnode = nodes.Arguments(vararg.arg if vararg else None,
  123. kwarg.arg if kwarg else None,
  124. parent)
  125. else:
  126. newnode = nodes.Arguments(vararg, kwarg, parent)
  127. args = [self.visit(child, newnode) for child in node.args]
  128. defaults = [self.visit(child, newnode)
  129. for child in node.defaults]
  130. varargannotation = None
  131. kwargannotation = None
  132. # change added in 82732 (7c5c678e4164), vararg and kwarg
  133. # are instances of `_ast.arg`, not strings
  134. if vararg:
  135. if PY34:
  136. if node.vararg.annotation:
  137. varargannotation = self.visit(node.vararg.annotation,
  138. newnode)
  139. vararg = vararg.arg
  140. if kwarg:
  141. if PY34:
  142. if node.kwarg.annotation:
  143. kwargannotation = self.visit(node.kwarg.annotation,
  144. newnode)
  145. kwarg = kwarg.arg
  146. if PY3:
  147. kwonlyargs = [self.visit(child, newnode) for child
  148. in node.kwonlyargs]
  149. kw_defaults = [self.visit(child, newnode) if child else
  150. None for child in node.kw_defaults]
  151. annotations = [self.visit(arg.annotation, newnode) if
  152. arg.annotation else None for arg in node.args]
  153. kwonlyargs_annotations = [
  154. self.visit(arg.annotation, newnode) if arg.annotation else None
  155. for arg in node.kwonlyargs
  156. ]
  157. else:
  158. kwonlyargs = []
  159. kw_defaults = []
  160. annotations = []
  161. kwonlyargs_annotations = []
  162. newnode.postinit(
  163. args=args,
  164. defaults=defaults,
  165. kwonlyargs=kwonlyargs,
  166. kw_defaults=kw_defaults,
  167. annotations=annotations,
  168. kwonlyargs_annotations=kwonlyargs_annotations,
  169. varargannotation=varargannotation,
  170. kwargannotation=kwargannotation
  171. )
  172. # save argument names in locals:
  173. if vararg:
  174. newnode.parent.set_local(vararg, newnode)
  175. if kwarg:
  176. newnode.parent.set_local(kwarg, newnode)
  177. return newnode
  178. def visit_assert(self, node, parent):
  179. """visit a Assert node by returning a fresh instance of it"""
  180. newnode = nodes.Assert(node.lineno, node.col_offset, parent)
  181. if node.msg:
  182. msg = self.visit(node.msg, newnode)
  183. else:
  184. msg = None
  185. newnode.postinit(self.visit(node.test, newnode), msg)
  186. return newnode
  187. def visit_assign(self, node, parent):
  188. """visit a Assign node by returning a fresh instance of it"""
  189. newnode = nodes.Assign(node.lineno, node.col_offset, parent)
  190. newnode.postinit([self.visit(child, newnode)
  191. for child in node.targets],
  192. self.visit(node.value, newnode))
  193. return newnode
  194. def visit_assignname(self, node, parent, node_name=None):
  195. '''visit a node and return a AssignName node'''
  196. newnode = nodes.AssignName(node_name, getattr(node, 'lineno', None),
  197. getattr(node, 'col_offset', None), parent)
  198. self._save_assignment(newnode)
  199. return newnode
  200. def visit_augassign(self, node, parent):
  201. """visit a AugAssign node by returning a fresh instance of it"""
  202. newnode = nodes.AugAssign(_BIN_OP_CLASSES[type(node.op)] + "=",
  203. node.lineno, node.col_offset, parent)
  204. newnode.postinit(self.visit(node.target, newnode),
  205. self.visit(node.value, newnode))
  206. return newnode
  207. def visit_repr(self, node, parent):
  208. """visit a Backquote node by returning a fresh instance of it"""
  209. newnode = nodes.Repr(node.lineno, node.col_offset, parent)
  210. newnode.postinit(self.visit(node.value, newnode))
  211. return newnode
  212. def visit_binop(self, node, parent):
  213. """visit a BinOp node by returning a fresh instance of it"""
  214. if isinstance(node.left, _ast.BinOp) and self._manager.optimize_ast:
  215. # Optimize BinOp operations in order to remove
  216. # redundant recursion. For instance, if the
  217. # following code is parsed in order to obtain
  218. # its ast, then the rebuilder will fail with an
  219. # infinite recursion, the same will happen with the
  220. # inference engine as well. There's no need to hold
  221. # so many objects for the BinOp if they can be reduced
  222. # to something else (also, the optimization
  223. # might handle only Const binops, which isn't a big
  224. # problem for the correctness of the program).
  225. #
  226. # ("a" + "b" + # one thousand more + "c")
  227. optimized = self._peepholer.optimize_binop(node, parent)
  228. if optimized:
  229. return optimized
  230. newnode = nodes.BinOp(_BIN_OP_CLASSES[type(node.op)],
  231. node.lineno, node.col_offset, parent)
  232. newnode.postinit(self.visit(node.left, newnode),
  233. self.visit(node.right, newnode))
  234. return newnode
  235. def visit_boolop(self, node, parent):
  236. """visit a BoolOp node by returning a fresh instance of it"""
  237. newnode = nodes.BoolOp(_BOOL_OP_CLASSES[type(node.op)],
  238. node.lineno, node.col_offset, parent)
  239. newnode.postinit([self.visit(child, newnode)
  240. for child in node.values])
  241. return newnode
  242. def visit_break(self, node, parent):
  243. """visit a Break node by returning a fresh instance of it"""
  244. return nodes.Break(getattr(node, 'lineno', None),
  245. getattr(node, 'col_offset', None),
  246. parent)
  247. def visit_call(self, node, parent):
  248. """visit a CallFunc node by returning a fresh instance of it"""
  249. newnode = nodes.Call(node.lineno, node.col_offset, parent)
  250. starargs = _visit_or_none(node, 'starargs', self, newnode)
  251. kwargs = _visit_or_none(node, 'kwargs', self, newnode)
  252. args = [self.visit(child, newnode)
  253. for child in node.args]
  254. if node.keywords:
  255. keywords = [self.visit(child, newnode)
  256. for child in node.keywords]
  257. else:
  258. keywords = None
  259. if starargs:
  260. new_starargs = nodes.Starred(col_offset=starargs.col_offset,
  261. lineno=starargs.lineno,
  262. parent=starargs.parent)
  263. new_starargs.postinit(value=starargs)
  264. args.append(new_starargs)
  265. if kwargs:
  266. new_kwargs = nodes.Keyword(arg=None, col_offset=kwargs.col_offset,
  267. lineno=kwargs.lineno,
  268. parent=kwargs.parent)
  269. new_kwargs.postinit(value=kwargs)
  270. if keywords:
  271. keywords.append(new_kwargs)
  272. else:
  273. keywords = [new_kwargs]
  274. newnode.postinit(self.visit(node.func, newnode),
  275. args, keywords)
  276. return newnode
  277. def visit_classdef(self, node, parent, newstyle=None):
  278. """visit a ClassDef node to become astroid"""
  279. node, doc = _get_doc(node)
  280. newnode = nodes.ClassDef(node.name, doc, node.lineno,
  281. node.col_offset, parent)
  282. metaclass = None
  283. if PY3:
  284. for keyword in node.keywords:
  285. if keyword.arg == 'metaclass':
  286. metaclass = self.visit(keyword, newnode).value
  287. break
  288. if node.decorator_list:
  289. decorators = self.visit_decorators(node, newnode)
  290. else:
  291. decorators = None
  292. newnode.postinit([self.visit(child, newnode)
  293. for child in node.bases],
  294. [self.visit(child, newnode)
  295. for child in node.body],
  296. decorators, newstyle, metaclass,
  297. [self.visit(kwd, newnode) for kwd in node.keywords
  298. if kwd.arg != 'metaclass'] if PY3 else [])
  299. return newnode
  300. def visit_const(self, node, parent):
  301. """visit a Const node by returning a fresh instance of it"""
  302. return nodes.Const(node.value,
  303. getattr(node, 'lineno', None),
  304. getattr(node, 'col_offset', None), parent)
  305. def visit_continue(self, node, parent):
  306. """visit a Continue node by returning a fresh instance of it"""
  307. return nodes.Continue(getattr(node, 'lineno', None),
  308. getattr(node, 'col_offset', None),
  309. parent)
  310. def visit_compare(self, node, parent):
  311. """visit a Compare node by returning a fresh instance of it"""
  312. newnode = nodes.Compare(node.lineno, node.col_offset, parent)
  313. newnode.postinit(self.visit(node.left, newnode),
  314. [(_CMP_OP_CLASSES[op.__class__],
  315. self.visit(expr, newnode))
  316. for (op, expr) in zip(node.ops, node.comparators)])
  317. return newnode
  318. def visit_comprehension(self, node, parent):
  319. """visit a Comprehension node by returning a fresh instance of it"""
  320. newnode = nodes.Comprehension(parent)
  321. newnode.postinit(self.visit(node.target, newnode),
  322. self.visit(node.iter, newnode),
  323. [self.visit(child, newnode)
  324. for child in node.ifs],
  325. getattr(node, 'is_async', None))
  326. return newnode
  327. def visit_decorators(self, node, parent):
  328. """visit a Decorators node by returning a fresh instance of it"""
  329. # /!\ node is actually a _ast.FunctionDef node while
  330. # parent is a astroid.nodes.FunctionDef node
  331. newnode = nodes.Decorators(node.lineno, node.col_offset, parent)
  332. newnode.postinit([self.visit(child, newnode)
  333. for child in node.decorator_list])
  334. return newnode
  335. def visit_delete(self, node, parent):
  336. """visit a Delete node by returning a fresh instance of it"""
  337. newnode = nodes.Delete(node.lineno, node.col_offset, parent)
  338. newnode.postinit([self.visit(child, newnode)
  339. for child in node.targets])
  340. return newnode
  341. def _visit_dict_items(self, node, parent, newnode):
  342. for key, value in zip(node.keys, node.values):
  343. rebuilt_value = self.visit(value, newnode)
  344. if not key:
  345. # Python 3.5 and extended unpacking
  346. rebuilt_key = nodes.DictUnpack(rebuilt_value.lineno,
  347. rebuilt_value.col_offset,
  348. parent)
  349. else:
  350. rebuilt_key = self.visit(key, newnode)
  351. yield rebuilt_key, rebuilt_value
  352. def visit_dict(self, node, parent):
  353. """visit a Dict node by returning a fresh instance of it"""
  354. newnode = nodes.Dict(node.lineno, node.col_offset, parent)
  355. items = list(self._visit_dict_items(node, parent, newnode))
  356. newnode.postinit(items)
  357. return newnode
  358. def visit_dictcomp(self, node, parent):
  359. """visit a DictComp node by returning a fresh instance of it"""
  360. newnode = nodes.DictComp(node.lineno, node.col_offset, parent)
  361. newnode.postinit(self.visit(node.key, newnode),
  362. self.visit(node.value, newnode),
  363. [self.visit(child, newnode)
  364. for child in node.generators])
  365. return newnode
  366. def visit_expr(self, node, parent):
  367. """visit a Expr node by returning a fresh instance of it"""
  368. newnode = nodes.Expr(node.lineno, node.col_offset, parent)
  369. newnode.postinit(self.visit(node.value, newnode))
  370. return newnode
  371. def visit_ellipsis(self, node, parent):
  372. """visit an Ellipsis node by returning a fresh instance of it"""
  373. return nodes.Ellipsis(getattr(node, 'lineno', None),
  374. getattr(node, 'col_offset', None), parent)
  375. def visit_emptynode(self, node, parent):
  376. """visit an EmptyNode node by returning a fresh instance of it"""
  377. return nodes.EmptyNode(getattr(node, 'lineno', None),
  378. getattr(node, 'col_offset', None), parent)
  379. def visit_excepthandler(self, node, parent):
  380. """visit an ExceptHandler node by returning a fresh instance of it"""
  381. newnode = nodes.ExceptHandler(node.lineno, node.col_offset, parent)
  382. # /!\ node.name can be a tuple
  383. newnode.postinit(_visit_or_none(node, 'type', self, newnode),
  384. _visit_or_none(node, 'name', self, newnode),
  385. [self.visit(child, newnode)
  386. for child in node.body])
  387. return newnode
  388. def visit_exec(self, node, parent):
  389. """visit an Exec node by returning a fresh instance of it"""
  390. newnode = nodes.Exec(node.lineno, node.col_offset, parent)
  391. newnode.postinit(self.visit(node.body, newnode),
  392. _visit_or_none(node, 'globals', self, newnode),
  393. _visit_or_none(node, 'locals', self, newnode))
  394. return newnode
  395. def visit_extslice(self, node, parent):
  396. """visit an ExtSlice node by returning a fresh instance of it"""
  397. newnode = nodes.ExtSlice(parent=parent)
  398. newnode.postinit([self.visit(dim, newnode)
  399. for dim in node.dims])
  400. return newnode
  401. def _visit_for(self, cls, node, parent):
  402. """visit a For node by returning a fresh instance of it"""
  403. newnode = cls(node.lineno, node.col_offset, parent)
  404. newnode.postinit(self.visit(node.target, newnode),
  405. self.visit(node.iter, newnode),
  406. [self.visit(child, newnode)
  407. for child in node.body],
  408. [self.visit(child, newnode)
  409. for child in node.orelse])
  410. return newnode
  411. def visit_for(self, node, parent):
  412. return self._visit_for(nodes.For, node, parent)
  413. def visit_importfrom(self, node, parent):
  414. """visit an ImportFrom node by returning a fresh instance of it"""
  415. names = [(alias.name, alias.asname) for alias in node.names]
  416. newnode = nodes.ImportFrom(node.module or '', names, node.level or None,
  417. getattr(node, 'lineno', None),
  418. getattr(node, 'col_offset', None), parent)
  419. # store From names to add them to locals after building
  420. self._import_from_nodes.append(newnode)
  421. return newnode
  422. def _visit_functiondef(self, cls, node, parent):
  423. """visit an FunctionDef node to become astroid"""
  424. self._global_names.append({})
  425. node, doc = _get_doc(node)
  426. newnode = cls(node.name, doc, node.lineno,
  427. node.col_offset, parent)
  428. if node.decorator_list:
  429. decorators = self.visit_decorators(node, newnode)
  430. else:
  431. decorators = None
  432. if PY3 and node.returns:
  433. returns = self.visit(node.returns, newnode)
  434. else:
  435. returns = None
  436. newnode.postinit(self.visit(node.args, newnode),
  437. [self.visit(child, newnode)
  438. for child in node.body],
  439. decorators, returns)
  440. self._global_names.pop()
  441. return newnode
  442. def visit_functiondef(self, node, parent):
  443. return self._visit_functiondef(nodes.FunctionDef, node, parent)
  444. def visit_generatorexp(self, node, parent):
  445. """visit a GeneratorExp node by returning a fresh instance of it"""
  446. newnode = nodes.GeneratorExp(node.lineno, node.col_offset, parent)
  447. newnode.postinit(self.visit(node.elt, newnode),
  448. [self.visit(child, newnode)
  449. for child in node.generators])
  450. return newnode
  451. def visit_attribute(self, node, parent):
  452. """visit an Attribute node by returning a fresh instance of it"""
  453. context = _get_context(node)
  454. if context == astroid.Del:
  455. # FIXME : maybe we should reintroduce and visit_delattr ?
  456. # for instance, deactivating assign_ctx
  457. newnode = nodes.DelAttr(node.attr, node.lineno, node.col_offset,
  458. parent)
  459. elif context == astroid.Store:
  460. newnode = nodes.AssignAttr(node.attr, node.lineno, node.col_offset,
  461. parent)
  462. # Prohibit a local save if we are in an ExceptHandler.
  463. if not isinstance(parent, astroid.ExceptHandler):
  464. self._delayed_assattr.append(newnode)
  465. else:
  466. newnode = nodes.Attribute(node.attr, node.lineno, node.col_offset,
  467. parent)
  468. newnode.postinit(self.visit(node.value, newnode))
  469. return newnode
  470. def visit_global(self, node, parent):
  471. """visit a Global node to become astroid"""
  472. newnode = nodes.Global(node.names, getattr(node, 'lineno', None),
  473. getattr(node, 'col_offset', None), parent)
  474. if self._global_names: # global at the module level, no effect
  475. for name in node.names:
  476. self._global_names[-1].setdefault(name, []).append(newnode)
  477. return newnode
  478. def visit_if(self, node, parent):
  479. """visit an If node by returning a fresh instance of it"""
  480. newnode = nodes.If(node.lineno, node.col_offset, parent)
  481. newnode.postinit(self.visit(node.test, newnode),
  482. [self.visit(child, newnode)
  483. for child in node.body],
  484. [self.visit(child, newnode)
  485. for child in node.orelse])
  486. return newnode
  487. def visit_ifexp(self, node, parent):
  488. """visit a IfExp node by returning a fresh instance of it"""
  489. newnode = nodes.IfExp(node.lineno, node.col_offset, parent)
  490. newnode.postinit(self.visit(node.test, newnode),
  491. self.visit(node.body, newnode),
  492. self.visit(node.orelse, newnode))
  493. return newnode
  494. def visit_import(self, node, parent):
  495. """visit a Import node by returning a fresh instance of it"""
  496. names = [(alias.name, alias.asname) for alias in node.names]
  497. newnode = nodes.Import(names, getattr(node, 'lineno', None),
  498. getattr(node, 'col_offset', None), parent)
  499. # save import names in parent's locals:
  500. for (name, asname) in newnode.names:
  501. name = asname or name
  502. parent.set_local(name.split('.')[0], newnode)
  503. return newnode
  504. def visit_index(self, node, parent):
  505. """visit a Index node by returning a fresh instance of it"""
  506. newnode = nodes.Index(parent=parent)
  507. newnode.postinit(self.visit(node.value, newnode))
  508. return newnode
  509. def visit_keyword(self, node, parent):
  510. """visit a Keyword node by returning a fresh instance of it"""
  511. newnode = nodes.Keyword(node.arg, parent=parent)
  512. newnode.postinit(self.visit(node.value, newnode))
  513. return newnode
  514. def visit_lambda(self, node, parent):
  515. """visit a Lambda node by returning a fresh instance of it"""
  516. newnode = nodes.Lambda(node.lineno, node.col_offset, parent)
  517. newnode.postinit(self.visit(node.args, newnode),
  518. self.visit(node.body, newnode))
  519. return newnode
  520. def visit_list(self, node, parent):
  521. """visit a List node by returning a fresh instance of it"""
  522. context = _get_context(node)
  523. newnode = nodes.List(ctx=context,
  524. lineno=node.lineno,
  525. col_offset=node.col_offset,
  526. parent=parent)
  527. newnode.postinit([self.visit(child, newnode)
  528. for child in node.elts])
  529. return newnode
  530. def visit_listcomp(self, node, parent):
  531. """visit a ListComp node by returning a fresh instance of it"""
  532. newnode = nodes.ListComp(node.lineno, node.col_offset, parent)
  533. newnode.postinit(self.visit(node.elt, newnode),
  534. [self.visit(child, newnode)
  535. for child in node.generators])
  536. return newnode
  537. def visit_name(self, node, parent):
  538. """visit a Name node by returning a fresh instance of it"""
  539. context = _get_context(node)
  540. # True and False can be assigned to something in py2x, so we have to
  541. # check first the context.
  542. if context == astroid.Del:
  543. newnode = nodes.DelName(node.id, node.lineno, node.col_offset,
  544. parent)
  545. elif context == astroid.Store:
  546. newnode = nodes.AssignName(node.id, node.lineno, node.col_offset,
  547. parent)
  548. elif node.id in CONST_NAME_TRANSFORMS:
  549. newnode = nodes.Const(CONST_NAME_TRANSFORMS[node.id],
  550. getattr(node, 'lineno', None),
  551. getattr(node, 'col_offset', None), parent)
  552. return newnode
  553. else:
  554. newnode = nodes.Name(node.id, node.lineno, node.col_offset, parent)
  555. # XXX REMOVE me :
  556. if context in (astroid.Del, astroid.Store): # 'Aug' ??
  557. self._save_assignment(newnode)
  558. return newnode
  559. def visit_str(self, node, parent):
  560. """visit a String/Bytes node by returning a fresh instance of Const"""
  561. return nodes.Const(node.s, getattr(node, 'lineno', None),
  562. getattr(node, 'col_offset', None), parent)
  563. visit_bytes = visit_str
  564. def visit_num(self, node, parent):
  565. """visit a Num node by returning a fresh instance of Const"""
  566. return nodes.Const(node.n, getattr(node, 'lineno', None),
  567. getattr(node, 'col_offset', None), parent)
  568. def visit_pass(self, node, parent):
  569. """visit a Pass node by returning a fresh instance of it"""
  570. return nodes.Pass(node.lineno, node.col_offset, parent)
  571. def visit_print(self, node, parent):
  572. """visit a Print node by returning a fresh instance of it"""
  573. newnode = nodes.Print(node.nl, node.lineno, node.col_offset, parent)
  574. newnode.postinit(_visit_or_none(node, 'dest', self, newnode),
  575. [self.visit(child, newnode)
  576. for child in node.values])
  577. return newnode
  578. def visit_raise(self, node, parent):
  579. """visit a Raise node by returning a fresh instance of it"""
  580. newnode = nodes.Raise(node.lineno, node.col_offset, parent)
  581. newnode.postinit(_visit_or_none(node, 'type', self, newnode),
  582. _visit_or_none(node, 'inst', self, newnode),
  583. _visit_or_none(node, 'tback', self, newnode))
  584. return newnode
  585. def visit_return(self, node, parent):
  586. """visit a Return node by returning a fresh instance of it"""
  587. newnode = nodes.Return(node.lineno, node.col_offset, parent)
  588. if node.value is not None:
  589. newnode.postinit(self.visit(node.value, newnode))
  590. return newnode
  591. def visit_set(self, node, parent):
  592. """visit a Set node by returning a fresh instance of it"""
  593. newnode = nodes.Set(node.lineno, node.col_offset, parent)
  594. newnode.postinit([self.visit(child, newnode)
  595. for child in node.elts])
  596. return newnode
  597. def visit_setcomp(self, node, parent):
  598. """visit a SetComp node by returning a fresh instance of it"""
  599. newnode = nodes.SetComp(node.lineno, node.col_offset, parent)
  600. newnode.postinit(self.visit(node.elt, newnode),
  601. [self.visit(child, newnode)
  602. for child in node.generators])
  603. return newnode
  604. def visit_slice(self, node, parent):
  605. """visit a Slice node by returning a fresh instance of it"""
  606. newnode = nodes.Slice(parent=parent)
  607. newnode.postinit(_visit_or_none(node, 'lower', self, newnode),
  608. _visit_or_none(node, 'upper', self, newnode),
  609. _visit_or_none(node, 'step', self, newnode))
  610. return newnode
  611. def visit_subscript(self, node, parent):
  612. """visit a Subscript node by returning a fresh instance of it"""
  613. context = _get_context(node)
  614. newnode = nodes.Subscript(ctx=context,
  615. lineno=node.lineno,
  616. col_offset=node.col_offset,
  617. parent=parent)
  618. newnode.postinit(self.visit(node.value, newnode),
  619. self.visit(node.slice, newnode))
  620. return newnode
  621. def visit_tryexcept(self, node, parent):
  622. """visit a TryExcept node by returning a fresh instance of it"""
  623. newnode = nodes.TryExcept(node.lineno, node.col_offset, parent)
  624. newnode.postinit([self.visit(child, newnode)
  625. for child in node.body],
  626. [self.visit(child, newnode)
  627. for child in node.handlers],
  628. [self.visit(child, newnode)
  629. for child in node.orelse])
  630. return newnode
  631. def visit_tryfinally(self, node, parent):
  632. """visit a TryFinally node by returning a fresh instance of it"""
  633. newnode = nodes.TryFinally(node.lineno, node.col_offset, parent)
  634. newnode.postinit([self.visit(child, newnode)
  635. for child in node.body],
  636. [self.visit(n, newnode)
  637. for n in node.finalbody])
  638. return newnode
  639. def visit_tuple(self, node, parent):
  640. """visit a Tuple node by returning a fresh instance of it"""
  641. context = _get_context(node)
  642. newnode = nodes.Tuple(ctx=context,
  643. lineno=node.lineno,
  644. col_offset=node.col_offset,
  645. parent=parent)
  646. newnode.postinit([self.visit(child, newnode)
  647. for child in node.elts])
  648. return newnode
  649. def visit_unaryop(self, node, parent):
  650. """visit a UnaryOp node by returning a fresh instance of it"""
  651. newnode = nodes.UnaryOp(_UNARY_OP_CLASSES[node.op.__class__],
  652. node.lineno, node.col_offset, parent)
  653. newnode.postinit(self.visit(node.operand, newnode))
  654. return newnode
  655. def visit_while(self, node, parent):
  656. """visit a While node by returning a fresh instance of it"""
  657. newnode = nodes.While(node.lineno, node.col_offset, parent)
  658. newnode.postinit(self.visit(node.test, newnode),
  659. [self.visit(child, newnode)
  660. for child in node.body],
  661. [self.visit(child, newnode)
  662. for child in node.orelse])
  663. return newnode
  664. def visit_with(self, node, parent):
  665. newnode = nodes.With(node.lineno, node.col_offset, parent)
  666. expr = self.visit(node.context_expr, newnode)
  667. if node.optional_vars is not None:
  668. optional_vars = self.visit(node.optional_vars, newnode)
  669. else:
  670. optional_vars = None
  671. newnode.postinit([(expr, optional_vars)],
  672. [self.visit(child, newnode)
  673. for child in node.body])
  674. return newnode
  675. def visit_yield(self, node, parent):
  676. """visit a Yield node by returning a fresh instance of it"""
  677. newnode = nodes.Yield(node.lineno, node.col_offset, parent)
  678. if node.value is not None:
  679. newnode.postinit(self.visit(node.value, newnode))
  680. return newnode
  681. class TreeRebuilder3(TreeRebuilder):
  682. """extend and overwrite TreeRebuilder for python3k"""
  683. def visit_arg(self, node, parent):
  684. """visit a arg node by returning a fresh AssName instance"""
  685. # TODO(cpopa): introduce an Arg node instead of using AssignName.
  686. return self.visit_assignname(node, parent, node.arg)
  687. def visit_nameconstant(self, node, parent):
  688. # in Python 3.4 we have NameConstant for True / False / None
  689. return nodes.Const(node.value, getattr(node, 'lineno', None),
  690. getattr(node, 'col_offset', None), parent)
  691. def visit_excepthandler(self, node, parent):
  692. """visit an ExceptHandler node by returning a fresh instance of it"""
  693. newnode = nodes.ExceptHandler(node.lineno, node.col_offset, parent)
  694. if node.name:
  695. name = self.visit_assignname(node, newnode, node.name)
  696. else:
  697. name = None
  698. newnode.postinit(_visit_or_none(node, 'type', self, newnode),
  699. name,
  700. [self.visit(child, newnode)
  701. for child in node.body])
  702. return newnode
  703. def visit_nonlocal(self, node, parent):
  704. """visit a Nonlocal node and return a new instance of it"""
  705. return nodes.Nonlocal(node.names, getattr(node, 'lineno', None),
  706. getattr(node, 'col_offset', None), parent)
  707. def visit_raise(self, node, parent):
  708. """visit a Raise node by returning a fresh instance of it"""
  709. newnode = nodes.Raise(node.lineno, node.col_offset, parent)
  710. # no traceback; anyway it is not used in Pylint
  711. newnode.postinit(_visit_or_none(node, 'exc', self, newnode),
  712. _visit_or_none(node, 'cause', self, newnode))
  713. return newnode
  714. def visit_starred(self, node, parent):
  715. """visit a Starred node and return a new instance of it"""
  716. context = _get_context(node)
  717. newnode = nodes.Starred(ctx=context, lineno=node.lineno,
  718. col_offset=node.col_offset,
  719. parent=parent)
  720. newnode.postinit(self.visit(node.value, newnode))
  721. return newnode
  722. def visit_try(self, node, parent):
  723. # python 3.3 introduce a new Try node replacing
  724. # TryFinally/TryExcept nodes
  725. if node.finalbody:
  726. newnode = nodes.TryFinally(node.lineno, node.col_offset, parent)
  727. if node.handlers:
  728. body = [self.visit_tryexcept(node, newnode)]
  729. else:
  730. body = [self.visit(child, newnode)
  731. for child in node.body]
  732. newnode.postinit(body,
  733. [self.visit(n, newnode)
  734. for n in node.finalbody])
  735. return newnode
  736. elif node.handlers:
  737. return self.visit_tryexcept(node, parent)
  738. return None
  739. def visit_annassign(self, node, parent):
  740. """visit an AnnAssign node by returning a fresh instance of it"""
  741. newnode = nodes.AnnAssign(node.lineno, node.col_offset, parent)
  742. annotation = _visit_or_none(node, 'annotation', self, newnode)
  743. newnode.postinit(target=self.visit(node.target, newnode),
  744. annotation=annotation,
  745. simple=node.simple,
  746. value=_visit_or_none(node, 'value', self, newnode))
  747. return newnode
  748. def _visit_with(self, cls, node, parent):
  749. if 'items' not in node._fields:
  750. # python < 3.3
  751. return super(TreeRebuilder3, self).visit_with(node, parent)
  752. newnode = cls(node.lineno, node.col_offset, parent)
  753. def visit_child(child):
  754. expr = self.visit(child.context_expr, newnode)
  755. var = _visit_or_none(child, 'optional_vars', self, newnode)
  756. return expr, var
  757. newnode.postinit([visit_child(child) for child in node.items],
  758. [self.visit(child, newnode)
  759. for child in node.body])
  760. return newnode
  761. def visit_with(self, node, parent):
  762. return self._visit_with(nodes.With, node, parent)
  763. def visit_yieldfrom(self, node, parent):
  764. newnode = nodes.YieldFrom(node.lineno, node.col_offset, parent)
  765. if node.value is not None:
  766. newnode.postinit(self.visit(node.value, newnode))
  767. return newnode
  768. def visit_classdef(self, node, parent, newstyle=True):
  769. return super(TreeRebuilder3, self).visit_classdef(node, parent,
  770. newstyle=newstyle)
  771. # Async structs added in Python 3.5
  772. def visit_asyncfunctiondef(self, node, parent):
  773. return self._visit_functiondef(nodes.AsyncFunctionDef, node, parent)
  774. def visit_asyncfor(self, node, parent):
  775. return self._visit_for(nodes.AsyncFor, node, parent)
  776. def visit_await(self, node, parent):
  777. newnode = nodes.Await(node.lineno, node.col_offset, parent)
  778. newnode.postinit(value=self.visit(node.value, newnode))
  779. return newnode
  780. def visit_asyncwith(self, node, parent):
  781. return self._visit_with(nodes.AsyncWith, node, parent)
  782. def visit_joinedstr(self, node, parent):
  783. newnode = nodes.JoinedStr(node.lineno, node.col_offset, parent)
  784. newnode.postinit([self.visit(child, newnode)
  785. for child in node.values])
  786. return newnode
  787. def visit_formattedvalue(self, node, parent):
  788. newnode = nodes.FormattedValue(node.lineno, node.col_offset, parent)
  789. newnode.postinit(self.visit(node.value, newnode),
  790. node.conversion,
  791. _visit_or_none(node, 'format_spec', self, newnode))
  792. return newnode
  793. if sys.version_info >= (3, 0):
  794. TreeRebuilder = TreeRebuilder3