| Index: third_party/logilab/astng/scoped_nodes.py
 | 
| diff --git a/third_party/logilab/astroid/scoped_nodes.py b/third_party/logilab/astng/scoped_nodes.py
 | 
| similarity index 67%
 | 
| rename from third_party/logilab/astroid/scoped_nodes.py
 | 
| rename to third_party/logilab/astng/scoped_nodes.py
 | 
| index eb60298f6a5fe345dbc9766f763beb4c10ba570d..52b97465933daa66559efe141ab5c518d2eaf417 100644
 | 
| --- a/third_party/logilab/astroid/scoped_nodes.py
 | 
| +++ b/third_party/logilab/astng/scoped_nodes.py
 | 
| @@ -1,20 +1,22 @@
 | 
| -# copyright 2003-2013 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
 | 
| +# 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 the classes for "scoped" node, i.e. which are opening a
 | 
|  new local scope in the language definition : Module, Class, Function (and
 | 
|  Lambda, GenExpr, DictComp and SetComp to some extent).
 | 
| @@ -25,28 +27,22 @@ __doctype__ = "restructuredtext en"
 | 
|  
 | 
|  import sys
 | 
|  from itertools import chain
 | 
| -try:
 | 
| -    from io import BytesIO
 | 
| -except ImportError:
 | 
| -    from cStringIO import StringIO as BytesIO
 | 
|  
 | 
|  from logilab.common.compat import builtins
 | 
| -from logilab.common.decorators import cached, cachedproperty
 | 
| -
 | 
| -from astroid.exceptions import NotFoundError, \
 | 
| -     AstroidBuildingException, InferenceError
 | 
| -from astroid.node_classes import Const, DelName, DelAttr, \
 | 
| -     Dict, From, List, Pass, Raise, Return, Tuple, Yield, YieldFrom, \
 | 
| -     LookupMixIn, const_factory as cf, unpack_infer, Name, CallFunc
 | 
| -from astroid.bases import NodeNG, InferenceContext, Instance,\
 | 
| +from logilab.common.decorators import cached
 | 
| +
 | 
| +from logilab.astng import BUILTINS_MODULE
 | 
| +from logilab.astng.exceptions import NotFoundError, NoDefault, \
 | 
| +     ASTNGBuildingException, InferenceError
 | 
| +from logilab.astng.node_classes import Const, DelName, DelAttr, \
 | 
| +     Dict, From, List, Name, Pass, Raise, Return, Tuple, Yield, \
 | 
| +     are_exclusive, LookupMixIn, const_factory as cf, unpack_infer
 | 
| +from logilab.astng.bases import NodeNG, InferenceContext, Instance,\
 | 
|       YES, Generator, UnboundMethod, BoundMethod, _infer_stmts, copy_context, \
 | 
| -     BUILTINS
 | 
| -from astroid.mixins import FilterStmtsMixin
 | 
| -from astroid.bases import Statement
 | 
| -from astroid.manager import AstroidManager
 | 
| -
 | 
| -ITER_METHODS = ('__iter__', '__getitem__')
 | 
| -PY3K = sys.version_info >= (3, 0)
 | 
| +     BUILTINS_NAME
 | 
| +from logilab.astng.mixins import FilterStmtsMixin
 | 
| +from logilab.astng.bases import Statement
 | 
| +from logilab.astng.manager import ASTNGManager
 | 
|  
 | 
|  
 | 
|  def remove_nodes(func, cls):
 | 
| @@ -79,20 +75,20 @@ def std_special_attributes(self, name, add_locals=True):
 | 
|          return [Dict()] + locals.get(name, [])
 | 
|      raise NotFoundError(name)
 | 
|  
 | 
| -MANAGER = AstroidManager()
 | 
| +MANAGER = ASTNGManager()
 | 
|  def builtin_lookup(name):
 | 
|      """lookup a name into the builtin module
 | 
| -    return the list of matching statements and the astroid for the builtin
 | 
| +    return the list of matching statements and the astng for the builtin
 | 
|      module
 | 
|      """
 | 
| -    builtin_astroid = MANAGER.ast_from_module(builtins)
 | 
| +    builtin_astng = MANAGER.astng_from_module(builtins)
 | 
|      if name == '__dict__':
 | 
| -        return builtin_astroid, ()
 | 
| +        return builtin_astng, ()
 | 
|      try:
 | 
| -        stmts = builtin_astroid.locals[name]
 | 
| +        stmts = builtin_astng.locals[name]
 | 
