summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--astroid/bases.py3
-rw-r--r--astroid/inference.py28
-rw-r--r--astroid/node_classes.py3
-rw-r--r--astroid/objects.py2
-rw-r--r--astroid/rebuilder.py36
-rw-r--r--astroid/scoped_nodes.py41
-rw-r--r--astroid/tests/unittest_builder.py1
-rw-r--r--astroid/tests/unittest_inference.py3
-rw-r--r--astroid/tests/unittest_objects.py2
-rw-r--r--astroid/tests/unittest_regrtest.py2
-rw-r--r--astroid/tests/unittest_scoped_nodes.py2
-rw-r--r--astroid/tests/unittest_transforms.py43
-rw-r--r--tox.ini2
13 files changed, 90 insertions, 78 deletions
diff --git a/astroid/bases.py b/astroid/bases.py
index 3c0e2f6..146d8e7 100644
--- a/astroid/bases.py
+++ b/astroid/bases.py
@@ -20,6 +20,7 @@ inference utils.
"""
from __future__ import print_function
+import inspect
import sys
import warnings
@@ -348,7 +349,6 @@ def path_wrapper(func):
context = contextmod.InferenceContext()
context.push(node)
yielded = set()
- print(node, context, _func, kwargs, file=sys.stderr)
for res in _func(node, context, **kwargs):
# unproxy only true instance, not const, tuple, dict...
if res.__class__ is Instance:
@@ -377,6 +377,7 @@ def raise_if_nothing_inferred(func):
inferred = True
yield node
if not inferred:
+ # print('Not inferred:', func, args, kwargs, inspect.getframeinfo(inspect.currentframe().f_back), sep='\n')
raise exceptions.InferenceError()
return wrapper
diff --git a/astroid/inference.py b/astroid/inference.py
index 62894a2..afba7fb 100644
--- a/astroid/inference.py
+++ b/astroid/inference.py
@@ -18,6 +18,8 @@
"""this module contains a set of functions to handle inference on astroid trees
"""
+from __future__ import print_function
+
import functools
import itertools
import operator
@@ -92,8 +94,8 @@ nodes.AssignName.infer_lhs = infer_name # won't work with a path wrapper
@bases.raise_if_nothing_inferred
@bases.path_wrapper
-def infer_callfunc(self, context=None):
- """infer a CallFunc node by trying to guess what the function returns"""
+def infer_call(self, context=None):
+ """infer a Call node by trying to guess what the function returns"""
callcontext = context.clone()
callcontext.callcontext = contextmod.CallContext(args=self.args,
keywords=self.keywords,
@@ -111,7 +113,7 @@ def infer_callfunc(self, context=None):
except exceptions.InferenceError:
## XXX log error ?
continue
-nodes.Call._infer = infer_callfunc
+nodes.Call._infer = infer_call
@bases.path_wrapper
@@ -135,8 +137,8 @@ nodes.Import.infer_name_module = infer_name_module
@bases.path_wrapper
-def infer_from(self, context=None, asname=True):
- """infer a From nodes: return the imported module/object"""
+def infer_import_from(self, context=None, asname=True):
+ """infer a ImportFrom node: return the imported module/object"""
name = context.lookupname
if name is None:
raise exceptions.InferenceError()
@@ -150,12 +152,12 @@ def infer_from(self, context=None, asname=True):
return bases._infer_stmts(stmts, context)
except exceptions.NotFoundError:
raise exceptions.InferenceError(name)
-nodes.ImportFrom._infer = infer_from
+nodes.ImportFrom._infer = infer_import_from
@bases.raise_if_nothing_inferred
-def infer_getattr(self, context=None):
- """infer a Getattr node by using getattr on the associated object"""
+def infer_attribute(self, context=None):
+ """infer an Attribute node by using getattr on the associated object"""
for owner in self.expr.infer(context):
if owner is util.YES:
yield owner
@@ -170,8 +172,8 @@ def infer_getattr(self, context=None):
except AttributeError:
# XXX method / function
context.boundnode = None
-nodes.Attribute._infer = bases.path_wrapper(infer_getattr)
-nodes.AssignAttr.infer_lhs = infer_getattr # # won't work with a path wrapper
+nodes.Attribute._infer = bases.path_wrapper(infer_attribute)
+nodes.AssignAttr.infer_lhs = infer_attribute # # won't work with a path wrapper
@bases.path_wrapper
@@ -600,7 +602,7 @@ nodes.Arguments._infer = infer_arguments
@bases.path_wrapper
-def infer_ass(self, context=None):
+def infer_assign(self, context=None):
"""infer a AssName/AssAttr: need to inspect the RHS part of the
assign node
"""
@@ -609,8 +611,8 @@ def infer_ass(self, context=None):
return stmt.infer(context)
stmts = list(self.assigned_stmts(context=context))
return bases._infer_stmts(stmts, context)
-nodes.AssignName._infer = infer_ass
-nodes.AssignAttr._infer = infer_ass
+nodes.AssignName._infer = infer_assign
+nodes.AssignAttr._infer = infer_assign
# no infer method on DelName and DelAttr (expected InferenceError)
diff --git a/astroid/node_classes.py b/astroid/node_classes.py
index 42f5b7d..9e424f7 100644
--- a/astroid/node_classes.py
+++ b/astroid/node_classes.py
@@ -566,7 +566,8 @@ class Call(bases.NodeNG):
starargs = None
kwargs = None
- def postinit(self, func=None, args=None, starargs=None, kwargs=None):
+ def postinit(self, func=None, args=None, keywords=None,
+ starargs=None, kwargs=None):
self.func = func
self.args = args
self.keywords = keywords
diff --git a/astroid/objects.py b/astroid/objects.py
index 9ae21f3..a38c2ee 100644
--- a/astroid/objects.py
+++ b/astroid/objects.py
@@ -22,7 +22,7 @@ which are used only as inference results, so they can't be found in the
original AST tree. For instance, inferring the following frozenset use,
leads to an inferred FrozenSet:
- CallFunc(func=Name('frozenset'), args=Tuple(...))
+ Call(func=Name('frozenset'), args=Tuple(...))
"""
diff --git a/astroid/rebuilder.py b/astroid/rebuilder.py
index 95bbce8..d55eb76 100644
--- a/astroid/rebuilder.py
+++ b/astroid/rebuilder.py
@@ -90,17 +90,17 @@ def _get_doc(node):
pass # ast built from scratch
return node, None
-def _visit_or_none(node, attr, visitor, parent, assign_ctx):
+def _visit_or_none(node, attr, visitor, parent, assign_ctx, visit='visit'):
"""If the given node has an attribute, visits the attribute, and
otherwise returns None.
"""
value = getattr(node, attr, None)
- if value is None:
- return None
+ if value:
+ return getattr(visitor, visit)(value, parent, assign_ctx)
else:
- return visitor.visit(value, parent, assign_ctx)
+ return None
class TreeRebuilder(object):
@@ -283,20 +283,19 @@ class TreeRebuilder(object):
def visit_call(self, node, parent, assign_ctx=None):
"""visit a CallFunc node by returning a fresh instance of it"""
newnode = nodes.Call(node.lineno, node.col_offset, parent)
- if node.starargs:
- starargs = self.visit(node.starargs, newnode, assign_ctx)
- else:
- starargs = None
- if node.kwargs:
- kwargs = self.visit(node.kwargs, newnode, assign_ctx)
+ if node.keywords:
+ keywords = [self.visit(child, newnode, assign_ctx)
+ for child in node.keywords]
else:
- kwargs = None
+ keywords = None
newnode.postinit(self.visit(node.func, newnode, assign_ctx),
[self.visit(child, newnode, assign_ctx)
for child in node.args],
- [self.visit(child, newnode, assign_ctx)
- for child in node.keywords],
- starargs, kwargs)
+ keywords,
+ _visit_or_none(node, 'starargs', self, newnode,
+ assign_ctx),
+ _visit_or_none(node, 'kwargs', self, newnode,
+ assign_ctx))
return newnode
def visit_classdef(self, node, parent, assign_ctx=None, newstyle=None):
@@ -406,7 +405,7 @@ class TreeRebuilder(object):
newnode = nodes.ExceptHandler(node.lineno, node.col_offset, parent)
# /!\ node.name can be a tuple
newnode.postinit(_visit_or_none(node, 'type', self, newnode, assign_ctx),
- _visit_or_none(node, 'name', self, newnode, "Assign"),
+ _visit_or_none(node, 'name', self, newnode, 'Assign'),
[self.visit(child, newnode, None)
for child in node.body])
return newnode
@@ -743,7 +742,7 @@ class TreeRebuilder3(TreeRebuilder):
"""visit an ExceptHandler node by returning a fresh instance of it"""
newnode = nodes.ExceptHandler(node.lineno, node.col_offset, parent)
newnode.postinit(_visit_or_none(node, 'type', self, newnode, assign_ctx),
- _visit_or_none(node, 'name', self, newnode, assign_ctx),
+ _visit_or_none(node, 'name', self, newnode, 'Assign', visit='visit_assignname'),
[self.visit(child, newnode, assign_ctx)
for child in node.body])
return newnode
@@ -793,10 +792,7 @@ class TreeRebuilder3(TreeRebuilder):
newnode = nodes.With(node.lineno, node.col_offset, parent)
def visit_child(child):
expr = self.visit(child.context_expr, newnode, assign_ctx)
- if child.optional_vars:
- var = self.visit(child.optional_vars, newnode, 'Assign')
- else:
- var = None
+ var = _visit_or_none(child, 'optional_vars', self, newnode, 'Assign')
return expr, var
newnode.postinit([visit_child(child) for child in node.items],
[self.visit(child, newnode, None)
diff --git a/astroid/scoped_nodes.py b/astroid/scoped_nodes.py
index fbb8be0..7a312bb 100644
--- a/astroid/scoped_nodes.py
+++ b/astroid/scoped_nodes.py
@@ -21,6 +21,10 @@ This module contains the classes for "scoped" node, i.e. which are opening a
new local scope in the language definition : Module, ClassDef, FunctionDef (and
Lambda, GeneratorExp, DictComp and SetComp to some extent).
"""
+
+from __future__ import print_function
+import inspect
+
import functools
import io
import itertools
@@ -193,6 +197,7 @@ class LocalsDictNodeNG(node_classes.LookupMixIn, bases.NodeNG):
if the name is already defined, ignore it
"""
#assert not stmt in self.locals.get(name, ()), (self, stmt)
+ # print('Set local:', self, name, stmt, inspect.getframeinfo(inspect.currentframe().f_back), sep='\n')
self.locals.setdefault(name, []).append(stmt)
__setitem__ = set_local
@@ -712,6 +717,9 @@ class FunctionDef(bases.Statement, Lambda):
self.doc = doc
self.instance_attrs = {}
super(FunctionDef, self).__init__(lineno, col_offset, parent)
+ if parent:
+ frame = parent.frame()
+ frame.set_local(name, self)
def postinit(self, args, body, decorators=None, returns=None):
self.args = args
@@ -721,23 +729,22 @@ class FunctionDef(bases.Statement, Lambda):
@decorators_mod.cachedproperty
def extra_decorators(self):
- """Get the extra decorators that this function can have
-
+ """Get the extra decorators that this function can haves
Additional decorators are considered when they are used as
assignments, as in `method = staticmethod(method)`.
The property will return all the callables that are used for
decoration.
"""
frame = self.parent.frame()
- if not isinstance(frame, Class):
+ if not isinstance(frame, ClassDef):
return []
decorators = []
for assign in frame.nodes_of_class(node_classes.Assign):
- if (isinstance(assign.value, node_classes.CallFunc)
+ if (isinstance(assign.value, node_classes.Call)
and isinstance(assign.value.func, node_classes.Name)):
for assign_node in assign.targets:
- if not isinstance(assign_node, node_classes.AssName):
+ if not isinstance(assign_node, node_classes.AssignName):
# Support only `name = callable(name)`
continue
@@ -750,7 +757,7 @@ class FunctionDef(bases.Statement, Lambda):
except KeyError:
continue
else:
- if isinstance(meth, Function):
+ if isinstance(meth, FunctionDef):
decorators.append(assign.value)
return decorators
@@ -768,9 +775,9 @@ class FunctionDef(bases.Statement, Lambda):
frame = self.parent.frame()
type_name = 'function'
- if isinstance(frame, Class):
+ if isinstance(frame, ClassDef):
if self.name == '__new__':
- return'classmethod'
+ return 'classmethod'
else:
type_name = 'method'
@@ -780,7 +787,7 @@ class FunctionDef(bases.Statement, Lambda):
if node.name in builtin_descriptors:
return node.name
- if isinstance(node, node_classes.CallFunc):
+ if isinstance(node, node_classes.Call):
# Handle the following case:
# @some_decorator(arg1, arg2)
# def func(...)
@@ -794,16 +801,16 @@ class FunctionDef(bases.Statement, Lambda):
return _type
try:
- for infered in node.infer():
+ for inferred in node.infer():
# Check to see if this returns a static or a class method.
- _type = _infer_decorator_callchain(infered)
+ _type = _infer_decorator_callchain(inferred)
if _type is not None:
return _type
- if not isinstance(infered, Class):
+ if not isinstance(inferred, ClassDef):
continue
- for ancestor in infered.ancestors():
- if not isinstance(ancestor, Class):
+ for ancestor in inferred.ancestors():
+ if not isinstance(ancestor, ClassDef):
continue
if ancestor.is_subtype_of('%s.classmethod' % BUILTINS):
return 'classmethod'
@@ -1039,7 +1046,7 @@ def get_wrapping_class(node):
"""
klass = node.frame()
- while klass is not None and not isinstance(klass, Class):
+ while klass is not None and not isinstance(klass, ClassDef):
if klass.parent is None:
klass = None
else:
@@ -1394,8 +1401,8 @@ class ClassDef(bases.Statement, LocalsDictNodeNG, mixins.FilterStmtsMixin):
if bases._is_property(attr):
# TODO(cpopa): don't use a private API.
- for infered in attr.infer_call_result(self, context):
- yield infered
+ for inferred in attr.infer_call_result(self, context):
+ yield inferred
continue
if attr.type == 'classmethod':
# If the method is a classmethod, then it will
diff --git a/astroid/tests/unittest_builder.py b/astroid/tests/unittest_builder.py
index 84bf50c..dd2e875 100644
--- a/astroid/tests/unittest_builder.py
+++ b/astroid/tests/unittest_builder.py
@@ -687,6 +687,7 @@ class FileBuildTest(unittest.TestCase):
# class method
method = klass2['class_method']
self.assertEqual([n.name for n in method.args.args], ['cls'])
+ # import pdb; pdb.set_trace()
self.assertEqual(method.type, 'classmethod')
# static method
method = klass2['static_method']
diff --git a/astroid/tests/unittest_inference.py b/astroid/tests/unittest_inference.py
index dd3cd91..6ce6c45 100644
--- a/astroid/tests/unittest_inference.py
+++ b/astroid/tests/unittest_inference.py
@@ -2138,6 +2138,7 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
('frozenset()', False),
('frozenset((1, 2))', True),
]
+ # import pdb; pdb.set_trace()
for code, expected in pairs:
node = test_utils.extract_node(code)
inferred = next(node.infer())
@@ -2568,6 +2569,8 @@ class InferenceTest(resources.SysPathSetup, unittest.TestCase):
f = A()
f += B() #@
''')
+ print('TEST HERE', ast_node)
+ import pdb; pdb.set_trace()
inferred = next(ast_node.infer())
self.assertIsInstance(inferred, Instance)
self.assertEqual(inferred.name, 'A')
diff --git a/astroid/tests/unittest_objects.py b/astroid/tests/unittest_objects.py
index b62f5d9..d44446b 100644
--- a/astroid/tests/unittest_objects.py
+++ b/astroid/tests/unittest_objects.py
@@ -17,7 +17,6 @@
# with astroid. If not, see <http://www.gnu.org/licenses/>.
from __future__ import print_function
-import sys
import unittest
@@ -280,7 +279,6 @@ class SuperTests(unittest.TestCase):
super(Super_Type_Object, self).class_method #@
''')
# Super(type, type) is the same for both functions and classmethods.
- print('TEST HERE', file=sys.stderr)
first = next(ast_nodes[0].infer())
self.assertIsInstance(first, nodes.FunctionDef)
self.assertEqual(first.name, 'method')
diff --git a/astroid/tests/unittest_regrtest.py b/astroid/tests/unittest_regrtest.py
index ba7e2bf..72f0928 100644
--- a/astroid/tests/unittest_regrtest.py
+++ b/astroid/tests/unittest_regrtest.py
@@ -160,7 +160,7 @@ multiply(1, 2, 3)
self.assertEqual(next(default.infer()).value, True)
@require_version('2.7')
- def test_with_infer_assnames(self):
+ def test_with_infer_assignnames(self):
builder = AstroidBuilder()
data = """
with open('a.txt') as stream, open('b.txt'):
diff --git a/astroid/tests/unittest_scoped_nodes.py b/astroid/tests/unittest_scoped_nodes.py
index f7088d8..1a9c20b 100644
--- a/astroid/tests/unittest_scoped_nodes.py
+++ b/astroid/tests/unittest_scoped_nodes.py
@@ -90,7 +90,7 @@ class ModuleNodeTest(ModuleLoader, unittest.TestCase):
self.assertIsInstance(red, nodes.FunctionDef)
self.assertEqual(red.name, 'four_args')
namenode = next(self.module.igetattr('NameNode'))
- self.assertIsInstance(namenode, nodes.Class)
+ self.assertIsInstance(namenode, nodes.ClassDef)
self.assertEqual(namenode.name, 'Name')
# resolve packageredirection
mod = resources.build_file('data/appl/myConnection.py',
diff --git a/astroid/tests/unittest_transforms.py b/astroid/tests/unittest_transforms.py
index 3bb0cc2..fe206a1 100644
--- a/astroid/tests/unittest_transforms.py
+++ b/astroid/tests/unittest_transforms.py
@@ -16,6 +16,9 @@
# You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>.
+from __future__ import print_function
+import sys
+
import contextlib
import time
import unittest
@@ -45,20 +48,20 @@ class TestTransforms(unittest.TestCase):
return self.transformer.visit(module)
def test_function_inlining_transform(self):
- def transform_callfunc(node):
+ def transform_call(node):
# Let's do some function inlining
inferred = next(node.infer())
return inferred
- self.transformer.register_transform(nodes.CallFunc,
- transform_callfunc)
+ self.transformer.register_transform(nodes.Call,
+ transform_call)
module = self.parse_transform('''
def test(): return 42
test() #@
''')
- self.assertIsInstance(module.body[1], nodes.Discard)
+ self.assertIsInstance(module.body[1], nodes.Expr)
self.assertIsInstance(module.body[1].value, nodes.Const)
self.assertEqual(module.body[1].value.value, 42)
@@ -85,20 +88,20 @@ class TestTransforms(unittest.TestCase):
a < b
''')
- self.assertIsInstance(module.body[2], nodes.Discard)
+ self.assertIsInstance(module.body[2], nodes.Expr)
self.assertIsInstance(module.body[2].value, nodes.Const)
self.assertFalse(module.body[2].value.value)
def test_transform_patches_locals(self):
def transform_function(node):
assign = nodes.Assign()
- name = nodes.AssName()
+ name = nodes.AssignName()
name.name = 'value'
assign.targets = [name]
assign.value = nodes.const_factory(42)
node.body.append(assign)
- self.transformer.register_transform(nodes.Function,
+ self.transformer.register_transform(nodes.FunctionDef,
transform_function)
module = self.parse_transform('''
@@ -112,15 +115,15 @@ class TestTransforms(unittest.TestCase):
self.assertEqual(func.body[1].as_string(), 'value = 42')
def test_predicates(self):
- def transform_callfunc(node):
+ def transform_call(node):
inferred = next(node.infer())
return inferred
def should_inline(node):
return node.func.name.startswith('inlineme')
- self.transformer.register_transform(nodes.CallFunc,
- transform_callfunc,
+ self.transformer.register_transform(nodes.Call,
+ transform_call,
should_inline)
module = self.parse_transform('''
@@ -135,12 +138,12 @@ class TestTransforms(unittest.TestCase):
inlineme_2()
''')
values = module.body[-3:]
- self.assertIsInstance(values[0], nodes.Discard)
+ self.assertIsInstance(values[0], nodes.Expr)
self.assertIsInstance(values[0].value, nodes.Const)
self.assertEqual(values[0].value.value, 24)
- self.assertIsInstance(values[1], nodes.Discard)
- self.assertIsInstance(values[1].value, nodes.CallFunc)
- self.assertIsInstance(values[2], nodes.Discard)
+ self.assertIsInstance(values[1], nodes.Expr)
+ self.assertIsInstance(values[1].value, nodes.Call)
+ self.assertIsInstance(values[2], nodes.Expr)
self.assertIsInstance(values[2].value, nodes.Const)
self.assertEqual(values[2].value.value, 2)
@@ -158,7 +161,7 @@ class TestTransforms(unittest.TestCase):
return next(node.infer_call_result(node))
manager = builder.MANAGER
- with add_transform(manager, nodes.Function, transform_function):
+ with add_transform(manager, nodes.FunctionDef, transform_function):
module = builder.parse('''
import abc
from abc import abstractmethod
@@ -184,21 +187,21 @@ class TestTransforms(unittest.TestCase):
def test_transforms_are_called_for_builtin_modules(self):
# Test that transforms are called for builtin modules.
def transform_function(node):
- name = nodes.AssName()
+ name = nodes.AssignName()
name.name = 'value'
node.args.args = [name]
return node
manager = builder.MANAGER
predicate = lambda node: node.root().name == 'time'
- with add_transform(manager, nodes.Function,
+ with add_transform(manager, nodes.FunctionDef,
transform_function, predicate):
builder_instance = builder.AstroidBuilder()
module = builder_instance.module_build(time)
asctime = module['asctime']
self.assertEqual(len(asctime.args.args), 1)
- self.assertIsInstance(asctime.args.args[0], nodes.AssName)
+ self.assertIsInstance(asctime.args.args[0], nodes.AssignName)
self.assertEqual(asctime.args.args[0].name, 'value')
def test_builder_apply_transforms(self):
@@ -206,12 +209,12 @@ class TestTransforms(unittest.TestCase):
return nodes.const_factory(42)
manager = builder.MANAGER
- with add_transform(manager, nodes.Function, transform_function):
+ with add_transform(manager, nodes.FunctionDef, transform_function):
astroid_builder = builder.AstroidBuilder(apply_transforms=False)
module = astroid_builder.string_build('''def test(): pass''')
# The transform wasn't applied.
- self.assertIsInstance(module.body[0], nodes.Function)
+ self.assertIsInstance(module.body[0], nodes.FunctionDef)
if __name__ == '__main__':
diff --git a/tox.ini b/tox.ini
index a1b7930..99b295a 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,7 @@
[tox]
# official list is
# envlist = py27, py33, py34, pypy, jython
-envlist = py27, py34, pylint
+envlist = py27, py34
# envlist = py27, py33
[testenv:pylint]