| Index: third_party/logilab/astng/bases.py
|
| diff --git a/third_party/logilab/astroid/bases.py b/third_party/logilab/astng/bases.py
|
| similarity index 83%
|
| rename from third_party/logilab/astroid/bases.py
|
| rename to third_party/logilab/astng/bases.py
|
| index 37e613b8241494ccfd319b17ae3024453b69f00d..92f12aad7d34df630263a7c5ad8b22393b0b6d60 100644
|
| --- a/third_party/logilab/astroid/bases.py
|
| +++ b/third_party/logilab/astng/bases.py
|
| @@ -1,43 +1,43 @@
|
| -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
|
| +# -*- coding: utf-8 -*-
|
| +# copyright 2003-2011 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 base classes and functions for the nodes and some
|
| inference utils.
|
| """
|
|
|
| __docformat__ = "restructuredtext en"
|
|
|
| -import sys
|
| from contextlib import contextmanager
|
|
|
| -from astroid.exceptions import (InferenceError, AstroidError, NotFoundError,
|
| - UnresolvableName, UseInferenceDefault)
|
| +from logilab.common.compat import builtins
|
|
|
| +from logilab.astng import BUILTINS_MODULE
|
| +from logilab.astng.exceptions import InferenceError, ASTNGError, \
|
| + NotFoundError, UnresolvableName
|
| +from logilab.astng.as_string import as_string
|
|
|
| -if sys.version_info >= (3, 0):
|
| - BUILTINS = 'builtins'
|
| -else:
|
| - BUILTINS = '__builtin__'
|
| -
|
| +BUILTINS_NAME = builtins.__name__
|
|
|
| class Proxy(object):
|
| """a simple proxy object"""
|
| -
|
| - _proxied = None # proxied object may be set by class or by instance
|
| + _proxied = None
|
|
|
| def __init__(self, proxied=None):
|
| if proxied is not None:
|
| @@ -72,7 +72,7 @@ class InferenceContext(object):
|
| name = self.lookupname
|
| if (node, name) in self.path:
|
| raise StopIteration()
|
| - self.path.add((node, name))
|
| + self.path.add( (node, name) )
|
|
|
| def clone(self):
|
| # XXX copy lookupname/callcontext ?
|
| @@ -131,8 +131,6 @@ class _Yes(object):
|
| def __repr__(self):
|
| return 'YES'
|
| def __getattribute__(self, name):
|
| - if name == 'next':
|
| - raise AttributeError('next method should not be called')
|
| if name.startswith('__') and name.endswith('__'):
|
| # to avoid inspection pb
|
| return super(_Yes, self).__getattribute__(name)
|
| @@ -171,9 +169,6 @@ class Instance(Proxy):
|
| def igetattr(self, name, context=None):
|
| """inferred getattr"""
|
| try:
|
| - # avoid recursively inferring the same attr on the same class
|
| - if context:
|
| - context.push((self._proxied, name))
|
| # XXX frame should be self._proxied, or not ?
|
| get_attr = self.getattr(name, context, lookupclass=False)
|
| return _infer_stmts(self._wrap_attr(get_attr, context), context,
|
| @@ -191,7 +186,7 @@ class Instance(Proxy):
|
| """wrap bound methods of attrs in a InstanceMethod proxies"""
|
| for attr in attrs:
|
| if isinstance(attr, UnboundMethod):
|
| - if BUILTINS + '.property' in attr.decoratornames():
|
| + if BUILTINS_NAME + '.property' in attr.decoratornames():
|
| for infered in attr.infer_call_result(self, context):
|
| yield infered
|
| else:
|
| @@ -203,8 +198,6 @@ class Instance(Proxy):
|
| """infer what a class instance is returning when called"""
|
| infered = False
|
| for node in self._proxied.igetattr('__call__', context):
|
| - if node is YES:
|
| - continue
|
| for res in node.infer_call_result(caller, context):
|
| infered = True
|
| yield res
|
| @@ -258,15 +251,14 @@ class UnboundMethod(Proxy):
|
| # If we're unbound method __new__ of builtin object, the result is an
|
| # instance of the class given as first argument.
|
| if (self._proxied.name == '__new__' and
|
| - self._proxied.parent.frame().qname() == '%s.object' % BUILTINS):
|
| - infer = caller.args[0].infer() if caller.args else []
|
| - return ((x is YES and x or Instance(x)) for x in infer)
|
| + self._proxied.parent.frame().qname() == '%s.object' % BUILTINS_MODULE):
|
| + return (x is YES and x or Instance(x) for x in caller.args[0].infer())
|
| return self._proxied.infer_call_result(caller, context)
|
|
|
|
|
| class BoundMethod(UnboundMethod):
|
| """a special node representing a method bound to an instance"""
|
| - def __init__(self, proxy, bound):
|
| + def __init__(self, proxy, bound):
|
| UnboundMethod.__init__(self, proxy)
|
| self.bound = bound
|
|
|
| @@ -280,15 +272,12 @@ class BoundMethod(UnboundMethod):
|
|
|
|
|
| class Generator(Instance):
|
| - """a special node representing a generator.
|
| -
|
| - Proxied class is set once for all in raw_building.
|
| - """
|
| + """a special node representing a generator"""
|
| def callable(self):
|
| - return False
|
| + return True
|
|
|
| def pytype(self):
|
| - return '%s.generator' % BUILTINS
|
| + return '%s.generator' % BUILTINS_MODULE
|
|
|
| def display_type(self):
|
| return 'Generator'
|
| @@ -345,7 +334,7 @@ def raise_if_nothing_infered(func):
|
| # Node ######################################################################
|
|
|
| class NodeNG(object):
|
| - """Base Class for all Astroid node classes.
|
| + """Base Class for all ASTNG node classes.
|
|
|
| It represents a node of the new abstract syntax tree.
|
| """
|
| @@ -360,24 +349,7 @@ class NodeNG(object):
|
| # parent node in the tree
|
| parent = None
|
| # attributes containing child node(s) redefined in most concrete classes:
|
| - _astroid_fields = ()
|
| - # instance specific inference function infer(node, context)
|
| - _explicit_inference = None
|
| -
|
| - def infer(self, context=None, **kwargs):
|
| - """main interface to the interface system, return a generator on infered
|
| - values.
|
| -
|
| - If the instance has some explicit inference function set, it will be
|
| - called instead of the default interface.
|
| - """
|
| - if self._explicit_inference is not None:
|
| - # explicit_inference is not bound, give it self explicitly
|
| - try:
|
| - return self._explicit_inference(self, context, **kwargs)
|
| - except UseInferenceDefault:
|
| - pass
|
| - return self._infer(context, **kwargs)
|
| + _astng_fields = ()
|
|
|
| def _repr_name(self):
|
| """return self.name or self.attrname or '' for nice representation"""
|
| @@ -387,19 +359,20 @@ class NodeNG(object):
|
| return '%s(%s)' % (self.__class__.__name__, self._repr_name())
|
|
|
| def __repr__(self):
|
| - return '<%s(%s) l.%s [%s] at 0x%x>' % (self.__class__.__name__,
|
| - self._repr_name(),
|
| - self.fromlineno,
|
| - self.root().name,
|
| - id(self))
|
| + return '<%s(%s) l.%s [%s] at Ox%x>' % (self.__class__.__name__,
|
| + self._repr_name(),
|
| + self.fromlineno,
|
| + self.root().name,
|
| + id(self))
|
|
|
|
|
| def accept(self, visitor):
|
| + klass = self.__class__.__name__
|
| func = getattr(visitor, "visit_" + self.__class__.__name__.lower())
|
| return func(self)
|
|
|
| def get_children(self):
|
| - for field in self._astroid_fields:
|
| + for field in self._astng_fields:
|
| attr = getattr(self, field)
|
| if attr is None:
|
| continue
|
| @@ -411,7 +384,7 @@ class NodeNG(object):
|
|
|
| def last_child(self):
|
| """an optimized version of list(get_children())[-1]"""
|
| - for field in self._astroid_fields[::-1]:
|
| + for field in self._astng_fields[::-1]:
|
| attr = getattr(self, field)
|
| if not attr: # None or empty listy / tuple
|
| continue
|
| @@ -455,7 +428,7 @@ class NodeNG(object):
|
|
|
| def child_sequence(self, child):
|
| """search for the right sequence where the child lies in"""
|
| - for field in self._astroid_fields:
|
| + for field in self._astng_fields:
|
| node_or_sequence = getattr(self, field)
|
| if node_or_sequence is child:
|
| return [node_or_sequence]
|
| @@ -463,20 +436,20 @@ class NodeNG(object):
|
| if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
|
| return node_or_sequence
|
| else:
|
| - msg = 'Could not find %s in %s\'s children'
|
| - raise AstroidError(msg % (repr(child), repr(self)))
|
| + msg = 'Could not found %s in %s\'s children'
|
| + raise ASTNGError(msg % (repr(child), repr(self)))
|
|
|
| def locate_child(self, child):
|
| """return a 2-uple (child attribute name, sequence or node)"""
|
| - for field in self._astroid_fields:
|
| + for field in self._astng_fields:
|
| node_or_sequence = getattr(self, field)
|
| # /!\ compiler.ast Nodes have an __iter__ walking over child nodes
|
| if child is node_or_sequence:
|
| return field, child
|
| if isinstance(node_or_sequence, (tuple, list)) and child in node_or_sequence:
|
| return field, node_or_sequence
|
| - msg = 'Could not find %s in %s\'s children'
|
| - raise AstroidError(msg % (repr(child), repr(self)))
|
| + msg = 'Could not found %s in %s\'s children'
|
| + raise ASTNGError(msg % (repr(child), repr(self)))
|
| # FIXME : should we merge child_sequence and locate_child ? locate_child
|
| # is only used in are_exclusive, child_sequence one time in pylint.
|
|
|
| @@ -565,7 +538,7 @@ class NodeNG(object):
|
| # overridden for From, Import, Global, TryExcept and Arguments
|
| return None
|
|
|
| - def _infer(self, context=None):
|
| + def infer(self, context=None):
|
| """we don't know how to resolve a statement by default"""
|
| # this method is overridden by most concrete classes
|
| raise InferenceError(self.__class__.__name__)
|
| @@ -588,12 +561,15 @@ class NodeNG(object):
|
| return False
|
|
|
| def as_string(self):
|
| - from astroid.as_string import to_code
|
| - return to_code(self)
|
| + return as_string(self)
|
|
|
| def repr_tree(self, ids=False):
|
| - from astroid.as_string import dump
|
| - return dump(self)
|
| + """print a nice astng tree representation.
|
| +
|
| + :param ids: if true, we also print the ids (usefull for debugging)"""
|
| + result = []
|
| + _repr_tree(self, result, ids=ids)
|
| + return "\n".join(result)
|
|
|
|
|
| class Statement(NodeNG):
|
| @@ -615,3 +591,39 @@ class Statement(NodeNG):
|
| index = stmts.index(self)
|
| if index >= 1:
|
| return stmts[index -1]
|
| +
|
| +INDENT = " "
|
| +
|
| +def _repr_tree(node, result, indent='', _done=None, ids=False):
|
| + """built a tree representation of a node as a list of lines"""
|
| + if _done is None:
|
| + _done = set()
|
| + if not hasattr(node, '_astng_fields'): # not a astng node
|
| + return
|
| + if node in _done:
|
| + result.append( indent + 'loop in tree: %s' % node )
|
| + return
|
| + _done.add(node)
|
| + node_str = str(node)
|
| + if ids:
|
| + node_str += ' . \t%x' % id(node)
|
| + result.append( indent + node_str )
|
| + indent += INDENT
|
| + for field in node._astng_fields:
|
| + value = getattr(node, field)
|
| + if isinstance(value, (list, tuple) ):
|
| + result.append( indent + field + " = [" )
|
| + for child in value:
|
| + if isinstance(child, (list, tuple) ):
|
| + # special case for Dict # FIXME
|
| + _repr_tree(child[0], result, indent, _done, ids)
|
| + _repr_tree(child[1], result, indent, _done, ids)
|
| + result.append(indent + ',')
|
| + else:
|
| + _repr_tree(child, result, indent, _done, ids)
|
| + result.append( indent + "]" )
|
| + else:
|
| + result.append( indent + field + " = " )
|
| + _repr_tree(value, result, indent, _done, ids)
|
| +
|
| +
|
|
|