|      except KeyError:
 | 
|          stmts = ()
 | 
| -    return builtin_astroid, stmts
 | 
| +    return builtin_astng, stmts
 | 
|  
 | 
|  
 | 
|  # TODO move this Mixin to mixins.py; problem: 'Function' in _scope_lookup
 | 
| @@ -214,24 +210,19 @@ class LocalsDictNodeNG(LookupMixIn, NodeNG):
 | 
|  # Module  #####################################################################
 | 
|  
 | 
|  class Module(LocalsDictNodeNG):
 | 
| -    _astroid_fields = ('body',)
 | 
| +    _astng_fields = ('body',)
 | 
|  
 | 
|      fromlineno = 0
 | 
|      lineno = 0
 | 
|  
 | 
|      # attributes below are set by the builder module or by raw factories
 | 
|  
 | 
| -    # the file from which as been extracted the astroid representation. It may
 | 
| +    # the file from which as been extracted the astng representation. It may
 | 
|      # be None if the representation has been built from a built-in module
 | 
|      file = None
 | 
| -    # Alternatively, if built from a string/bytes, this can be set
 | 
| -    file_bytes = None
 | 
| -    # encoding of python source file, so we can get unicode out of it (python2
 | 
| -    # only)
 | 
| -    file_encoding = None
 | 
|      # the module name
 | 
|      name = None
 | 
| -    # boolean for astroid built from source (i.e. ast)
 | 
| +    # boolean for astng built from source (i.e. ast)
 | 
|      pure_python = None
 | 
|      # boolean for package module
 | 
|      package = None
 | 
| @@ -239,9 +230,6 @@ class Module(LocalsDictNodeNG):
 | 
|      # as value
 | 
|      globals = None
 | 
|  
 | 
| -    # Future imports
 | 
| -    future_imports = None
 | 
| -
 | 
|      # names of python special attributes (handled by getattr impl.)
 | 
|      special_attributes = set(('__name__', '__doc__', '__file__', '__path__',
 | 
|                                '__dict__'))
 | 
| @@ -254,14 +242,11 @@ class Module(LocalsDictNodeNG):
 | 
|          self.pure_python = pure_python
 | 
|          self.locals = self.globals = {}
 | 
|          self.body = []
 | 
| -        self.future_imports = set()
 | 
|  
 | 
|      @property
 | 
|      def file_stream(self):
 | 
| -        if self.file_bytes is not None:
 | 
| -            return BytesIO(self.file_bytes)
 | 
|          if self.file is not None:
 | 
| -            return open(self.file, 'rb')
 | 
| +            return file(self.file)
 | 
|          return None
 | 
|  
 | 
|      def block_range(self, lineno):
 | 
| @@ -280,7 +265,7 @@ class Module(LocalsDictNodeNG):
 | 
|          return self._scope_lookup(node, name, offset)
 | 
|  
 | 
|      def pytype(self):
 | 
| -        return '%s.module' % BUILTINS
 | 
| +        return '%s.module' % BUILTINS_MODULE
 | 
|  
 | 
|      def display_type(self):
 | 
|          return 'Module'
 | 
| @@ -297,9 +282,7 @@ class Module(LocalsDictNodeNG):
 | 
|          if self.package:
 | 
|              try:
 | 
|                  return [self.import_module(name, relative_only=True)]
 | 
| -            except AstroidBuildingException:
 | 
| -                raise NotFoundError(name)
 | 
| -            except SyntaxError:
 | 
| +            except ASTNGBuildingException:
 | 
|                  raise NotFoundError(name)
 | 
|              except Exception:# XXX pylint tests never pass here; do we need it?
 | 
|                  import traceback
 | 
| @@ -353,13 +336,13 @@ class Module(LocalsDictNodeNG):
 | 
|              level = 0
 | 
|          absmodname = self.relative_to_absolute_name(modname, level)
 | 
|          try:
 | 
| -            return MANAGER.ast_from_module_name(absmodname)
 | 
| -        except AstroidBuildingException:
 | 
| +            return MANAGER.astng_from_module_name(absmodname)
 | 
| +        except ASTNGBuildingException:
 | 
|              # we only want to import a sub module or package of this module,
 | 
|              # skip here
 | 
|              if relative_only:
 | 
|                  raise
 | 
| -        return MANAGER.ast_from_module_name(modname)
 | 
| +        return MANAGER.astng_from_module_name(modname)
 | 
|  
 | 
|      def relative_to_absolute_name(self, modname, level):
 | 
