| Index: third_party/logilab/astroid/node_classes.py
 | 
| diff --git a/third_party/logilab/astroid/node_classes.py b/third_party/logilab/astroid/node_classes.py
 | 
| index 6d59745812d96da764be4a2b18a45c795686d4ab..71e512f49cb88f03e61de516e2d6a0160d83de8f 100644
 | 
| --- a/third_party/logilab/astroid/node_classes.py
 | 
| +++ b/third_party/logilab/astroid/node_classes.py
 | 
| @@ -20,6 +20,9 @@
 | 
|  
 | 
|  import sys
 | 
|  
 | 
| +import six
 | 
| +from logilab.common.decorators import cachedproperty
 | 
| +
 | 
|  from astroid.exceptions import NoDefault
 | 
|  from astroid.bases import (NodeNG, Statement, Instance, InferenceContext,
 | 
|                             _infer_stmts, YES, BUILTINS)
 | 
| @@ -39,7 +42,7 @@ def unpack_infer(stmt, context=None):
 | 
|                  yield infered_elt
 | 
|          return
 | 
|      # if infered is a final node, return it and stop
 | 
| -    infered = stmt.infer(context).next()
 | 
| +    infered = next(stmt.infer(context))
 | 
|      if infered is stmt:
 | 
|          yield infered
 | 
|          return
 | 
| @@ -127,8 +130,7 @@ class LookupMixIn(object):
 | 
|          the lookup method
 | 
|          """
 | 
|          frame, stmts = self.lookup(name)
 | 
| -        context = InferenceContext()
 | 
| -        return _infer_stmts(stmts, context, frame)
 | 
| +        return _infer_stmts(stmts, None, frame)
 | 
|  
 | 
|      def _filter_stmts(self, stmts, frame, offset):
 | 
|          """filter statements to remove ignorable statements.
 | 
| @@ -146,6 +148,20 @@ class LookupMixIn(object):
 | 
|              myframe = self.frame().parent.frame()
 | 
|          else:
 | 
|              myframe = self.frame()
 | 
| +            # If the frame of this node is the same as the statement
 | 
| +            # of this node, then the node is part of a class or
 | 
| +            # a function definition and the frame of this node should be the
 | 
| +            # the upper frame, not the frame of the definition.
 | 
| +            # For more information why this is important,
 | 
| +            # see Pylint issue #295.
 | 
| +            # For example, for 'b', the statement is the same
 | 
| +            # as the frame / scope:
 | 
| +            #
 | 
| +            # def test(b=1):
 | 
| +            #     ...
 | 
| +
 | 
| +            if self.statement() is myframe and myframe.parent:
 | 
| +                myframe = myframe.parent.frame()
 | 
|          if not myframe is frame or self is frame:
 | 
|              return stmts
 | 
|          mystmt = self.statement()
 | 
| @@ -289,6 +305,11 @@ class Arguments(NodeNG, AssignTypeMixin):
 | 
|              return name
 | 
|          return None
 | 
|  
 | 
| +    @cachedproperty
 | 
| +    def fromlineno(self):
 | 
| +        lineno = super(Arguments, self).fromlineno
 | 
| +        return max(lineno, self.parent.fromlineno)
 | 
| +
 | 
|      def format_args(self):
 | 
|          """return arguments formatted as string"""
 | 
|          result = []
 | 
| @@ -475,7 +496,7 @@ class Const(NodeNG, Instance):
 | 
|          self.value = value
 | 
|  
 | 
|      def getitem(self, index, context=None):
 | 
| -        if isinstance(self.value, basestring):
 | 
| +        if isinstance(self.value, six.string_types):
 | 
|              return Const(self.value[index])
 | 
|          raise TypeError('%r (value=%s)' % (self, self.value))
 | 
|  
 | 
| @@ -483,7 +504,7 @@ class Const(NodeNG, Instance):
 | 
|          return False
 | 
|  
 | 
|      def itered(self):
 | 
| -        if isinstance(self.value, basestring):
 | 
| +        if isinstance(self.value, six.string_types):
 | 
|              return self.value
 | 
