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): |