|          """return the absolute module name for a relative import.
 | 
| @@ -367,7 +350,7 @@ class Module(LocalsDictNodeNG):
 | 
|          The relative import can be implicit or explicit.
 | 
|          """
 | 
|          # XXX this returns non sens when called on an absolute import
 | 
| -        # like 'pylint.checkers.astroid.utils'
 | 
| +        # like 'pylint.checkers.logilab.astng.utils'
 | 
|          # XXX doesn't return absolute name if self.name isn't absolute name
 | 
|          if self.absolute_import_activated() and level is None:
 | 
|              return modname
 | 
| @@ -404,7 +387,7 @@ class Module(LocalsDictNodeNG):
 | 
|              except AttributeError:
 | 
|                  return [name for name in living.__dict__.keys()
 | 
|                          if not name.startswith('_')]
 | 
| -        # else lookup the astroid
 | 
| +        # else lookup the astng
 | 
|          #
 | 
|          # We separate the different steps of lookup in try/excepts
 | 
|          # to avoid catching too many Exceptions
 | 
| @@ -436,7 +419,7 @@ class ComprehensionScope(LocalsDictNodeNG):
 | 
|  
 | 
|  
 | 
|  class GenExpr(ComprehensionScope):
 | 
| -    _astroid_fields = ('elt', 'generators')
 | 
| +    _astng_fields = ('elt', 'generators')
 | 
|  
 | 
|      def __init__(self):
 | 
|          self.locals = {}
 | 
| @@ -445,7 +428,7 @@ class GenExpr(ComprehensionScope):
 | 
|  
 | 
|  
 | 
|  class DictComp(ComprehensionScope):
 | 
| -    _astroid_fields = ('key', 'value', 'generators')
 | 
| +    _astng_fields = ('key', 'value', 'generators')
 | 
|  
 | 
|      def __init__(self):
 | 
|          self.locals = {}
 | 
| @@ -455,7 +438,7 @@ class DictComp(ComprehensionScope):
 | 
|  
 | 
|  
 | 
|  class SetComp(ComprehensionScope):
 | 
| -    _astroid_fields = ('elt', 'generators')
 | 
| +    _astng_fields = ('elt', 'generators')
 | 
|  
 | 
|      def __init__(self):
 | 
|          self.locals = {}
 | 
| @@ -465,7 +448,7 @@ class SetComp(ComprehensionScope):
 | 
|  
 | 
|  class _ListComp(NodeNG):
 | 
|      """class representing a ListComp node"""
 | 
| -    _astroid_fields = ('elt', 'generators')
 | 
| +    _astng_fields = ('elt', 'generators')
 | 
|      elt = None
 | 
|      generators = None
 | 
|  
 | 
| @@ -480,85 +463,9 @@ else:
 | 
|  
 | 
|  # Function  ###################################################################
 | 
|  
 | 
| -def _infer_decorator_callchain(node):
 | 
| -    """ Detect decorator call chaining and see if the
 | 
| -    end result is a static or a classmethod.
 | 
| -    """
 | 
| -    current = node
 | 
| -    while True:
 | 
| -        if isinstance(current, CallFunc):
 | 
| -            try:
 | 
| -                current = current.func.infer().next()
 | 
| -            except InferenceError:
 | 
| -                return
 | 
| -        elif isinstance(current, Function):
 | 
| -            if not current.parent:
 | 
| -                return
 | 
| -            try:
 | 
| -                # TODO: We don't handle multiple inference results right now,
 | 
| -                #       because there's no flow to reason when the return
 | 
| -                #       is what we are looking for, a static or a class method.
 | 
| -                result = current.infer_call_result(current.parent).next()
 | 
| -            except (StopIteration, InferenceError):
 | 
| -                return
 | 
| -            if isinstance(result, (Function, CallFunc)):
 | 
| -                current = result
 | 
| -            else:
 | 
| -                if isinstance(result, Instance):
 | 
| -                    result = result._proxied
 | 
| -                if isinstance(result, Class):
 | 
| -                    if (result.name == 'classmethod' and
 | 
| -                            result.root().name == BUILTINS):
 | 
| -                        return 'classmethod'
 | 
| -                    elif (result.name == 'staticmethod' and
 | 
| -                          result.root().name == BUILTINS):
 | 
| -                        return 'staticmethod'
 | 
| -                    else:
 | 
| -                        return
 | 
| -                else:
 | 
| -                    # We aren't interested in anything else returned,
 | 
| -                    # so go back to the function type inference.
 | 