|          raise TypeError()
 | 
|  
 | 
| @@ -528,7 +549,7 @@ class Dict(NodeNG, Instance):
 | 
|              self.items = []
 | 
|          else:
 | 
|              self.items = [(const_factory(k), const_factory(v))
 | 
| -                          for k, v in items.iteritems()]
 | 
| +                          for k, v in items.items()]
 | 
|  
 | 
|      def pytype(self):
 | 
|          return '%s.dict' % BUILTINS
 | 
| @@ -583,7 +604,8 @@ class ExceptHandler(Statement, AssignTypeMixin):
 | 
|      name = None
 | 
|      body = None
 | 
|  
 | 
| -    def _blockstart_toline(self):
 | 
| +    @cachedproperty
 | 
| +    def blockstart_tolineno(self):
 | 
|          if self.name:
 | 
|              return self.name.tolineno
 | 
|          elif self.type:
 | 
| @@ -591,11 +613,6 @@ class ExceptHandler(Statement, AssignTypeMixin):
 | 
|          else:
 | 
|              return self.lineno
 | 
|  
 | 
| -    def set_line_info(self, lastchild):
 | 
| -        self.fromlineno = self.lineno
 | 
| -        self.tolineno = lastchild.tolineno
 | 
| -        self.blockstart_tolineno = self._blockstart_toline()
 | 
| -
 | 
|      def catch(self, exceptions):
 | 
|          if self.type is None or exceptions is None:
 | 
|              return True
 | 
| @@ -626,7 +643,8 @@ class For(BlockRangeMixIn, AssignTypeMixin, Statement):
 | 
|      orelse = None
 | 
|  
 | 
|      optional_assign = True
 | 
| -    def _blockstart_toline(self):
 | 
| +    @cachedproperty
 | 
| +    def blockstart_tolineno(self):
 | 
|          return self.iter.tolineno
 | 
|  
 | 
|  
 | 
| @@ -661,7 +679,8 @@ class If(BlockRangeMixIn, Statement):
 | 
|      body = None
 | 
|      orelse = None
 | 
|  
 | 
| -    def _blockstart_toline(self):
 | 
| +    @cachedproperty
 | 
| +    def blockstart_tolineno(self):
 | 
|          return self.test.tolineno
 | 
|  
 | 
|      def block_range(self, lineno):
 | 
| @@ -812,9 +831,6 @@ class TryExcept(BlockRangeMixIn, Statement):
 | 
|      def _infer_name(self, frame, name):
 | 
|          return name
 | 
|  
 | 
| -    def _blockstart_toline(self):
 | 
| -        return self.lineno
 | 
| -
 | 
|      def block_range(self, lineno):
 | 
|          """handle block line numbers range for try/except statements"""
 | 
|          last = None
 | 
| @@ -834,9 +850,6 @@ class TryFinally(BlockRangeMixIn, Statement):
 | 
|      body = None
 | 
|      finalbody = None
 | 
|  
 | 
| -    def _blockstart_toline(self):
 | 
| -        return self.lineno
 | 
| -
 | 
|      def block_range(self, lineno):
 | 
|          """handle block line numbers range for try/finally statements"""
 | 
|          child = self.body[0]
 | 
| @@ -880,7 +893,8 @@ class While(BlockRangeMixIn, Statement):
 | 
|      body = None
 | 
|      orelse = None
 | 
|  
 | 
| -    def _blockstart_toline(self):
 | 
| +    @cachedproperty
 | 
| +    def blockstart_tolineno(self):
 | 
|          return self.test.tolineno
 | 
|  
 | 
|      def block_range(self, lineno):
 | 
| @@ -894,7 +908,8 @@ class With(BlockRangeMixIn, AssignTypeMixin, Statement):
 | 
|      items = None
 | 
|      body = None
 | 
|  
 | 
| -    def _blockstart_toline(self):
 | 
| +    @cachedproperty
 | 
| +    def blockstart_tolineno(self):
 | 
|          return self.items[-1][0].tolineno
 | 
|  
 | 
|      def get_children(self):
 | 
| 
 |