| Index: third_party/logilab/astng/rebuilder.py
|
| diff --git a/third_party/logilab/astroid/rebuilder.py b/third_party/logilab/astng/rebuilder.py
|
| similarity index 81%
|
| rename from third_party/logilab/astroid/rebuilder.py
|
| rename to third_party/logilab/astng/rebuilder.py
|
| index 8fa7ee9232bbf2035b3c005730467edcb452a5d1..bac7a0951142723a28291baf25679ccfd28ae335 100644
|
| --- a/third_party/logilab/astroid/rebuilder.py
|
| +++ b/third_party/logilab/astng/rebuilder.py
|
| @@ -1,27 +1,28 @@
|
| -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
| +# copyright 2003-2010 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
| # contact http://www.logilab.fr/ -- mailto:contact@logilab.fr
|
| +# copyright 2003-2010 Sylvain Thenault, all rights reserved.
|
| +# contact mailto:thenault@gmail.com
|
| #
|
| -# This file is part of astroid.
|
| +# This file is part of logilab-astng.
|
| #
|
| -# astroid is free software: you can redistribute it and/or modify it
|
| +# logilab-astng is free software: you can redistribute it and/or modify it
|
| # under the terms of the GNU Lesser General Public License as published by the
|
| # Free Software Foundation, either version 2.1 of the License, or (at your
|
| # option) any later version.
|
| #
|
| -# astroid is distributed in the hope that it will be useful, but
|
| +# logilab-astng is distributed in the hope that it will be useful, but
|
| # WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
| # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
| # for more details.
|
| #
|
| # You should have received a copy of the GNU Lesser General Public License along
|
| -# with astroid. If not, see <http://www.gnu.org/licenses/>.
|
| +# with logilab-astng. If not, see <http://www.gnu.org/licenses/>.
|
| """this module contains utilities for rebuilding a _ast tree in
|
| -order to get a single Astroid representation
|
| +order to get a single ASTNG representation
|
| """
|
|
|
| import sys
|
| -from _ast import (
|
| - Expr as Discard, Str,
|
| +from _ast import (Expr as Discard, Str,
|
| # binary operators
|
| Add, Div, FloorDiv, Mod, Mult, Pow, Sub, BitAnd, BitOr, BitXor,
|
| LShift, RShift,
|
| @@ -33,7 +34,8 @@ from _ast import (
|
| Eq, Gt, GtE, In, Is, IsNot, Lt, LtE, NotEq, NotIn,
|
| )
|
|
|
| -from astroid import nodes as new
|
| +from logilab.astng.exceptions import ASTNGBuildingException
|
| +from logilab.astng import nodes as new
|
|
|
|
|
| _BIN_OP_CLASSES = {Add: '+',
|
| @@ -47,18 +49,15 @@ _BIN_OP_CLASSES = {Add: '+',
|
| Pow: '**',
|
| Sub: '-',
|
| LShift: '<<',
|
| - RShift: '>>',
|
| - }
|
| + RShift: '>>'}
|
|
|
| _BOOL_OP_CLASSES = {And: 'and',
|
| - Or: 'or',
|
| - }
|
| + Or: 'or'}
|
|
|
| _UNARY_OP_CLASSES = {UAdd: '+',
|
| USub: '-',
|
| Not: 'not',
|
| - Invert: '~',
|
| - }
|
| + Invert: '~'}
|
|
|
| _CMP_OP_CLASSES = {Eq: '==',
|
| Gt: '>',
|
| @@ -69,13 +68,11 @@ _CMP_OP_CLASSES = {Eq: '==',
|
| Lt: '<',
|
| LtE: '<=',
|
| NotEq: '!=',
|
| - NotIn: 'not in',
|
| - }
|
| + NotIn: 'not in'}
|
|
|
| CONST_NAME_TRANSFORMS = {'None': None,
|
| 'True': True,
|
| - 'False': False,
|
| - }
|
| + 'False': False}
|
|
|
| REDIRECT = {'arguments': 'Arguments',
|
| 'Attribute': 'Getattr',
|
| @@ -91,9 +88,7 @@ REDIRECT = {'arguments': 'Arguments',
|
| 'ImportFrom': 'From',
|
| 'keyword': 'Keyword',
|
| 'Repr': 'Backquote',
|
| - }
|
| -PY3K = sys.version_info >= (3, 0)
|
| -PY34 = sys.version_info >= (3, 4)
|
| + }
|
|
|
| def _init_set_doc(node, newnode):
|
| newnode.doc = None
|
| @@ -121,47 +116,33 @@ def _set_infos(oldnode, newnode, parent):
|
| newnode.col_offset = oldnode.col_offset
|
| newnode.set_line_info(newnode.last_child()) # set_line_info accepts None
|
|
|
| -def _create_yield_node(node, parent, rebuilder, factory):
|
| - newnode = factory()
|
| - _lineno_parent(node, newnode, parent)
|
| - if node.value is not None:
|
| - newnode.value = rebuilder.visit(node.value, newnode)
|
| - newnode.set_line_info(newnode.last_child())
|
| - return newnode
|
| +
|
|
|
|
|
| class TreeRebuilder(object):
|
| - """Rebuilds the _ast tree to become an Astroid tree"""
|
| + """Rebuilds the _ast tree to become an ASTNG tree"""
|
| +
|
| + _visit_meths = {}
|
| + def __init__(self):
|
| + self.init()
|
|
|
| - def __init__(self, manager):
|
| - self._manager = manager
|
| + def init(self):
|
| self.asscontext = None
|
| + self._metaclass = ['']
|
| self._global_names = []
|
| self._from_nodes = []
|
| self._delayed_assattr = []
|
| - self._visit_meths = {}
|
| - self._transform = manager.transform
|
| -
|
| - def visit_module(self, node, modname, package):
|
| - """visit a Module node by returning a fresh instance of it"""
|
| - newnode = new.Module(modname, None)
|
| - newnode.package = package
|
| - _lineno_parent(node, newnode, parent=None)
|
| - _init_set_doc(node, newnode)
|
| - newnode.body = [self.visit(child, newnode) for child in node.body]
|
| - newnode.set_line_info(newnode.last_child())
|
| - return self._transform(newnode)
|
|
|
| def visit(self, node, parent):
|
| cls = node.__class__
|
| if cls in self._visit_meths:
|
| - visit_method = self._visit_meths[cls]
|
| + return self._visit_meths[cls](node, parent)
|
| else:
|
| cls_name = cls.__name__
|
| visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower()
|
| visit_method = getattr(self, visit_name)
|
| self._visit_meths[cls] = visit_method
|
| - return self._transform(visit_method(node, parent))
|
| + return visit_method(node, parent)
|
|
|
| def _save_assignment(self, node, name=None):
|
| """save assignement situation since node.parent is not available yet"""
|
| @@ -179,37 +160,13 @@ class TreeRebuilder(object):
|
| newnode.args = [self.visit(child, newnode) for child in node.args]
|
| self.asscontext = None
|
| newnode.defaults = [self.visit(child, newnode) for child in node.defaults]
|
| - newnode.kwonlyargs = []
|
| - newnode.kw_defaults = []
|
| - vararg, kwarg = node.vararg, node.kwarg
|
| - # change added in 82732 (7c5c678e4164), vararg and kwarg
|
| - # are instances of `_ast.arg`, not strings
|
| - if vararg:
|
| - if PY34:
|
| - if vararg.annotation:
|
| - newnode.varargannotation = self.visit(vararg.annotation,
|
| - newnode)
|
| - vararg = vararg.arg
|
| - elif PY3K and node.varargannotation:
|
| - newnode.varargannotation = self.visit(node.varargannotation,
|
| - newnode)
|
| - if kwarg:
|
| - if PY34:
|
| - if kwarg.annotation:
|
| - newnode.kwargannotation = self.visit(kwarg.annotation,
|
| - newnode)
|
| - kwarg = kwarg.arg
|
| - elif PY3K:
|
| - if node.kwargannotation:
|
| - newnode.kwargannotation = self.visit(node.kwargannotation,
|
| - newnode)
|
| - newnode.vararg = vararg
|
| - newnode.kwarg = kwarg
|
| + newnode.vararg = node.vararg
|
| + newnode.kwarg = node.kwarg
|
| # save argument names in locals:
|
| - if vararg:
|
| - newnode.parent.set_local(vararg, newnode)
|
| - if kwarg:
|
| - newnode.parent.set_local(kwarg, newnode)
|
| + if node.vararg:
|
| + newnode.parent.set_local(newnode.vararg, newnode)
|
| + if node.kwarg:
|
| + newnode.parent.set_local(newnode.kwarg, newnode)
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
|
|
| @@ -245,8 +202,8 @@ class TreeRebuilder(object):
|
| # set some function or metaclass infos XXX explain ?
|
| klass = newnode.parent.frame()
|
| if (isinstance(klass, new.Class)
|
| - and isinstance(newnode.value, new.CallFunc)
|
| - and isinstance(newnode.value.func, new.Name)):
|
| + and isinstance(newnode.value, new.CallFunc)
|
| + and isinstance(newnode.value.func, new.Name)):
|
| func_name = newnode.value.func.name
|
| for ass_node in newnode.targets:
|
| try:
|
| @@ -259,6 +216,9 @@ class TreeRebuilder(object):
|
| meth.extra_decorators.append(newnode.value)
|
| except (AttributeError, KeyError):
|
| continue
|
| + elif getattr(newnode.targets[0], 'name', None) == '__metaclass__':
|
| + # XXX check more...
|
| + self._metaclass[-1] = 'type' # XXX get the actual metaclass
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
|
|
| @@ -330,7 +290,8 @@ class TreeRebuilder(object):
|
| return newnode
|
|
|
| def visit_class(self, node, parent):
|
| - """visit a Class node to become astroid"""
|
| + """visit a Class node to become astng"""
|
| + self._metaclass.append(self._metaclass[-1])
|
| newnode = new.Class(node.name, None)
|
| _lineno_parent(node, newnode, parent)
|
| _init_set_doc(node, newnode)
|
| @@ -339,6 +300,11 @@ class TreeRebuilder(object):
|
| if 'decorator_list' in node._fields and node.decorator_list:# py >= 2.6
|
| newnode.decorators = self.visit_decorators(node, newnode)
|
| newnode.set_line_info(newnode.last_child())
|
| + metaclass = self._metaclass.pop()
|
| + if not newnode.bases:
|
| + # no base classes, detect new / style old style according to
|
| + # current scope
|
| + newnode._newstyle = metaclass == 'type'
|
| newnode.parent.frame().set_local(newnode.name, newnode)
|
| return newnode
|
|
|
| @@ -360,7 +326,7 @@ class TreeRebuilder(object):
|
| _lineno_parent(node, newnode, parent)
|
| newnode.left = self.visit(node.left, newnode)
|
| newnode.ops = [(_CMP_OP_CLASSES[op.__class__], self.visit(expr, newnode))
|
| - for (op, expr) in zip(node.ops, node.comparators)]
|
| + for (op, expr) in zip(node.ops, node.comparators)]
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
|
|
| @@ -379,13 +345,13 @@ class TreeRebuilder(object):
|
| def visit_decorators(self, node, parent):
|
| """visit a Decorators node by returning a fresh instance of it"""
|
| # /!\ node is actually a _ast.Function node while
|
| - # parent is a astroid.nodes.Function node
|
| + # parent is a astng.nodes.Function node
|
| newnode = new.Decorators()
|
| _lineno_parent(node, newnode, parent)
|
| if 'decorators' in node._fields: # py < 2.6, i.e. 2.5
|
| decorators = node.decorators
|
| else:
|
| - decorators = node.decorator_list
|
| + decorators= node.decorator_list
|
| newnode.nodes = [self.visit(child, newnode) for child in decorators]
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
| @@ -405,7 +371,7 @@ class TreeRebuilder(object):
|
| newnode = new.Dict()
|
| _lineno_parent(node, newnode, parent)
|
| newnode.items = [(self.visit(key, newnode), self.visit(value, newnode))
|
| - for key, value in zip(node.keys, node.values)]
|
| + for key, value in zip(node.keys, node.values)]
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
|
|
| @@ -491,14 +457,14 @@ class TreeRebuilder(object):
|
| def visit_from(self, node, parent):
|
| """visit a From node by returning a fresh instance of it"""
|
| names = [(alias.name, alias.asname) for alias in node.names]
|
| - newnode = new.From(node.module or '', names, node.level or None)
|
| + newnode = new.From(node.module or '', names, node.level)
|
| _set_infos(node, newnode, parent)
|
| # store From names to add them to locals after building
|
| self._from_nodes.append(newnode)
|
| return newnode
|
|
|
| def visit_function(self, node, parent):
|
| - """visit an Function node to become astroid"""
|
| + """visit an Function node to become astng"""
|
| self._global_names.append({})
|
| newnode = new.Function(node.name, None)
|
| _lineno_parent(node, newnode, parent)
|
| @@ -512,23 +478,21 @@ class TreeRebuilder(object):
|
| decorators = getattr(node, attr)
|
| if decorators:
|
| newnode.decorators = self.visit_decorators(node, newnode)
|
| - if PY3K and node.returns:
|
| - newnode.returns = self.visit(node.returns, newnode)
|
| newnode.set_line_info(newnode.last_child())
|
| self._global_names.pop()
|
| frame = newnode.parent.frame()
|
| if isinstance(frame, new.Class):
|
| if newnode.name == '__new__':
|
| - newnode._type = 'classmethod'
|
| + newnode.type = 'classmethod'
|
| else:
|
| - newnode._type = 'method'
|
| + newnode.type = 'method'
|
| if newnode.decorators is not None:
|
| for decorator_expr in newnode.decorators.nodes:
|
| if isinstance(decorator_expr, new.Name):
|
| if decorator_expr.name in ('classmethod', 'staticmethod'):
|
| - newnode._type = decorator_expr.name
|
| + newnode.type = decorator_expr.name
|
| elif decorator_expr.name == 'classproperty':
|
| - newnode._type = 'classmethod'
|
| + newnode.type = 'classmethod'
|
| frame.set_local(newnode.name, newnode)
|
| return newnode
|
|
|
| @@ -562,7 +526,7 @@ class TreeRebuilder(object):
|
| return newnode
|
|
|
| def visit_global(self, node, parent):
|
| - """visit an Global node to become astroid"""
|
| + """visit an Global node to become astng"""
|
| newnode = new.Global(node.names)
|
| _set_infos(node, newnode, parent)
|
| if self._global_names: # global at the module level, no effect
|
| @@ -645,6 +609,16 @@ class TreeRebuilder(object):
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
|
|
| + def visit_module(self, node, modname, package):
|
| + """visit a Module node by returning a fresh instance of it"""
|
| + newnode = new.Module(modname, None)
|
| + newnode.package = package
|
| + _lineno_parent(node, newnode, parent=None)
|
| + _init_set_doc(node, newnode)
|
| + newnode.body = [self.visit(child, newnode) for child in node.body]
|
| + newnode.set_line_info(newnode.last_child())
|
| + return newnode
|
| +
|
| def visit_name(self, node, parent):
|
| """visit a Name node by returning a fresh instance of it"""
|
| # True and False can be assigned to something in py2x, so we have to
|
| @@ -726,7 +700,7 @@ class TreeRebuilder(object):
|
| return newnode
|
|
|
| def visit_set(self, node, parent):
|
| - """visit a Set node by returning a fresh instance of it"""
|
| + """visit a Tuple node by returning a fresh instance of it"""
|
| newnode = new.Set()
|
| _lineno_parent(node, newnode, parent)
|
| newnode.elts = [self.visit(child, newnode) for child in node.elts]
|
| @@ -814,23 +788,27 @@ class TreeRebuilder(object):
|
| return newnode
|
|
|
| def visit_with(self, node, parent):
|
| + """visit a With node by returning a fresh instance of it"""
|
| newnode = new.With()
|
| _lineno_parent(node, newnode, parent)
|
| - expr = self.visit(node.context_expr, newnode)
|
| + newnode.expr = self.visit(node.context_expr, newnode)
|
| self.asscontext = "Ass"
|
| if node.optional_vars is not None:
|
| - vars = self.visit(node.optional_vars, newnode)
|
| - else:
|
| - vars = None
|
| + newnode.vars = self.visit(node.optional_vars, newnode)
|
| self.asscontext = None
|
| - newnode.items = [(expr, vars)]
|
| newnode.body = [self.visit(child, newnode) for child in node.body]
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
|
|
| def visit_yield(self, node, parent):
|
| """visit a Yield node by returning a fresh instance of it"""
|
| - return _create_yield_node(node, parent, self, new.Yield)
|
| + newnode = new.Yield()
|
| + _lineno_parent(node, newnode, parent)
|
| + if node.value is not None:
|
| + newnode.value = self.visit(node.value, newnode)
|
| + newnode.set_line_info(newnode.last_child())
|
| + return newnode
|
| +
|
|
|
| class TreeRebuilder3k(TreeRebuilder):
|
| """extend and overwrite TreeRebuilder for python3k"""
|
| @@ -838,26 +816,9 @@ class TreeRebuilder3k(TreeRebuilder):
|
| def visit_arg(self, node, parent):
|
| """visit a arg node by returning a fresh AssName instance"""
|
| # the <arg> node is coming from py>=3.0, but we use AssName in py2.x
|
| - # XXX or we should instead introduce a Arg node in astroid ?
|
| + # XXX or we should instead introduce a Arg node in astng ?
|
| return self.visit_assname(node, parent, node.arg)
|
|
|
| - def visit_nameconstant(self, node, parent):
|
| - # in Python 3.4 we have NameConstant for True / False / None
|
| - newnode = new.Const(node.value)
|
| - _set_infos(node, newnode, parent)
|
| - return newnode
|
| -
|
| - def visit_arguments(self, node, parent):
|
| - newnode = super(TreeRebuilder3k, self).visit_arguments(node, parent)
|
| - self.asscontext = "Ass"
|
| - newnode.kwonlyargs = [self.visit(child, newnode) for child in node.kwonlyargs]
|
| - self.asscontext = None
|
| - newnode.kw_defaults = [self.visit(child, newnode) if child else None for child in node.kw_defaults]
|
| - newnode.annotations = [
|
| - self.visit(arg.annotation, newnode) if arg.annotation else None
|
| - for arg in node.args]
|
| - return newnode
|
| -
|
| def visit_excepthandler(self, node, parent):
|
| """visit an ExceptHandler node by returning a fresh instance of it"""
|
| newnode = new.ExceptHandler()
|
| @@ -896,64 +857,6 @@ class TreeRebuilder3k(TreeRebuilder):
|
| newnode.set_line_info(newnode.last_child())
|
| return newnode
|
|
|
| - def visit_try(self, node, parent):
|
| - # python 3.3 introduce a new Try node replacing TryFinally/TryExcept nodes
|
| - if node.finalbody:
|
| - newnode = new.TryFinally()
|
| - _lineno_parent(node, newnode, parent)
|
| - newnode.finalbody = [self.visit(n, newnode) for n in node.finalbody]
|
| - if node.handlers:
|
| - excnode = new.TryExcept()
|
| - _lineno_parent(node, excnode, newnode)
|
| - excnode.body = [self.visit(child, excnode) for child in node.body]
|
| - excnode.handlers = [self.visit(child, excnode) for child in node.handlers]
|
| - excnode.orelse = [self.visit(child, excnode) for child in node.orelse]
|
| - excnode.set_line_info(excnode.last_child())
|
| - newnode.body = [excnode]
|
| - else:
|
| - newnode.body = [self.visit(child, newnode) for child in node.body]
|
| - elif node.handlers:
|
| - newnode = new.TryExcept()
|
| - _lineno_parent(node, newnode, parent)
|
| - newnode.body = [self.visit(child, newnode) for child in node.body]
|
| - newnode.handlers = [self.visit(child, newnode) for child in node.handlers]
|
| - newnode.orelse = [self.visit(child, newnode) for child in node.orelse]
|
| - newnode.set_line_info(newnode.last_child())
|
| - return newnode
|
| -
|
| - def visit_with(self, node, parent):
|
| - if 'items' not in node._fields:
|
| - # python < 3.3
|
| - return super(TreeRebuilder3k, self).visit_with(node, parent)
|
| -
|
| - newnode = new.With()
|
| - _lineno_parent(node, newnode, parent)
|
| - def visit_child(child):
|
| - expr = self.visit(child.context_expr, newnode)
|
| - self.asscontext = 'Ass'
|
| - if child.optional_vars:
|
| - var = self.visit(child.optional_vars, newnode)
|
| - else:
|
| - var = None
|
| - self.asscontext = None
|
| - return expr, var
|
| - newnode.items = [visit_child(child)
|
| - for child in node.items]
|
| - newnode.body = [self.visit(child, newnode) for child in node.body]
|
| - newnode.set_line_info(newnode.last_child())
|
| - return newnode
|
| -
|
| - def visit_yieldfrom(self, node, parent):
|
| - return _create_yield_node(node, parent, self, new.YieldFrom)
|
| -
|
| - def visit_class(self, node, parent):
|
| - newnode = super(TreeRebuilder3k, self).visit_class(node, parent)
|
| - newnode._newstyle = True
|
| - for keyword in node.keywords:
|
| - if keyword.arg == 'metaclass':
|
| - newnode._metaclass = self.visit(keyword, newnode).value
|
| - break
|
| - return newnode
|
|
|
| if sys.version_info >= (3, 0):
|
| TreeRebuilder = TreeRebuilder3k
|
|
|