| -                    return
 | 
| -        else:
 | 
| -            return
 | 
| -
 | 
| -def _function_type(self):
 | 
| -    """
 | 
| -    Function type, possible values are:
 | 
| -    method, function, staticmethod, classmethod.
 | 
| -    """
 | 
| -    # Can't infer that this node is decorated
 | 
| -    # with a subclass of `classmethod` where `type` is first set,
 | 
| -    # so do it here.
 | 
| -    if self.decorators:
 | 
| -        for node in self.decorators.nodes:
 | 
| -            if isinstance(node, CallFunc):
 | 
| -                _type = _infer_decorator_callchain(node)
 | 
| -                if _type is None:
 | 
| -                    continue
 | 
| -                else:
 | 
| -                    return _type
 | 
| -            if not isinstance(node, Name):
 | 
| -                continue
 | 
| -            try:
 | 
| -                for infered in node.infer():
 | 
| -                    if not isinstance(infered, Class):
 | 
| -                        continue
 | 
| -                    for ancestor in infered.ancestors():
 | 
| -                        if isinstance(ancestor, Class):
 | 
| -                            if (ancestor.name == 'classmethod' and
 | 
| -                                    ancestor.root().name == BUILTINS):
 | 
| -                                return 'classmethod'
 | 
| -                            elif (ancestor.name == 'staticmethod' and
 | 
| -                                  ancestor.root().name == BUILTINS):
 | 
| -                                return 'staticmethod'
 | 
| -            except InferenceError:
 | 
| -                pass
 | 
| -    return self._type
 | 
| -
 | 
|  
 | 
|  class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
 | 
| -    _astroid_fields = ('args', 'body',)
 | 
| +    _astng_fields = ('args', 'body',)
 | 
|      name = '<lambda>'
 | 
|  
 | 
|      # function's type, 'function' | 'method' | 'staticmethod' | 'classmethod'
 | 
| @@ -571,8 +478,8 @@ class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
 | 
|  
 | 
|      def pytype(self):
 | 
|          if 'method' in self.type:
 | 
| -            return '%s.instancemethod' % BUILTINS
 | 
| -        return '%s.function' % BUILTINS
 | 
| +            return '%s.instancemethod' % BUILTINS_MODULE
 | 
| +        return '%s.function' % BUILTINS_MODULE
 | 
|  
 | 
|      def display_type(self):
 | 
|          if 'method' in self.type:
 | 
| @@ -599,7 +506,7 @@ class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
 | 
|          return self.body.infer(context)
 | 
|  
 | 
|      def scope_lookup(self, node, name, offset=0):
 | 
| -        if node in self.args.defaults or node in self.args.kw_defaults:
 | 
| +        if node in self.args.defaults:
 | 
|              frame = self.parent.frame()
 | 
|              # line offset to avoid that def func(f=func) resolve the default
 | 
|              # value to the defined function
 | 
| @@ -611,19 +518,13 @@ class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
 | 
|  
 | 
|  
 | 
|  class Function(Statement, Lambda):
 | 
| -    if PY3K:
 | 
| -        _astroid_fields = ('decorators', 'args', 'body', 'returns')
 | 
| -        returns = None
 | 
| -    else:
 | 
| -        _astroid_fields = ('decorators', 'args', 'body')
 | 
| +    _astng_fields = ('decorators', 'args', 'body')
 | 
|  
 | 
|      special_attributes = set(('__name__', '__doc__', '__dict__'))
 | 
|      is_function = True
 | 
|      # attributes below are set by the builder module or by raw factories
 | 
|      blockstart_tolineno = None
 | 
|      decorators = None
 | 
| -    _type = "function"
 | 
| -    type = cachedproperty(_function_type)
 | 
|  
 | 
|      def __init__(self, name, doc):
 | 
|          self.locals = {}
 | 
| @@ -639,10 +540,7 @@ class Function(Statement, Lambda):
 | 
|          self.fromlineno = self.lineno
 | 
|          # lineno is the line number of the first decorator, we want the def statement lineno
 | 
|          if self.decorators is not None:
 | 
| -            self.fromlineno += sum(node.tolineno - node.lineno + 1
 | 
| -                                   for node in self.decorators.nodes)
 | 
| -        if self.args.fromlineno < self.fromlineno:
 | 
| -            self.args.fromlineno = self.fromlineno
 | 
| +            self.fromlineno += len(self.decorators.nodes)
 | 
|          self.tolineno = lastchild.tolineno
 | 
|          self.blockstart_tolineno = self.args.tolineno
 | 
|  
 | 
| @@ -687,23 +585,10 @@ class Function(Statement, Lambda):
 | 
|          return self.type == 'classmethod'
 | 
|  
 | 
|      def is_abstract(self, pass_is_abstract=True):
 | 
| -        """Returns True if the method is abstract.
 | 
| -
 | 
| -        A method is considered abstract if
 | 
| -         - the only statement is 'raise NotImplementedError', or
 | 
| -         - the only statement is 'pass' and pass_is_abstract is True, or
 | 
| -         - the method is annotated with abc.astractproperty/abc.abstractmethod
 | 
| +        """return true if the method is abstract
 | 
| +        It's considered as abstract if the only statement is a raise of
 | 
| +        NotImplementError, or, if pass_is_abstract, a pass statement
 | 
|          """
 | 
| -        if self.decorators:
 | 
| -            for node in self.decorators.nodes:
 | 
| -                try:
 | 
| -                    infered = node.infer().next()
 | 
| -                except InferenceError:
 | 
| -                    continue
 | 
| -                if infered and infered.qname() in ('abc.abstractproperty',
 | 
| -                                                   'abc.abstractmethod'):
 | 
| -                    return True
 | 
| -
 | 
|          for child_node in self.body:
 | 
|              if isinstance(child_node, Raise):
 | 
|                  if child_node.raises_not_implemented():
 | 
| @@ -719,15 +604,14 @@ class Function(Statement, Lambda):
 | 
|          """return true if this is a generator function"""
 | 
|          # XXX should be flagged, not computed
 | 
|          try:
 | 
| -            return self.nodes_of_class((Yield, YieldFrom),
 | 
| -                                       skip_klass=(Function, Lambda)).next()
 | 
| +            return self.nodes_of_class(Yield, skip_klass=Function).next()
 | 
|          except StopIteration:
 | 
|              return False
 | 
|  
 | 
|      def infer_call_result(self, caller, context=None):
 | 
|          """infer what a function is returning when called"""
 | 
|          if self.is_generator():
 | 
| -            yield Generator()
 | 
| +            yield Generator(self)
 | 
|              return
 | 
|          returns = self.nodes_of_class(Return, skip_klass=Function)
 | 
|          for returnnode in returns:
 | 
| @@ -755,40 +639,6 @@ def _rec_get_names(args, names=None):
 | 
|  
 | 
|  # Class ######################################################################
 | 
|  
 | 
| -
 | 
| -def _is_metaclass(klass, seen=None):
 | 
| -    """ Return if the given class can be
 | 
| -    used as a metaclass.
 | 
| -    """
 | 
| -    if klass.name == 'type':
 | 
| -        return True
 | 
| -    if seen is None:
 | 
| -        seen = set()
 | 
| -    for base in klass.bases:
 | 
| -        try:
 | 
| -            for baseobj in base.infer():
 | 
| -                if baseobj in seen:
 | 
| -                    continue
 | 
| -                else:
 | 
| -                    seen.add(baseobj)
 | 
| -                if isinstance(baseobj, Instance):
 | 
| -                    # not abstract
 | 
| -                    return False
 | 
| -                if baseobj is YES:
 | 
| -                    continue
 | 
| -                if baseobj is klass:
 | 
| -                    continue
 | 
| -                if not isinstance(baseobj, Class):
 | 
| -                    continue
 | 
| -                if baseobj._type == 'metaclass':
 | 
| -                    return True
 | 
| -                if _is_metaclass(baseobj, seen):
 | 
| -                    return True
 | 
| -        except InferenceError:
 | 
| -            continue
 | 
| -    return False
 | 
| -
 | 
| -
 | 
|  def _class_type(klass, ancestors=None):
 | 
|      """return a Class node type to differ metaclass, interface and exception
 | 
|      from 'regular' classes
 | 
| @@ -796,7 +646,7 @@ def _class_type(klass, ancestors=None):
 | 
|      # XXX we have to store ancestors in case we have a ancestor loop
 | 
|      if klass._type is not None:
 | 
|          return klass._type
 | 
| -    if _is_metaclass(klass):
 | 
| +    if klass.name == 'type':
 | 
|          klass._type = 'metaclass'
 | 
|      elif klass.name.endswith('Interface'):
 | 
|          klass._type = 'interface'
 | 
| @@ -812,12 +662,7 @@ def _class_type(klass, ancestors=None):
 | 
|          ancestors.add(klass)
 | 
|          # print >> sys.stderr, '_class_type', repr(klass)
 | 
|          for base in klass.ancestors(recurs=False):
 | 
| -            name = _class_type(base, ancestors)
 | 
| -            if name != 'class':
 | 
| -                if name == 'metaclass' and not _is_metaclass(klass):
 | 
| -                    # don't propagate it if the current class
 | 
| -                    # can't be a metaclass
 | 
| -                    continue
 | 
| +            if _class_type(base, ancestors) != 'class':
 | 
|                  klass._type = base.type
 | 
|                  break
 | 
|      if klass._type is None:
 | 
| @@ -837,7 +682,7 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|      # by a raw factories
 | 
|  
 | 
|      # a dictionary of class instances attributes
 | 
| -    _astroid_fields = ('decorators', 'bases', 'body') # name
 | 
| +    _astng_fields = ('decorators', 'bases', 'body') # name
 | 
|  
 | 
|      decorators = None
 | 
|      special_attributes = set(('__name__', '__doc__', '__dict__', '__module__',
 | 
| @@ -866,11 +711,6 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|              if base._newstyle_impl(context):
 | 
|                  self._newstyle = True
 | 
|                  break
 | 
| -        klass = self._explicit_metaclass()
 | 
| -        # could be any callable, we'd need to infer the result of klass(name,
 | 
| -        # bases, dict).  punt if it's not a class node.
 | 
| -        if klass is not None and isinstance(klass, Class):
 | 
| -            self._newstyle = klass._newstyle_impl(context)
 | 
|          if self._newstyle is None:
 | 
|              self._newstyle = False
 | 
|          return self._newstyle
 | 
| @@ -896,8 +736,8 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|  
 | 
|      def pytype(self):
 | 
|          if self.newstyle:
 | 
| -            return '%s.type' % BUILTINS
 | 
| -        return '%s.classobj' % BUILTINS
 | 
| +            return '%s.type' % BUILTINS_MODULE
 | 
| +        return '%s.classobj' % BUILTINS_MODULE
 | 
|  
 | 
|      def display_type(self):
 | 
|          return 'Class'
 | 
| @@ -905,36 +745,9 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|      def callable(self):
 | 
|          return True
 | 
|  
 | 
| -    def _is_subtype_of(self, type_name):
 | 
| -        if self.qname() == type_name:
 | 
| -            return True
 | 
| -        for anc in self.ancestors():
 | 
| -            if anc.qname() == type_name:
 | 
| -                return True
 | 
| -
 | 
|      def infer_call_result(self, caller, context=None):
 | 
|          """infer what a class is returning when called"""
 | 
| -        if self._is_subtype_of('%s.type' % (BUILTINS,)) and len(caller.args) == 3:
 | 
| -            name_node = caller.args[0].infer().next()
 | 
| -            if isinstance(name_node, Const) and isinstance(name_node.value, basestring):
 | 
| -                name = name_node.value
 | 
| -            else:
 | 
| -                yield YES
 | 
| -                return
 | 
| -            result = Class(name, None)
 | 
| -            bases = caller.args[1].infer().next()
 | 
| -            if isinstance(bases, (Tuple, List)):
 | 
| -                result.bases = bases.itered()
 | 
| -            else:
 | 
| -                # There is currently no AST node that can represent an 'unknown'
 | 
| -                # node (YES is not an AST node), therefore we simply return YES here
 | 
| -                # although we know at least the name of the class.
 | 
| -                yield YES
 | 
| -                return
 | 
| -            result.parent = caller.parent
 | 
| -            yield result
 | 
| -        else:
 | 
| -            yield Instance(self)
 | 
| +        yield Instance(self)
 | 
|  
 | 
|      def scope_lookup(self, node, name, offset=0):
 | 
|          if node in self.bases:
 | 
| @@ -971,11 +784,8 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|                  try:
 | 
|                      for baseobj in stmt.infer(context):
 | 
|                          if not isinstance(baseobj, Class):
 | 
| -                            if isinstance(baseobj, Instance):
 | 
| -                                baseobj = baseobj._proxied
 | 
| -                            else:
 | 
| -                                # duh ?
 | 
| -                                continue
 | 
| +                            # duh ?
 | 
| +                            continue
 | 
|                          if baseobj in yielded:
 | 
|                              continue # cf xxx above
 | 
|                          yielded.add(baseobj)
 | 
| @@ -991,20 +801,20 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|                      continue
 | 
|  
 | 
|      def local_attr_ancestors(self, name, context=None):
 | 
| -        """return an iterator on astroid representation of parent classes
 | 
| +        """return an iterator on astng representation of parent classes
 | 
|          which have <name> defined in their locals
 | 
|          """
 | 
| -        for astroid in self.ancestors(context=context):
 | 
| -            if name in astroid:
 | 
| -                yield astroid
 | 
| +        for astng in self.ancestors(context=context):
 | 
| +            if name in astng:
 | 
| +                yield astng
 | 
|  
 | 
|      def instance_attr_ancestors(self, name, context=None):
 | 
| -        """return an iterator on astroid representation of parent classes
 | 
| +        """return an iterator on astng representation of parent classes
 | 
|          which have <name> defined in their instance attribute dictionary
 | 
|          """
 | 
| -        for astroid in self.ancestors(context=context):
 | 
| -            if name in astroid.instance_attrs:
 | 
| -                yield astroid
 | 
| +        for astng in self.ancestors(context=context):
 | 
| +            if name in astng.instance_attrs:
 | 
| +                yield astng
 | 
|  
 | 
|      def has_base(self, node):
 | 
|          return node in self.bases
 | 
| @@ -1027,16 +837,14 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|      local_attr = remove_nodes(local_attr, DelAttr)
 | 
|  
 | 
|      def instance_attr(self, name, context=None):
 | 
| -        """return the astroid nodes associated to name in this class instance
 | 
| +        """return the astng nodes associated to name in this class instance
 | 
|          attributes dictionary and in its parents
 | 
|  
 | 
|          :raises `NotFoundError`:
 | 
|            if no attribute with this name has been find in this class or
 | 
|            its parent classes
 | 
|          """
 | 
| -        # Return a copy, so we don't modify self.instance_attrs,
 | 
| -        # which could lead to infinite loop.
 | 
| -        values = list(self.instance_attrs.get(name, []))
 | 
| +        values = self.instance_attrs.get(name, [])
 | 
|          # get all values from parents
 | 
|          for class_node in self.instance_attr_ancestors(name, context):
 | 
|              values += class_node.instance_attrs[name]
 | 
| @@ -1060,14 +868,15 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|          if name in self.special_attributes:
 | 
|              if name == '__module__':
 | 
|                  return [cf(self.root().qname())] + values
 | 
| -            # FIXME: do we really need the actual list of ancestors?
 | 
| -            # returning [Tuple()] + values don't break any test
 | 
| +            # FIXME : what is expected by passing the list of ancestors to cf:
 | 
| +            # you can just do [cf(tuple())] + values without breaking any test
 | 
|              # this is ticket http://www.logilab.org/ticket/52785
 | 
| +            if name == '__bases__':
 | 
| +                return [cf(tuple(self.ancestors(recurs=False, context=context)))] + values
 | 
|              # XXX need proper meta class handling + MRO implementation
 | 
| -            if name == '__bases__' or (name == '__mro__' and self.newstyle):
 | 
| -                node = Tuple()
 | 
| -                node.items = self.ancestors(recurs=True, context=context)
 | 
| -                return [node] + values
 | 
| +            if name == '__mro__' and self.newstyle:
 | 
| +                # XXX mro is read-only but that's not our job to detect that
 | 
| +                return [cf(tuple(self.ancestors(recurs=True, context=context)))] + values
 | 
|              return std_special_attributes(self, name)
 | 
|          # don't modify the list in self.locals!
 | 
|          values = list(values)
 | 
| @@ -1119,7 +928,7 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|              #if self.newstyle: XXX cause an infinite recursion error
 | 
|              try:
 | 
|                  getattribute = self.getattr('__getattribute__', context)[0]
 | 
| -                if getattribute.root().name != BUILTINS:
 | 
| +                if getattribute.root().name != BUILTINS_NAME:
 | 
|                      # class has a custom __getattribute__ defined
 | 
|                      return True
 | 
|              except NotFoundError:
 | 
| @@ -1131,8 +940,8 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|          its ancestors
 | 
|          """
 | 
|          done = {}
 | 
| -        for astroid in chain(iter((self,)), self.ancestors()):
 | 
| -            for meth in astroid.mymethods():
 | 
| +        for astng in chain(iter((self,)), self.ancestors()):
 | 
| +            for meth in astng.mymethods():
 | 
|                  if meth.name in done:
 | 
|                      continue
 | 
|                  done[meth.name] = None
 | 
| @@ -1166,112 +975,3 @@ class Class(Statement, LocalsDictNodeNG, FilterStmtsMixin):
 | 
|                  yield iface
 | 
|          if missing:
 | 
|              raise InferenceError()
 | 
| -
 | 
| -    _metaclass = None
 | 
| -    def _explicit_metaclass(self):
 | 
| -        """ Return the explicit defined metaclass
 | 
| -        for the current class.
 | 
| -
 | 
| -        An explicit defined metaclass is defined
 | 
| -        either by passing the ``metaclass`` keyword argument
 | 
| -        in the class definition line (Python 3) or (Python 2) by
 | 
| -        having a ``__metaclass__`` class attribute, or if there are
 | 
| -        no explicit bases but there is a global ``__metaclass__`` variable.
 | 
| -        """
 | 
| -        if self._metaclass:
 | 
| -            # Expects this from Py3k TreeRebuilder
 | 
| -            try:
 | 
| -                return next(node for node in self._metaclass.infer()
 | 
| -                            if node is not YES)
 | 
| -            except (InferenceError, StopIteration):
 | 
| -                return None
 | 
| -        if sys.version_info >= (3, ):
 | 
| -            return None
 | 
| -
 | 
| -        if '__metaclass__' in self.locals:
 | 
| -            assignment = self.locals['__metaclass__'][-1]
 | 
| -        elif self.bases:
 | 
| -            return None
 | 
| -        elif '__metaclass__' in self.root().locals:
 | 
| -            assignments = [ass for ass in self.root().locals['__metaclass__']
 | 
| -                           if ass.lineno < self.lineno]
 | 
| -            if not assignments:
 | 
| -                return None
 | 
| -            assignment = assignments[-1]
 | 
| -        else:
 | 
| -            return None
 | 
| -
 | 
| -        try:
 | 
| -            infered = assignment.infer().next()
 | 
| -        except InferenceError:
 | 
| -            return
 | 
| -        if infered is YES: # don't expose this
 | 
| -            return None
 | 
| -        return infered
 | 
| -
 | 
| -    def metaclass(self):
 | 
| -        """ Return the metaclass of this class.
 | 
| -
 | 
| -        If this class does not define explicitly a metaclass,
 | 
| -        then the first defined metaclass in ancestors will be used
 | 
| -        instead.
 | 
| -        """
 | 
| -        klass = self._explicit_metaclass()
 | 
| -        if klass is None:
 | 
| -            for parent in self.ancestors():
 | 
| -                klass = parent.metaclass()
 | 
| -                if klass is not None:
 | 
| -                    break
 | 
| -        return klass
 | 
| -
 | 
| -    def _islots(self):
 | 
| -        """ Return an iterator with the inferred slots. """
 | 
| -        if '__slots__' not in self.locals:
 | 
| -            return
 | 
| -        for slots in self.igetattr('__slots__'):
 | 
| -            # check if __slots__ is a valid type
 | 
| -            for meth in ITER_METHODS:
 | 
| -                try:
 | 
| -                    slots.getattr(meth)
 | 
| -                    break
 | 
| -                except NotFoundError:
 | 
| -                    continue
 | 
| -            else:
 | 
| -                continue
 | 
| -
 | 
| -            if isinstance(slots, Const):
 | 
| -                # a string. Ignore the following checks,
 | 
| -                # but yield the node, only if it has a value
 | 
| -                if slots.value:
 | 
| -                    yield slots
 | 
| -                continue
 | 
| -            if not hasattr(slots, 'itered'):
 | 
| -                # we can't obtain the values, maybe a .deque?
 | 
| -                continue
 | 
| -
 | 
| -            if isinstance(slots, Dict):
 | 
| -                values = [item[0] for item in slots.items]
 | 
| -            else:
 | 
| -                values = slots.itered()
 | 
| -            if values is YES:
 | 
| -                continue
 | 
| -
 | 
| -            for elt in values:
 | 
| -                try:
 | 
| -                    for infered in elt.infer():
 | 
| -                        if infered is YES:
 | 
| -                            continue
 | 
| -                        if (not isinstance(infered, Const) or
 | 
| -                                not isinstance(infered.value, str)):
 | 
| -                            continue
 | 
| -                        if not infered.value:
 | 
| -                            continue
 | 
| -                        yield infered
 | 
| -                except InferenceError:
 | 
| -                    continue
 | 
| -
 | 
| -    # Cached, because inferring them all the time is expensive
 | 
| -    @cached
 | 
| -    def slots(self):
 | 
| -        """ Return all the slots for this node. """
 | 
| -        return list(self._islots())
 | 
| 
 |