summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCeridwen <ceridwenv@gmail.com>2016-02-15 22:36:02 -0500
committerCeridwen <ceridwenv@gmail.com>2016-02-15 22:36:02 -0500
commit54e5ddc279c4281e1612380af67051734ae30064 (patch)
treeefdb59cd69e68a10cf3ce1a0c271524ecc72c341
parent329fc88e739e403c4bc0e7bb93f757efd5b49556 (diff)
parent7a206c6851cd63a4028d6ce384f281f1ee460181 (diff)
downloadastroid-git-54e5ddc279c4281e1612380af67051734ae30064.tar.gz
Merge testdata changes and Parameter nodes into zipper.
-rw-r--r--.travis.yml2
-rw-r--r--ChangeLog22
-rw-r--r--MANIFEST.in3
-rw-r--r--astroid/as_string.py15
-rw-r--r--astroid/inference.py1
-rw-r--r--astroid/interpreter/lookup.py7
-rw-r--r--astroid/interpreter/scope.py20
-rw-r--r--astroid/nodes.py6
-rw-r--r--astroid/protocols.py7
-rw-r--r--astroid/raw_building.py96
-rw-r--r--astroid/test_utils.py13
-rw-r--r--astroid/tests/resources.py27
-rw-r--r--astroid/tests/testdata/data/MyPyPa-0.1.0-py2.5.egg (renamed from astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg)bin1222 -> 1222 bytes
-rw-r--r--astroid/tests/testdata/data/MyPyPa-0.1.0-py2.5.zip (renamed from astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip)bin1222 -> 1222 bytes
-rw-r--r--astroid/tests/testdata/data/SSL1/Connection1.py (renamed from astroid/tests/testdata/python3/data/SSL1/Connection1.py)0
-rw-r--r--astroid/tests/testdata/data/SSL1/__init__.py (renamed from astroid/tests/testdata/python3/data/SSL1/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/__init__.py (renamed from astroid/tests/testdata/python2/data/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/absimp/__init__.py (renamed from astroid/tests/testdata/python2/data/absimp/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/absimp/sidepackage/__init__.py (renamed from astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/absimp/string.py (renamed from astroid/tests/testdata/python2/data/absimp/string.py)0
-rw-r--r--astroid/tests/testdata/data/absimport.py (renamed from astroid/tests/testdata/python2/data/absimport.py)0
-rw-r--r--astroid/tests/testdata/data/all.py (renamed from astroid/tests/testdata/python2/data/all.py)2
-rw-r--r--astroid/tests/testdata/data/appl/__init__.py (renamed from astroid/tests/testdata/python2/data/appl/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/appl/myConnection.py (renamed from astroid/tests/testdata/python3/data/appl/myConnection.py)1
-rw-r--r--astroid/tests/testdata/data/descriptor_crash.py (renamed from astroid/tests/testdata/python2/data/descriptor_crash.py)0
-rw-r--r--astroid/tests/testdata/data/email.py (renamed from astroid/tests/testdata/python2/data/email.py)0
-rw-r--r--astroid/tests/testdata/data/find_test/__init__.py (renamed from astroid/tests/testdata/python2/data/find_test/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/find_test/module.py (renamed from astroid/tests/testdata/python2/data/find_test/module.py)0
-rw-r--r--astroid/tests/testdata/data/find_test/module2.py (renamed from astroid/tests/testdata/python2/data/find_test/module2.py)0
-rw-r--r--astroid/tests/testdata/data/find_test/noendingnewline.py (renamed from astroid/tests/testdata/python2/data/find_test/noendingnewline.py)0
-rw-r--r--astroid/tests/testdata/data/find_test/nonregr.py (renamed from astroid/tests/testdata/python2/data/find_test/nonregr.py)0
-rw-r--r--astroid/tests/testdata/data/format.py (renamed from astroid/tests/testdata/python2/data/format.py)0
-rw-r--r--astroid/tests/testdata/data/lmfp/__init__.py (renamed from astroid/tests/testdata/python2/data/lmfp/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/lmfp/foo.py (renamed from astroid/tests/testdata/python2/data/lmfp/foo.py)0
-rw-r--r--astroid/tests/testdata/data/module.py (renamed from astroid/tests/testdata/python2/data/module.py)6
-rw-r--r--astroid/tests/testdata/data/module1abs/__init__.py (renamed from astroid/tests/testdata/python2/data/module1abs/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/module1abs/core.py (renamed from astroid/tests/testdata/python2/data/module1abs/core.py)0
-rw-r--r--astroid/tests/testdata/data/module2.py (renamed from astroid/tests/testdata/python3/data/module2.py)2
-rw-r--r--astroid/tests/testdata/data/noendingnewline.py (renamed from astroid/tests/testdata/python3/data/noendingnewline.py)0
-rw-r--r--astroid/tests/testdata/data/nonregr.py (renamed from astroid/tests/testdata/python2/data/nonregr.py)0
-rw-r--r--astroid/tests/testdata/data/notall.py (renamed from astroid/tests/testdata/python3/data/notall.py)0
-rw-r--r--astroid/tests/testdata/data/notamodule/file.py (renamed from astroid/tests/testdata/python2/data/notamodule/file.py)0
-rw-r--r--astroid/tests/testdata/data/package/__init__.py (renamed from astroid/tests/testdata/python2/data/package/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/package/absimport.py (renamed from astroid/tests/testdata/python2/data/package/absimport.py)0
-rw-r--r--astroid/tests/testdata/data/package/hello.py (renamed from astroid/tests/testdata/python2/data/package/hello.py)0
-rw-r--r--astroid/tests/testdata/data/package/import_package_subpackage_module.py (renamed from astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py)0
-rw-r--r--astroid/tests/testdata/data/package/subpackage/__init__.py (renamed from astroid/tests/testdata/python2/data/package/subpackage/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/package/subpackage/module.py (renamed from astroid/tests/testdata/python2/data/package/subpackage/module.py)0
-rw-r--r--astroid/tests/testdata/data/recursion.py (renamed from astroid/tests/testdata/python2/data/recursion.py)4
-rw-r--r--astroid/tests/testdata/data/unicode_package/__init__.py (renamed from astroid/tests/testdata/python2/data/unicode_package/__init__.py)0
-rw-r--r--astroid/tests/testdata/data/unicode_package/core/__init__.py (renamed from astroid/tests/testdata/python2/data/unicode_package/core/__init__.py)0
-rw-r--r--astroid/tests/testdata/python2/data/SSL1/Connection1.py14
-rw-r--r--astroid/tests/testdata/python2/data/SSL1/__init__.py1
-rw-r--r--astroid/tests/testdata/python2/data/appl/myConnection.py12
-rw-r--r--astroid/tests/testdata/python2/data/invalid_encoding.py1
-rw-r--r--astroid/tests/testdata/python2/data/module2.py143
-rw-r--r--astroid/tests/testdata/python2/data/noendingnewline.py36
-rw-r--r--astroid/tests/testdata/python2/data/notall.py7
-rw-r--r--astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.eggbin1222 -> 0 bytes
-rw-r--r--astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zipbin1222 -> 0 bytes
-rw-r--r--astroid/tests/testdata/python3/data/__init__.py1
-rw-r--r--astroid/tests/testdata/python3/data/absimp/__init__.py5
-rw-r--r--astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py3
-rw-r--r--astroid/tests/testdata/python3/data/absimp/string.py3
-rw-r--r--astroid/tests/testdata/python3/data/absimport.py3
-rw-r--r--astroid/tests/testdata/python3/data/all.py9
-rw-r--r--astroid/tests/testdata/python3/data/appl/__init__.py3
-rw-r--r--astroid/tests/testdata/python3/data/descriptor_crash.py11
-rw-r--r--astroid/tests/testdata/python3/data/email.py1
-rw-r--r--astroid/tests/testdata/python3/data/find_test/__init__.py0
-rw-r--r--astroid/tests/testdata/python3/data/find_test/module.py0
-rw-r--r--astroid/tests/testdata/python3/data/find_test/module2.py0
-rw-r--r--astroid/tests/testdata/python3/data/find_test/noendingnewline.py0
-rw-r--r--astroid/tests/testdata/python3/data/find_test/nonregr.py0
-rw-r--r--astroid/tests/testdata/python3/data/format.py34
-rw-r--r--astroid/tests/testdata/python3/data/invalid_encoding.py1
-rw-r--r--astroid/tests/testdata/python3/data/lmfp/__init__.py2
-rw-r--r--astroid/tests/testdata/python3/data/lmfp/foo.py6
-rw-r--r--astroid/tests/testdata/python3/data/module.py87
-rw-r--r--astroid/tests/testdata/python3/data/module1abs/__init__.py4
-rw-r--r--astroid/tests/testdata/python3/data/module1abs/core.py1
-rw-r--r--astroid/tests/testdata/python3/data/nonregr.py57
-rw-r--r--astroid/tests/testdata/python3/data/notamodule/file.py0
-rw-r--r--astroid/tests/testdata/python3/data/package/__init__.py4
-rw-r--r--astroid/tests/testdata/python3/data/package/absimport.py6
-rw-r--r--astroid/tests/testdata/python3/data/package/hello.py2
-rw-r--r--astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py49
-rw-r--r--astroid/tests/testdata/python3/data/package/subpackage/__init__.py1
-rw-r--r--astroid/tests/testdata/python3/data/package/subpackage/module.py1
-rw-r--r--astroid/tests/testdata/python3/data/recursion.py3
-rw-r--r--astroid/tests/testdata/python3/data/unicode_package/__init__.py1
-rw-r--r--astroid/tests/testdata/python3/data/unicode_package/core/__init__.py0
-rw-r--r--astroid/tests/unittest_brain.py4
-rw-r--r--astroid/tests/unittest_builder.py51
-rw-r--r--astroid/tests/unittest_modutils.py2
-rw-r--r--astroid/tests/unittest_nodes.py12
-rw-r--r--astroid/tests/unittest_python3.py40
-rw-r--r--astroid/tests/unittest_regrtest.py8
-rw-r--r--astroid/tests/unittest_scoped_nodes.py24
-rw-r--r--astroid/tree/base.py51
-rw-r--r--astroid/tree/node_classes.py164
-rw-r--r--astroid/tree/rebuilder.py162
-rw-r--r--astroid/tree/scoped_nodes.py30
-rw-r--r--astroid/tree/treeabc.py13
-rw-r--r--doc/source/conf.py6
-rw-r--r--doc/source/inference.rst2
-rw-r--r--setup.py4
-rw-r--r--tox.ini6
108 files changed, 478 insertions, 847 deletions
diff --git a/.travis.yml b/.travis.yml
index 9075168a..e3a7da10 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,7 +35,7 @@ install:
- $PYTHON_EXE -m pip --version
- $PYTHON_EXE -m tox --version
script:
- - python -m tox -e $TOXENV
+ - tox -e $TOXENV
after_failure:
- more .tox/log/* | cat
- more .tox/*/log/* | cat
diff --git a/ChangeLog b/ChangeLog
index 3836022a..f405b4e4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,28 @@ Change log for the astroid package (used to be astng)
=====================================================
--
+ * Changed the way how parameters are being built
+
+ The old way consisted in having the parameter names, their
+ defaults and their annotations separated in different components
+ of the Arguments node. We introduced a new Param node, which holds
+ the name of a parameter, its default value and its annotation.
+ If any of the last two values are missing, then that slot will be
+ filled with a new node kind, Empty, which is used for specifying the
+ lack of something (None could have been used instead, but that means having
+ non-AST nodes in the Arguments node).
+ We're also having support for positional only arguments, for the moment
+ only in raw_building.
+
+ * We don't support nested arguments in functions in Python 2
+ anymore.
+
+ This was dropped in order to simplify the implementation.
+ When they are encountered, we'll unflatten them into a list
+ of parameters, as if they were not nested from the beginning.
+
+ * NodeNG.nearest was removed. It's not an API that we were using
+ and it was buggy.
* Dict nodes are constructed with two arguments, keys and values,
in the same way that ast.Dict is built.
diff --git a/MANIFEST.in b/MANIFEST.in
index 4837adf1..eab1f75b 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,7 +1,6 @@
include ChangeLog
-include README
+include README.rst
include COPYING
include COPYING.LESSER
include tox.ini
recursive-include astroid/tests/testdata *.py *.zip *.egg
-recursive-include astroid/brain *.py
diff --git a/astroid/as_string.py b/astroid/as_string.py
index d99aee0a..800617e7 100644
--- a/astroid/as_string.py
+++ b/astroid/as_string.py
@@ -193,8 +193,8 @@ class AsStringVisitor(object):
def visit_excepthandler(self, node):
if node.type:
if node.name:
- excs = 'except %s, %s' % (node.type.accept(self),
- node.name.accept(self))
+ excs = 'except %s as %s' % (node.type.accept(self),
+ node.name.accept(self))
else:
excs = 'except %s' % node.type.accept(self)
else:
@@ -442,17 +442,6 @@ class AsStringVisitor(object):
class AsStringVisitor3(AsStringVisitor):
"""AsStringVisitor3 overwrites some AsStringVisitor methods"""
- def visit_excepthandler(self, node):
- if node.type:
- if node.name:
- excs = 'except %s as %s' % (node.type.accept(self),
- node.name.accept(self))
- else:
- excs = 'except %s' % node.type.accept(self)
- else:
- excs = 'except'
- return '%s:\n%s' % (excs, self._stmt_list(node.body))
-
def visit_nonlocal(self, node):
"""return an astroid.Nonlocal node as string"""
return 'nonlocal %s' % ', '.join(node.names)
diff --git a/astroid/inference.py b/astroid/inference.py
index 1a7ce413..e4074bc1 100644
--- a/astroid/inference.py
+++ b/astroid/inference.py
@@ -698,6 +698,7 @@ def infer_arguments(self, context=None, nodes=None):
@infer.register(treeabc.AssignName)
@infer.register(treeabc.AssignAttr)
+@infer.register(treeabc.Parameter)
@decorators.path_wrapper
def infer_assign(self, context=None):
"""infer a AssignName/AssignAttr: need to inspect the RHS part of the
diff --git a/astroid/interpreter/lookup.py b/astroid/interpreter/lookup.py
index d8e5931a..20fda77a 100644
--- a/astroid/interpreter/lookup.py
+++ b/astroid/interpreter/lookup.py
@@ -238,6 +238,7 @@ def locals_new_scope(node, locals_):
@_get_locals.register(treeabc.DelName)
@_get_locals.register(treeabc.FunctionDef)
@_get_locals.register(treeabc.ClassDef)
+@_get_locals.register(treeabc.Parameter)
def locals_name(node, locals_):
'''These nodes add a name to the local variables. AssignName and
DelName have no children while FunctionDef and ClassDef start a
@@ -287,9 +288,11 @@ def locals_import_from(node, locals_):
# Don't add future imports to locals.
if node.modname == '__future__':
return
- # Inherited code, I don't know why this function sorts this list.
+
+ # Sort the list for having the locals ordered by their first
+ # appearance.
def sort_locals(my_list):
- my_list.sort(key=lambda node: node.fromlineno)
+ my_list.sort(key=lambda node: node.fromlineno or 0)
for name, asname in node.names:
if name == '*':
diff --git a/astroid/interpreter/scope.py b/astroid/interpreter/scope.py
index 4cca5c5c..47fb3a0c 100644
--- a/astroid/interpreter/scope.py
+++ b/astroid/interpreter/scope.py
@@ -41,19 +41,23 @@ def _scope_by_parent(parent, node):
# in order to decouple the implementation for the normal cases.
+def _node_arguments(node):
+ for arg in itertools.chain(node.positional_and_keyword, node.keyword_only,
+ (node.vararg, ), (node.kwarg, )):
+ if arg and arg.annotation:
+ yield arg
+
+
@_scope_by_parent.register(treeabc.Arguments)
def _scope_by_argument_parent(parent, node):
args = parent
- if node in itertools.chain(args.defaults, args.kw_defaults):
- return args.parent.parent.scope()
- if six.PY3:
- look_for = itertools.chain(
- (args.kwargannotation, ),
- (args.varargannotation, ),
- args.annotations)
- if node in look_for:
+ for param in itertools.chain(args.positional_and_keyword, args.keyword_only):
+ if param.default == node:
return args.parent.parent.scope()
+ if six.PY3 and node in _node_arguments(args):
+ return args.parent.parent.scope()
+
@_scope_by_parent.register(treeabc.FunctionDef)
def _scope_by_function_parent(parent, node):
diff --git a/astroid/nodes.py b/astroid/nodes.py
index 1aea53f2..6fb37652 100644
--- a/astroid/nodes.py
+++ b/astroid/nodes.py
@@ -40,9 +40,9 @@ from astroid.tree.node_classes import (
Arguments, AssignAttr, Assert, Assign,
AssignName, AugAssign, Repr, BinOp, BoolOp, Break, Call, Compare,
Comprehension, Const, Continue, Decorators, DelAttr, DelName, Delete,
- Dict, Expr, Ellipsis, ExceptHandler, Exec, ExtSlice, For,
+ Dict, Empty, Expr, Ellipsis, ExceptHandler, Exec, ExtSlice, For,
ImportFrom, Attribute, Global, If, IfExp, Import, Index, Keyword,
- List, Name, NameConstant, Nonlocal, Pass, Print, Raise, Return, Set, Slice,
+ List, Name, NameConstant, Nonlocal, Pass, Parameter, Print, Raise, Return, Set, Slice,
Starred, Subscript, TryExcept, TryFinally, Tuple, UnaryOp, While, With,
WithItem, Yield, YieldFrom, AsyncFor, Await, AsyncWith,
# Node not present in the builtin ast module.
@@ -74,7 +74,7 @@ ALL_NODE_CLASSES = (
Lambda, List, ListComp,
Name, NameConstant, Nonlocal,
Module,
- Pass, Print,
+ Parameter, Pass, Print,
Raise, ReservedName, Return,
Set, SetComp, Slice, Starred, Subscript,
TryExcept, TryFinally, Tuple,
diff --git a/astroid/protocols.py b/astroid/protocols.py
index eada9764..7fdc6e29 100644
--- a/astroid/protocols.py
+++ b/astroid/protocols.py
@@ -304,6 +304,7 @@ def mulass_assigned_stmts(self, nodes, node=None, context=None, assign_path=None
@assigned_stmts.register(treeabc.AssignName)
@assigned_stmts.register(treeabc.AssignAttr)
+@assigned_stmts.register(treeabc.Parameter)
def assend_assigned_stmts(self, nodes, node=None, context=None, assign_path=None):
return self.parent.assigned_stmts(self, context=context)
@@ -311,7 +312,7 @@ def assend_assigned_stmts(self, nodes, node=None, context=None, assign_path=None
def _arguments_infer_argname(self, name, context, nodes):
# arguments information may be missing, in which case we can't do anything
# more
- if not (self.args or self.vararg or self.kwarg):
+ if not self.args and (not self.vararg and not self.kwarg):
yield util.Uninferable
return
# first argument of instance/class method
@@ -336,10 +337,10 @@ def _arguments_infer_argname(self, name, context, nodes):
return
# TODO: just provide the type here, no need to have an empty Dict.
- if name == self.vararg:
+ if self.vararg and name == self.vararg.name:
yield nodes.Tuple(parent=self)
return
- if name == self.kwarg:
+ if self.kwarg and name == self.kwarg.name:
yield nodes.Dict(parent=self)
return
# if there is a default value, yield it. And then yield Uninferable to reflect
diff --git a/astroid/raw_building.py b/astroid/raw_building.py
index f3871143..bccd83da 100644
--- a/astroid/raw_building.py
+++ b/astroid/raw_building.py
@@ -319,65 +319,71 @@ def ast_from_function(func, built_objects, module, name=None, parent=None):
itertools.groupby(signature.parameters.values(),
operator.attrgetter('kind'))}
- def extract_args(parameters, parent):
- '''Takes an iterator over Parameter objects and returns three
- sequences, arg names, default values, and annotations.
-
- '''
- names = []
- defaults = []
- annotations = []
+ def _extract_args(parameters, parent):
+ """Generate an iterator of Parameter nodes from a list of inspect.Parameter objects."""
for parameter in parameters:
- names.append(parameter.name)
+ param = node_classes.Parameter(name=parameter.name,
+ col_offset=parent.col_offset,
+ lineno=parent.lineno,
+ parent=parent)
+ default = node_classes.Empty
+ annotation = node_classes.Empty
if parameter.default is not _Parameter.empty:
- defaults.extend(_ast_from_object(parameter.default, built_objects, module, parent=parent))
+ default = _ast_from_object(parameter.default, built_objects,
+ module, parent=parent)
+
if parameter.annotation is not _Parameter.empty:
- annotations.extend(_ast_from_object(parameter.annotation, built_objects, module, parent=parent))
- else:
- annotations.append(None)
- return names, defaults, annotations
+ annotation = _ast_from_object(parameter.annotation, built_objects,
+ module, parent=parent)
- def extract_vararg(parameter):
- '''Takes a single-element iterator possibly containing a Parameter and
- returns a name and an annotation.
+ param.postinit(default=default, annotation=annotation)
+ yield param
- '''
+ def _extract_vararg(parameter, parent):
+ """Build a variadic Parameter node from an inspect.Parameter object."""
try:
- return parameter[0].name
+ parameter = parameter[0]
except IndexError:
- return None
-
- vararg = parameters.get(_Parameter.VAR_POSITIONAL, ())
- kwarg = parameters.get(_Parameter.VAR_KEYWORD, ())
- vararg_name = extract_vararg(vararg)
- kwarg_name = extract_vararg(kwarg)
- args_node = node_classes.Arguments(vararg=vararg_name, kwarg=kwarg_name, parent=func_node)
-
- # This ignores POSITIONAL_ONLY args, because they only appear in
- # functions implemented in C and can't be mimicked by any Python
- # function.
- names, defaults, annotations = extract_args(parameters.get(_Parameter.POSITIONAL_OR_KEYWORD, ()), args_node)
- kwonlynames, kw_defaults, kwonly_annotations = extract_args(parameters.get(_Parameter.KEYWORD_ONLY, ()), args_node)
- args = [node_classes.AssignName(name=n, parent=args_node) for n in names]
- kwonlyargs = [node_classes.AssignName(name=n, parent=args_node) for n in kwonlynames]
- if vararg_name and vararg[0].annotation is not _Parameter.empty:
- varargannotation = vararg.annotation
- else:
- varargannotation = None
- if kwarg_name and kwarg[0].annotation is not _Parameter.empty:
- kwargannotation = kwarg.annotation
- else:
- kwargannotation = None
+ return node_classes.Empty
+
+ if parameter.annotation is not _Parameter.empty:
+ annotation = _ast_from_object(parameter.annotation,
+ built_objects, module, parent=parent)[0]
+ else:
+ annotation = node_classes.Empty
+
+ param = node_classes.Parameter(name=parameter.name,
+ lineno=parent.lineno,
+ col_offset=parent.col_offset,
+ parent=parent)
+ param.postinit(annotation=annotation, default=node_classes.Empty)
+ return param
+
+ args_node = node_classes.Arguments(parent=func_node)
+ args = _extract_args(parameters.get(_Parameter.POSITIONAL_OR_KEYWORD, ()),
+ args_node)
+ keyword_only = _extract_args(parameters.get(_Parameter.KEYWORD_ONLY, ()),
+ args_node)
+ positional_only = _extract_args(parameters.get(_Parameter.POSITIONAL_ONLY, ()),
+ args_node)
+ python_vararg = parameters.get(_Parameter.VAR_POSITIONAL, ())
+ python_kwarg = parameters.get(_Parameter.VAR_KEYWORD, ())
+ vararg = _extract_vararg(python_vararg, args_node)
+ kwarg = _extract_vararg(python_kwarg, args_node)
+
returns = None
if signature.return_annotation is not _Parameter.empty:
returns = _ast_from_object(signature.return_annotation,
built_objects,
module,
parent=func_node)[0]
- args_node.postinit(args, defaults, kwonlyargs, kw_defaults,
- annotations, kwonly_annotations,
- varargannotation, kwargannotation)
+ args_node.postinit(args=list(args),
+ vararg=vararg,
+ kwarg=kwarg,
+ keyword_only=list(keyword_only),
+ positional_only=list(positional_only))
func_node.postinit(args=args_node, body=[], returns=returns)
+
for name in set(dir(func)) - set(dir(type(func))):
# This checks against method special attributes because
# methods are also dispatched through this function.
diff --git a/astroid/test_utils.py b/astroid/test_utils.py
index b15ab766..ff81cd59 100644
--- a/astroid/test_utils.py
+++ b/astroid/test_utils.py
@@ -19,6 +19,7 @@ _TRANSIENT_FUNCTION = '__'
# when calling extract_node.
_STATEMENT_SELECTOR = '#@'
+
def _extract_expressions(node):
"""Find expressions in a call to _TRANSIENT_FUNCTION and extract them.
@@ -46,8 +47,18 @@ def _extract_expressions(node):
child = getattr(node.parent, name)
if isinstance(child, (list, tuple)):
for idx, compound_child in enumerate(child):
- if compound_child is node:
+
+ # Can't find a cleaner way to do this.
+ if isinstance(compound_child, nodes.Parameter):
+ if compound_child.default is node:
+ child[idx].default = real_expr
+ elif compound_child.annotation is node:
+ child[idx].annotation = real_expr
+ else:
+ child[idx] = real_expr
+ elif compound_child is node:
child[idx] = real_expr
+
elif child is node:
setattr(node.parent, name, real_expr)
yield real_expr
diff --git a/astroid/tests/resources.py b/astroid/tests/resources.py
index 6a29b54e..1390088c 100644
--- a/astroid/tests/resources.py
+++ b/astroid/tests/resources.py
@@ -15,8 +15,12 @@
#
# You should have received a copy of the GNU Lesser General Public License along
# with astroid. If not, see <http://www.gnu.org/licenses/>.
+import binascii
+import contextlib
import os
import sys
+import shutil
+import tempfile
import pkg_resources
import six
@@ -25,12 +29,31 @@ from astroid import builder
from astroid import MANAGER
-DATA_DIR = 'testdata/python{}/'.format(sys.version_info[0])
+DATA_DIR = 'testdata'
BUILTINS = six.moves.builtins.__name__
+
+@contextlib.contextmanager
+def _temporary_file():
+ name = binascii.hexlify(os.urandom(5)).decode()
+ path = find(name)
+ try:
+ yield path
+ finally:
+ os.remove(path)
+
+@contextlib.contextmanager
+def tempfile_with_content(content):
+ with _temporary_file() as tmp:
+ with open(tmp, 'wb') as stream:
+ stream.write(content)
+ yield tmp
+
+
def find(name):
return pkg_resources.resource_filename(
- 'astroid.tests', os.path.normpath(os.path.join(DATA_DIR, name)))
+ 'astroid.tests',
+ os.path.normpath(os.path.join(DATA_DIR, name)))
def build_file(path, modname=None):
diff --git a/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg b/astroid/tests/testdata/data/MyPyPa-0.1.0-py2.5.egg
index f62599c7..f62599c7 100644
--- a/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.egg
+++ b/astroid/tests/testdata/data/MyPyPa-0.1.0-py2.5.egg
Binary files differ
diff --git a/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip b/astroid/tests/testdata/data/MyPyPa-0.1.0-py2.5.zip
index f62599c7..f62599c7 100644
--- a/astroid/tests/testdata/python2/data/MyPyPa-0.1.0-py2.5.zip
+++ b/astroid/tests/testdata/data/MyPyPa-0.1.0-py2.5.zip
Binary files differ
diff --git a/astroid/tests/testdata/python3/data/SSL1/Connection1.py b/astroid/tests/testdata/data/SSL1/Connection1.py
index 7373271d..7373271d 100644
--- a/astroid/tests/testdata/python3/data/SSL1/Connection1.py
+++ b/astroid/tests/testdata/data/SSL1/Connection1.py
diff --git a/astroid/tests/testdata/python3/data/SSL1/__init__.py b/astroid/tests/testdata/data/SSL1/__init__.py
index c83ededc..c83ededc 100644
--- a/astroid/tests/testdata/python3/data/SSL1/__init__.py
+++ b/astroid/tests/testdata/data/SSL1/__init__.py
diff --git a/astroid/tests/testdata/python2/data/__init__.py b/astroid/tests/testdata/data/__init__.py
index 332e2e72..332e2e72 100644
--- a/astroid/tests/testdata/python2/data/__init__.py
+++ b/astroid/tests/testdata/data/__init__.py
diff --git a/astroid/tests/testdata/python2/data/absimp/__init__.py b/astroid/tests/testdata/data/absimp/__init__.py
index b98444df..b98444df 100644
--- a/astroid/tests/testdata/python2/data/absimp/__init__.py
+++ b/astroid/tests/testdata/data/absimp/__init__.py
diff --git a/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py b/astroid/tests/testdata/data/absimp/sidepackage/__init__.py
index 239499a6..239499a6 100644
--- a/astroid/tests/testdata/python2/data/absimp/sidepackage/__init__.py
+++ b/astroid/tests/testdata/data/absimp/sidepackage/__init__.py
diff --git a/astroid/tests/testdata/python2/data/absimp/string.py b/astroid/tests/testdata/data/absimp/string.py
index e68e7496..e68e7496 100644
--- a/astroid/tests/testdata/python2/data/absimp/string.py
+++ b/astroid/tests/testdata/data/absimp/string.py
diff --git a/astroid/tests/testdata/python2/data/absimport.py b/astroid/tests/testdata/data/absimport.py
index f98effa6..f98effa6 100644
--- a/astroid/tests/testdata/python2/data/absimport.py
+++ b/astroid/tests/testdata/data/absimport.py
diff --git a/astroid/tests/testdata/python2/data/all.py b/astroid/tests/testdata/data/all.py
index 23f7d2b6..dd86abc5 100644
--- a/astroid/tests/testdata/python2/data/all.py
+++ b/astroid/tests/testdata/data/all.py
@@ -4,6 +4,6 @@ _bla = 2
other = 'o'
class Aaa: pass
-def func(): print 'yo'
+def func(): pass
__all__ = 'Aaa', '_bla', 'name'
diff --git a/astroid/tests/testdata/python2/data/appl/__init__.py b/astroid/tests/testdata/data/appl/__init__.py
index d652ffd9..d652ffd9 100644
--- a/astroid/tests/testdata/python2/data/appl/__init__.py
+++ b/astroid/tests/testdata/data/appl/__init__.py
diff --git a/astroid/tests/testdata/python3/data/appl/myConnection.py b/astroid/tests/testdata/data/appl/myConnection.py
index 49269534..398484ad 100644
--- a/astroid/tests/testdata/python3/data/appl/myConnection.py
+++ b/astroid/tests/testdata/data/appl/myConnection.py
@@ -1,3 +1,4 @@
+from __future__ import print_function
from data import SSL1
class MyConnection(SSL1.Connection):
diff --git a/astroid/tests/testdata/python2/data/descriptor_crash.py b/astroid/tests/testdata/data/descriptor_crash.py
index 11fbb4a2..11fbb4a2 100644
--- a/astroid/tests/testdata/python2/data/descriptor_crash.py
+++ b/astroid/tests/testdata/data/descriptor_crash.py
diff --git a/astroid/tests/testdata/python2/data/email.py b/astroid/tests/testdata/data/email.py
index dc593564..dc593564 100644
--- a/astroid/tests/testdata/python2/data/email.py
+++ b/astroid/tests/testdata/data/email.py
diff --git a/astroid/tests/testdata/python2/data/find_test/__init__.py b/astroid/tests/testdata/data/find_test/__init__.py
index e69de29b..e69de29b 100644
--- a/astroid/tests/testdata/python2/data/find_test/__init__.py
+++ b/astroid/tests/testdata/data/find_test/__init__.py
diff --git a/astroid/tests/testdata/python2/data/find_test/module.py b/astroid/tests/testdata/data/find_test/module.py
index e69de29b..e69de29b 100644
--- a/astroid/tests/testdata/python2/data/find_test/module.py
+++ b/astroid/tests/testdata/data/find_test/module.py
diff --git a/astroid/tests/testdata/python2/data/find_test/module2.py b/astroid/tests/testdata/data/find_test/module2.py
index e69de29b..e69de29b 100644
--- a/astroid/tests/testdata/python2/data/find_test/module2.py
+++ b/astroid/tests/testdata/data/find_test/module2.py
diff --git a/astroid/tests/testdata/python2/data/find_test/noendingnewline.py b/astroid/tests/testdata/data/find_test/noendingnewline.py
index e69de29b..e69de29b 100644
--- a/astroid/tests/testdata/python2/data/find_test/noendingnewline.py
+++ b/astroid/tests/testdata/data/find_test/noendingnewline.py
diff --git a/astroid/tests/testdata/python2/data/find_test/nonregr.py b/astroid/tests/testdata/data/find_test/nonregr.py
index e69de29b..e69de29b 100644
--- a/astroid/tests/testdata/python2/data/find_test/nonregr.py
+++ b/astroid/tests/testdata/data/find_test/nonregr.py
diff --git a/astroid/tests/testdata/python2/data/format.py b/astroid/tests/testdata/data/format.py
index 73797061..73797061 100644
--- a/astroid/tests/testdata/python2/data/format.py
+++ b/astroid/tests/testdata/data/format.py
diff --git a/astroid/tests/testdata/python2/data/lmfp/__init__.py b/astroid/tests/testdata/data/lmfp/__init__.py
index 74b26b82..74b26b82 100644
--- a/astroid/tests/testdata/python2/data/lmfp/__init__.py
+++ b/astroid/tests/testdata/data/lmfp/__init__.py
diff --git a/astroid/tests/testdata/python2/data/lmfp/foo.py b/astroid/tests/testdata/data/lmfp/foo.py
index 8f7de1e8..8f7de1e8 100644
--- a/astroid/tests/testdata/python2/data/lmfp/foo.py
+++ b/astroid/tests/testdata/data/lmfp/foo.py
diff --git a/astroid/tests/testdata/python2/data/module.py b/astroid/tests/testdata/data/module.py
index 118b16f9..84185cfa 100644
--- a/astroid/tests/testdata/python2/data/module.py
+++ b/astroid/tests/testdata/data/module.py
@@ -29,7 +29,7 @@ class YO:
def __init__(self):
try:
self.yo = 1
- except ValueError, ex:
+ except ValueError as ex:
pass
except (NameError, TypeError):
raise XXXError()
@@ -66,7 +66,7 @@ class YOUPI(YO):
def class_method(cls):
"""class method test"""
- exec a in b
+ pass
class_method = classmethod(class_method)
@@ -83,6 +83,6 @@ def four_args(a, b, c, d):
d = ((a) and (b)) or (c)
else:
c = ((a) and (b)) or (d)
- map(lambda x, y: (y, x), a)
+ list(map(lambda x, y: (y, x), a))
redirect = four_args
diff --git a/astroid/tests/testdata/python2/data/module1abs/__init__.py b/astroid/tests/testdata/data/module1abs/__init__.py
index 42949a44..42949a44 100644
--- a/astroid/tests/testdata/python2/data/module1abs/__init__.py
+++ b/astroid/tests/testdata/data/module1abs/__init__.py
diff --git a/astroid/tests/testdata/python2/data/module1abs/core.py b/astroid/tests/testdata/data/module1abs/core.py
index de101117..de101117 100644
--- a/astroid/tests/testdata/python2/data/module1abs/core.py
+++ b/astroid/tests/testdata/data/module1abs/core.py
diff --git a/astroid/tests/testdata/python3/data/module2.py b/astroid/tests/testdata/data/module2.py
index 582ccd98..72d08c51 100644
--- a/astroid/tests/testdata/python3/data/module2.py
+++ b/astroid/tests/testdata/data/module2.py
@@ -76,8 +76,6 @@ b = (1) | (((2) & (3)) ^ (8))
bb = ((1) | (two)) | (6)
ccc = ((one) & (two)) & (three)
dddd = ((x) ^ (o)) ^ (r)
-exec('c = 3')
-exec('c = 3', {}, {})
def raise_string(a=2, *args, **kwargs):
raise Exception('yo')
diff --git a/astroid/tests/testdata/python3/data/noendingnewline.py b/astroid/tests/testdata/data/noendingnewline.py
index e17b92cc..e17b92cc 100644
--- a/astroid/tests/testdata/python3/data/noendingnewline.py
+++ b/astroid/tests/testdata/data/noendingnewline.py
diff --git a/astroid/tests/testdata/python2/data/nonregr.py b/astroid/tests/testdata/data/nonregr.py
index 813469fe..813469fe 100644
--- a/astroid/tests/testdata/python2/data/nonregr.py
+++ b/astroid/tests/testdata/data/nonregr.py
diff --git a/astroid/tests/testdata/python3/data/notall.py b/astroid/tests/testdata/data/notall.py
index 9d35aa3a..9d35aa3a 100644
--- a/astroid/tests/testdata/python3/data/notall.py
+++ b/astroid/tests/testdata/data/notall.py
diff --git a/astroid/tests/testdata/python2/data/notamodule/file.py b/astroid/tests/testdata/data/notamodule/file.py
index e69de29b..e69de29b 100644
--- a/astroid/tests/testdata/python2/data/notamodule/file.py
+++ b/astroid/tests/testdata/data/notamodule/file.py
diff --git a/astroid/tests/testdata/python2/data/package/__init__.py b/astroid/tests/testdata/data/package/__init__.py
index 575d18b1..575d18b1 100644
--- a/astroid/tests/testdata/python2/data/package/__init__.py
+++ b/astroid/tests/testdata/data/package/__init__.py
diff --git a/astroid/tests/testdata/python2/data/package/absimport.py b/astroid/tests/testdata/data/package/absimport.py
index 33ed117c..33ed117c 100644
--- a/astroid/tests/testdata/python2/data/package/absimport.py
+++ b/astroid/tests/testdata/data/package/absimport.py
diff --git a/astroid/tests/testdata/python2/data/package/hello.py b/astroid/tests/testdata/data/package/hello.py
index b154c844..b154c844 100644
--- a/astroid/tests/testdata/python2/data/package/hello.py
+++ b/astroid/tests/testdata/data/package/hello.py
diff --git a/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py b/astroid/tests/testdata/data/package/import_package_subpackage_module.py
index ad442c16..ad442c16 100644
--- a/astroid/tests/testdata/python2/data/package/import_package_subpackage_module.py
+++ b/astroid/tests/testdata/data/package/import_package_subpackage_module.py
diff --git a/astroid/tests/testdata/python2/data/package/subpackage/__init__.py b/astroid/tests/testdata/data/package/subpackage/__init__.py
index dc4782e6..dc4782e6 100644
--- a/astroid/tests/testdata/python2/data/package/subpackage/__init__.py
+++ b/astroid/tests/testdata/data/package/subpackage/__init__.py
diff --git a/astroid/tests/testdata/python2/data/package/subpackage/module.py b/astroid/tests/testdata/data/package/subpackage/module.py
index 4b7244ba..4b7244ba 100644
--- a/astroid/tests/testdata/python2/data/package/subpackage/module.py
+++ b/astroid/tests/testdata/data/package/subpackage/module.py
diff --git a/astroid/tests/testdata/python2/data/recursion.py b/astroid/tests/testdata/data/recursion.py
index a34dad32..85f65134 100644
--- a/astroid/tests/testdata/python2/data/recursion.py
+++ b/astroid/tests/testdata/data/recursion.py
@@ -1,3 +1,3 @@
-""" For issue #25 """
-class Base(object):
+""" For issue #25 """
+class Base(object):
pass \ No newline at end of file
diff --git a/astroid/tests/testdata/python2/data/unicode_package/__init__.py b/astroid/tests/testdata/data/unicode_package/__init__.py
index 713e5591..713e5591 100644
--- a/astroid/tests/testdata/python2/data/unicode_package/__init__.py
+++ b/astroid/tests/testdata/data/unicode_package/__init__.py
diff --git a/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py b/astroid/tests/testdata/data/unicode_package/core/__init__.py
index e69de29b..e69de29b 100644
--- a/astroid/tests/testdata/python2/data/unicode_package/core/__init__.py
+++ b/astroid/tests/testdata/data/unicode_package/core/__init__.py
diff --git a/astroid/tests/testdata/python2/data/SSL1/Connection1.py b/astroid/tests/testdata/python2/data/SSL1/Connection1.py
deleted file mode 100644
index 6bbb1302..00000000
--- a/astroid/tests/testdata/python2/data/SSL1/Connection1.py
+++ /dev/null
@@ -1,14 +0,0 @@
-"""M2Crypto.SSL.Connection
-
-Copyright (c) 1999-2004 Ng Pheng Siong. All rights reserved."""
-from __future__ import print_function
-RCS_id='$Id: Connection1.py,v 1.1 2005-06-13 20:55:22 syt Exp $'
-
-#Some code deleted here
-
-class Connection:
-
- """An SSL connection."""
-
- def __init__(self, ctx, sock=None):
- print('init Connection')
diff --git a/astroid/tests/testdata/python2/data/SSL1/__init__.py b/astroid/tests/testdata/python2/data/SSL1/__init__.py
deleted file mode 100644
index a007b049..00000000
--- a/astroid/tests/testdata/python2/data/SSL1/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-from Connection1 import Connection
diff --git a/astroid/tests/testdata/python2/data/appl/myConnection.py b/astroid/tests/testdata/python2/data/appl/myConnection.py
deleted file mode 100644
index 5b24b259..00000000
--- a/astroid/tests/testdata/python2/data/appl/myConnection.py
+++ /dev/null
@@ -1,12 +0,0 @@
-from __future__ import print_function
-from data import SSL1
-class MyConnection(SSL1.Connection):
-
- """An SSL connection."""
-
- def __init__(self, dummy):
- print('MyConnection init')
-
-if __name__ == '__main__':
- myConnection = MyConnection(' ')
- raw_input('Press Enter to continue...')
diff --git a/astroid/tests/testdata/python2/data/invalid_encoding.py b/astroid/tests/testdata/python2/data/invalid_encoding.py
deleted file mode 100644
index dddd208e..00000000
--- a/astroid/tests/testdata/python2/data/invalid_encoding.py
+++ /dev/null
@@ -1 +0,0 @@
-# -*- coding: lala -*- \ No newline at end of file
diff --git a/astroid/tests/testdata/python2/data/module2.py b/astroid/tests/testdata/python2/data/module2.py
deleted file mode 100644
index 0a1bd1ad..00000000
--- a/astroid/tests/testdata/python2/data/module2.py
+++ /dev/null
@@ -1,143 +0,0 @@
-from data.module import YO, YOUPI
-import data
-
-
-class Specialization(YOUPI, YO):
- pass
-
-
-
-class Metaclass(type):
- pass
-
-
-
-class Interface:
- pass
-
-
-
-class MyIFace(Interface):
- pass
-
-
-
-class AnotherIFace(Interface):
- pass
-
-
-
-class MyException(Exception):
- pass
-
-
-
-class MyError(MyException):
- pass
-
-
-
-class AbstractClass(object):
-
- def to_override(self, whatever):
- raise NotImplementedError()
-
- def return_something(self, param):
- if param:
- return 'toto'
- return
-
-
-
-class Concrete0:
- __implements__ = MyIFace
-
-
-
-class Concrete1:
- __implements__ = (MyIFace, AnotherIFace)
-
-
-
-class Concrete2:
- __implements__ = (MyIFace, AnotherIFace)
-
-
-
-class Concrete23(Concrete1):
- pass
-
-del YO.member
-del YO
-[SYN1, SYN2] = (Concrete0, Concrete1)
-assert '1'
-b = (1) | (((2) & (3)) ^ (8))
-bb = ((1) | (two)) | (6)
-ccc = ((one) & (two)) & (three)
-dddd = ((x) ^ (o)) ^ (r)
-exec 'c = 3'
-exec 'c = 3' in {}, {}
-
-def raise_string(a=2, *args, **kwargs):
- raise Exception, 'yo'
- yield 'coucou'
- yield
-a = (b) + (2)
-c = (b) * (2)
-c = (b) / (2)
-c = (b) // (2)
-c = (b) - (2)
-c = (b) % (2)
-c = (b) ** (2)
-c = (b) << (2)
-c = (b) >> (2)
-c = ~b
-c = not b
-d = [c]
-e = d[:]
-e = d[a:b:c]
-raise_string(*args, **kwargs)
-print >> stream, 'bonjour'
-print >> stream, 'salut',
-
-def make_class(any, base=data.module.YO, *args, **kwargs):
- """check base is correctly resolved to Concrete0"""
-
-
- class Aaaa(base):
- """dynamic class"""
-
-
- return Aaaa
-from os.path import abspath
-import os as myos
-
-
-class A:
- pass
-
-
-
-class A(A):
- pass
-
-
-def generator():
- """A generator."""
- yield
-
-def not_a_generator():
- """A function that contains generator, but is not one."""
-
- def generator():
- yield
- genl = lambda : (yield)
-
-def with_metaclass(meta, *bases):
- return meta('NewBase', bases, {})
-
-
-class NotMetaclass(with_metaclass(Metaclass)):
- pass
-
-
diff --git a/astroid/tests/testdata/python2/data/noendingnewline.py b/astroid/tests/testdata/python2/data/noendingnewline.py
deleted file mode 100644
index e1d6e4a1..00000000
--- a/astroid/tests/testdata/python2/data/noendingnewline.py
+++ /dev/null
@@ -1,36 +0,0 @@
-import unittest
-
-
-class TestCase(unittest.TestCase):
-
- def setUp(self):
- unittest.TestCase.setUp(self)
-
-
- def tearDown(self):
- unittest.TestCase.tearDown(self)
-
- def testIt(self):
- self.a = 10
- self.xxx()
-
-
- def xxx(self):
- if False:
- pass
- print 'a'
-
- if False:
- pass
- pass
-
- if False:
- pass
- print 'rara'
-
-
-if __name__ == '__main__':
- print 'test2'
- unittest.main()
-
-
diff --git a/astroid/tests/testdata/python2/data/notall.py b/astroid/tests/testdata/python2/data/notall.py
deleted file mode 100644
index 042491e0..00000000
--- a/astroid/tests/testdata/python2/data/notall.py
+++ /dev/null
@@ -1,7 +0,0 @@
-name = 'a'
-_bla = 2
-other = 'o'
-class Aaa: pass
-
-def func(): return 'yo'
-
diff --git a/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg b/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg
deleted file mode 100644
index f62599c7..00000000
--- a/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.egg
+++ /dev/null
Binary files differ
diff --git a/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip b/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip
deleted file mode 100644
index f62599c7..00000000
--- a/astroid/tests/testdata/python3/data/MyPyPa-0.1.0-py2.5.zip
+++ /dev/null
Binary files differ
diff --git a/astroid/tests/testdata/python3/data/__init__.py b/astroid/tests/testdata/python3/data/__init__.py
deleted file mode 100644
index 332e2e72..00000000
--- a/astroid/tests/testdata/python3/data/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-__revision__="$Id: __init__.py,v 1.1 2005-06-13 20:55:20 syt Exp $"
diff --git a/astroid/tests/testdata/python3/data/absimp/__init__.py b/astroid/tests/testdata/python3/data/absimp/__init__.py
deleted file mode 100644
index b98444df..00000000
--- a/astroid/tests/testdata/python3/data/absimp/__init__.py
+++ /dev/null
@@ -1,5 +0,0 @@
-"""a package with absolute import activated
-"""
-
-from __future__ import absolute_import
-
diff --git a/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py b/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py
deleted file mode 100644
index 239499a6..00000000
--- a/astroid/tests/testdata/python3/data/absimp/sidepackage/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""a side package with nothing in it
-"""
-
diff --git a/astroid/tests/testdata/python3/data/absimp/string.py b/astroid/tests/testdata/python3/data/absimp/string.py
deleted file mode 100644
index e68e7496..00000000
--- a/astroid/tests/testdata/python3/data/absimp/string.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from __future__ import absolute_import, print_function
-import string
-print(string)
diff --git a/astroid/tests/testdata/python3/data/absimport.py b/astroid/tests/testdata/python3/data/absimport.py
deleted file mode 100644
index 88f9d955..00000000
--- a/astroid/tests/testdata/python3/data/absimport.py
+++ /dev/null
@@ -1,3 +0,0 @@
-
-import email
-from email import message
diff --git a/astroid/tests/testdata/python3/data/all.py b/astroid/tests/testdata/python3/data/all.py
deleted file mode 100644
index 587765b5..00000000
--- a/astroid/tests/testdata/python3/data/all.py
+++ /dev/null
@@ -1,9 +0,0 @@
-
-name = 'a'
-_bla = 2
-other = 'o'
-class Aaa: pass
-
-def func(): print('yo')
-
-__all__ = 'Aaa', '_bla', 'name'
diff --git a/astroid/tests/testdata/python3/data/appl/__init__.py b/astroid/tests/testdata/python3/data/appl/__init__.py
deleted file mode 100644
index d652ffd9..00000000
--- a/astroid/tests/testdata/python3/data/appl/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-"""
-Init
-"""
diff --git a/astroid/tests/testdata/python3/data/descriptor_crash.py b/astroid/tests/testdata/python3/data/descriptor_crash.py
deleted file mode 100644
index 11fbb4a2..00000000
--- a/astroid/tests/testdata/python3/data/descriptor_crash.py
+++ /dev/null
@@ -1,11 +0,0 @@
-
-import urllib
-
-class Page(object):
- _urlOpen = staticmethod(urllib.urlopen)
-
- def getPage(self, url):
- handle = self._urlOpen(url)
- data = handle.read()
- handle.close()
- return data
diff --git a/astroid/tests/testdata/python3/data/email.py b/astroid/tests/testdata/python3/data/email.py
deleted file mode 100644
index dc593564..00000000
--- a/astroid/tests/testdata/python3/data/email.py
+++ /dev/null
@@ -1 +0,0 @@
-"""fake email module to test absolute import doesn't grab this one"""
diff --git a/astroid/tests/testdata/python3/data/find_test/__init__.py b/astroid/tests/testdata/python3/data/find_test/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/astroid/tests/testdata/python3/data/find_test/__init__.py
+++ /dev/null
diff --git a/astroid/tests/testdata/python3/data/find_test/module.py b/astroid/tests/testdata/python3/data/find_test/module.py
deleted file mode 100644
index e69de29b..00000000
--- a/astroid/tests/testdata/python3/data/find_test/module.py
+++ /dev/null
diff --git a/astroid/tests/testdata/python3/data/find_test/module2.py b/astroid/tests/testdata/python3/data/find_test/module2.py
deleted file mode 100644
index e69de29b..00000000
--- a/astroid/tests/testdata/python3/data/find_test/module2.py
+++ /dev/null
diff --git a/astroid/tests/testdata/python3/data/find_test/noendingnewline.py b/astroid/tests/testdata/python3/data/find_test/noendingnewline.py
deleted file mode 100644
index e69de29b..00000000
--- a/astroid/tests/testdata/python3/data/find_test/noendingnewline.py
+++ /dev/null
diff --git a/astroid/tests/testdata/python3/data/find_test/nonregr.py b/astroid/tests/testdata/python3/data/find_test/nonregr.py
deleted file mode 100644
index e69de29b..00000000
--- a/astroid/tests/testdata/python3/data/find_test/nonregr.py
+++ /dev/null
diff --git a/astroid/tests/testdata/python3/data/format.py b/astroid/tests/testdata/python3/data/format.py
deleted file mode 100644
index 73797061..00000000
--- a/astroid/tests/testdata/python3/data/format.py
+++ /dev/null
@@ -1,34 +0,0 @@
-"""A multiline string
-"""
-
-function('aeozrijz\
-earzer', hop)
-# XXX write test
-x = [i for i in range(5)
- if i % 4]
-
-fonction(1,
- 2,
- 3,
- 4)
-
-def definition(a,
- b,
- c):
- return a + b + c
-
-class debile(dict,
- object):
- pass
-
-if aaaa: pass
-else:
- aaaa,bbbb = 1,2
- aaaa,bbbb = bbbb,aaaa
-# XXX write test
-hop = \
- aaaa
-
-
-__revision__.lower();
-
diff --git a/astroid/tests/testdata/python3/data/invalid_encoding.py b/astroid/tests/testdata/python3/data/invalid_encoding.py
deleted file mode 100644
index dddd208e..00000000
--- a/astroid/tests/testdata/python3/data/invalid_encoding.py
+++ /dev/null
@@ -1 +0,0 @@
-# -*- coding: lala -*- \ No newline at end of file
diff --git a/astroid/tests/testdata/python3/data/lmfp/__init__.py b/astroid/tests/testdata/python3/data/lmfp/__init__.py
deleted file mode 100644
index 74b26b82..00000000
--- a/astroid/tests/testdata/python3/data/lmfp/__init__.py
+++ /dev/null
@@ -1,2 +0,0 @@
-# force a "direct" python import
-from . import foo
diff --git a/astroid/tests/testdata/python3/data/lmfp/foo.py b/astroid/tests/testdata/python3/data/lmfp/foo.py
deleted file mode 100644
index 8f7de1e8..00000000
--- a/astroid/tests/testdata/python3/data/lmfp/foo.py
+++ /dev/null
@@ -1,6 +0,0 @@
-import sys
-if not getattr(sys, 'bar', None):
- sys.just_once = []
-# there used to be two numbers here because
-# of a load_module_from_path bug
-sys.just_once.append(42)
diff --git a/astroid/tests/testdata/python3/data/module.py b/astroid/tests/testdata/python3/data/module.py
deleted file mode 100644
index da4d7afb..00000000
--- a/astroid/tests/testdata/python3/data/module.py
+++ /dev/null
@@ -1,87 +0,0 @@
-"""test module for astroid
-"""
-
-__revision__ = '$Id: module.py,v 1.2 2005-11-02 11:56:54 syt Exp $'
-from astroid.tree.node_classes import Name as NameNode
-from astroid import modutils
-from astroid.utils import *
-import os.path
-MY_DICT = {}
-
-def global_access(key, val):
- """function test"""
- local = 1
- MY_DICT[key] = val
- for i in val:
- if i:
- del MY_DICT[i]
- continue
- else:
- break
- else:
- return
-
-
-class YO:
- """hehe"""
- a = 1
-
- def __init__(self):
- try:
- self.yo = 1
- except ValueError as ex:
- pass
- except (NameError, TypeError):
- raise XXXError()
- except:
- raise
-
-
-
-class YOUPI(YO):
- class_attr = None
-
- def __init__(self):
- self.member = None
-
- def method(self):
- """method test"""
- try:
- MY_DICT = {}
- local = None
- autre = [a for (a, b) in MY_DICT if b]
- if b in autre:
- return
- else:
- if a in autre:
- return 'hehe'
- global_access(local, val=autre)
- finally:
- return local
-
- def static_method():
- """static method test"""
- assert MY_DICT, '???'
- static_method = staticmethod(static_method)
-
- def class_method(cls):
- """class method test"""
- exec(a, b)
- class_method = classmethod(class_method)
-
-
-def four_args(a, b, c, d):
- """four arguments (was nested_args)"""
- while 1:
- if a:
- break
- a += +1
- else:
- b += -2
- if c:
- d = ((a) and (b)) or (c)
- else:
- c = ((a) and (b)) or (d)
- list(map(lambda x, y: (y, x), a))
-redirect = four_args
-
diff --git a/astroid/tests/testdata/python3/data/module1abs/__init__.py b/astroid/tests/testdata/python3/data/module1abs/__init__.py
deleted file mode 100644
index f9d5b686..00000000
--- a/astroid/tests/testdata/python3/data/module1abs/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-
-from . import core
-from .core import *
-print(sys.version)
diff --git a/astroid/tests/testdata/python3/data/module1abs/core.py b/astroid/tests/testdata/python3/data/module1abs/core.py
deleted file mode 100644
index de101117..00000000
--- a/astroid/tests/testdata/python3/data/module1abs/core.py
+++ /dev/null
@@ -1 +0,0 @@
-import sys
diff --git a/astroid/tests/testdata/python3/data/nonregr.py b/astroid/tests/testdata/python3/data/nonregr.py
deleted file mode 100644
index 78765c85..00000000
--- a/astroid/tests/testdata/python3/data/nonregr.py
+++ /dev/null
@@ -1,57 +0,0 @@
-
-
-try:
- enumerate = enumerate
-except NameError:
-
- def enumerate(iterable):
- """emulates the python2.3 enumerate() function"""
- i = 0
- for val in iterable:
- yield i, val
- i += 1
-
-def toto(value):
- for k, v in value:
- print(v.get('yo'))
-
-
-import imp
-fp, mpath, desc = imp.find_module('optparse',a)
-s_opt = imp.load_module('std_optparse', fp, mpath, desc)
-
-class OptionParser(s_opt.OptionParser):
-
- def parse_args(self, args=None, values=None, real_optparse=False):
- if real_optparse:
- pass
-## return super(OptionParser, self).parse_args()
- else:
- import optcomp
- optcomp.completion(self)
-
-
-class Aaa(object):
- """docstring"""
- def __init__(self):
- self.__setattr__('a','b')
- pass
-
- def one_public(self):
- """docstring"""
- pass
-
- def another_public(self):
- """docstring"""
- pass
-
-class Ccc(Aaa):
- """docstring"""
-
- class Ddd(Aaa):
- """docstring"""
- pass
-
- class Eee(Ddd):
- """docstring"""
- pass
diff --git a/astroid/tests/testdata/python3/data/notamodule/file.py b/astroid/tests/testdata/python3/data/notamodule/file.py
deleted file mode 100644
index e69de29b..00000000
--- a/astroid/tests/testdata/python3/data/notamodule/file.py
+++ /dev/null
diff --git a/astroid/tests/testdata/python3/data/package/__init__.py b/astroid/tests/testdata/python3/data/package/__init__.py
deleted file mode 100644
index 575d18b1..00000000
--- a/astroid/tests/testdata/python3/data/package/__init__.py
+++ /dev/null
@@ -1,4 +0,0 @@
-"""package's __init__ file"""
-
-
-from . import subpackage
diff --git a/astroid/tests/testdata/python3/data/package/absimport.py b/astroid/tests/testdata/python3/data/package/absimport.py
deleted file mode 100644
index 33ed117c..00000000
--- a/astroid/tests/testdata/python3/data/package/absimport.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from __future__ import absolute_import, print_function
-import import_package_subpackage_module # fail
-print(import_package_subpackage_module)
-
-from . import hello as hola
-
diff --git a/astroid/tests/testdata/python3/data/package/hello.py b/astroid/tests/testdata/python3/data/package/hello.py
deleted file mode 100644
index b154c844..00000000
--- a/astroid/tests/testdata/python3/data/package/hello.py
+++ /dev/null
@@ -1,2 +0,0 @@
-"""hello module"""
-
diff --git a/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py b/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py
deleted file mode 100644
index ad442c16..00000000
--- a/astroid/tests/testdata/python3/data/package/import_package_subpackage_module.py
+++ /dev/null
@@ -1,49 +0,0 @@
-# pylint: disable-msg=I0011,C0301,W0611
-"""I found some of my scripts trigger off an AttributeError in pylint
-0.8.1 (with common 0.12.0 and astroid 0.13.1).
-
-Traceback (most recent call last):
- File "/usr/bin/pylint", line 4, in ?
- lint.Run(sys.argv[1:])
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 729, in __init__
- linter.check(args)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 412, in check
- self.check_file(filepath, modname, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 426, in check_file
- astroid = self._check_file(filepath, modname, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 450, in _check_file
- self.check_astroid_module(astroid, checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 494, in check_astroid_module
- self.astroid_events(astroid, [checker for checker in checkers
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
- self.astroid_events(child, checkers, _reversed_checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 511, in astroid_events
- self.astroid_events(child, checkers, _reversed_checkers)
- File "/usr/lib/python2.4/site-packages/pylint/lint.py", line 508, in astroid_events
- checker.visit(astroid)
- File "/usr/lib/python2.4/site-packages/logilab/astroid/utils.py", line 84, in visit
- method(node)
- File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 295, in visit_import
- self._check_module_attrs(node, module, name_parts[1:])
- File "/usr/lib/python2.4/site-packages/pylint/checkers/variables.py", line 357, in _check_module_attrs
- self.add_message('E0611', args=(name, module.name),
-AttributeError: Import instance has no attribute 'name'
-
-
-You can reproduce it by:
-(1) create package structure like the following:
-
-package/
- __init__.py
- subpackage/
- __init__.py
- module.py
-
-(2) in package/__init__.py write:
-
-import subpackage
-
-(3) run pylint with a script importing package.subpackage.module.
-"""
-__revision__ = '$Id: import_package_subpackage_module.py,v 1.1 2005-11-10 15:59:32 syt Exp $'
-import package.subpackage.module
diff --git a/astroid/tests/testdata/python3/data/package/subpackage/__init__.py b/astroid/tests/testdata/python3/data/package/subpackage/__init__.py
deleted file mode 100644
index dc4782e6..00000000
--- a/astroid/tests/testdata/python3/data/package/subpackage/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-"""package.subpackage"""
diff --git a/astroid/tests/testdata/python3/data/package/subpackage/module.py b/astroid/tests/testdata/python3/data/package/subpackage/module.py
deleted file mode 100644
index 4b7244ba..00000000
--- a/astroid/tests/testdata/python3/data/package/subpackage/module.py
+++ /dev/null
@@ -1 +0,0 @@
-"""package.subpackage.module"""
diff --git a/astroid/tests/testdata/python3/data/recursion.py b/astroid/tests/testdata/python3/data/recursion.py
deleted file mode 100644
index a34dad32..00000000
--- a/astroid/tests/testdata/python3/data/recursion.py
+++ /dev/null
@@ -1,3 +0,0 @@
-""" For issue #25 """
-class Base(object):
- pass \ No newline at end of file
diff --git a/astroid/tests/testdata/python3/data/unicode_package/__init__.py b/astroid/tests/testdata/python3/data/unicode_package/__init__.py
deleted file mode 100644
index 713e5591..00000000
--- a/astroid/tests/testdata/python3/data/unicode_package/__init__.py
+++ /dev/null
@@ -1 +0,0 @@
-x = "șțîâ" \ No newline at end of file
diff --git a/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py b/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/astroid/tests/testdata/python3/data/unicode_package/core/__init__.py
+++ /dev/null
diff --git a/astroid/tests/unittest_brain.py b/astroid/tests/unittest_brain.py
index 85f6f04c..a12b242e 100644
--- a/astroid/tests/unittest_brain.py
+++ b/astroid/tests/unittest_brain.py
@@ -84,7 +84,9 @@ class HashlibTest(unittest.TestCase):
self.assertIn('block_size', class_obj)
self.assertIn('digest_size', class_obj)
self.assertEqual(len(class_obj['__init__'].args.args), 2)
- self.assertEqual(len(class_obj['__init__'].args.defaults), 1)
+ default = class_obj['__init__'].args.args[1].default
+ self.assertIsInstance(default, nodes.Const)
+ self.assertEqual(default.value, '')
self.assertEqual(len(class_obj['update'].args.args), 2)
self.assertEqual(len(class_obj['digest'].args.args), 1)
self.assertEqual(len(class_obj['hexdigest'].args.args), 1)
diff --git a/astroid/tests/unittest_builder.py b/astroid/tests/unittest_builder.py
index 206c7da2..813c2e3d 100644
--- a/astroid/tests/unittest_builder.py
+++ b/astroid/tests/unittest_builder.py
@@ -39,7 +39,41 @@ BUILTINS = six.moves.builtins.__name__
class FromToLineNoTest(unittest.TestCase):
def setUp(self):
- self.astroid = resources.build_file('data/format.py')
+ self.astroid = builder.parse('''
+ """A multiline string
+ """
+
+ function('aeozrijz\
+ earzer', hop)
+ # XXX write test
+ x = [i for i in range(5)
+ if i % 4]
+
+ fonction(1,
+ 2,
+ 3,
+ 4)
+
+ def definition(a,
+ b,
+ c):
+ return a + b + c
+
+ class debile(dict,
+ object):
+ pass
+
+ if aaaa: pass
+ else:
+ aaaa,bbbb = 1,2
+ aaaa,bbbb = bbbb,aaaa
+ # XXX write test
+ hop = \
+ aaaa
+
+
+ __revision__.lower();
+ ''')
def test_callfunc_lineno(self):
stmts = self.astroid.body
@@ -48,16 +82,16 @@ class FromToLineNoTest(unittest.TestCase):
# earzer', hop)
discard = stmts[0]
self.assertIsInstance(discard, nodes.Expr)
- self.assertEqual(discard.fromlineno, 4)
+ self.assertEqual(discard.fromlineno, 5)
self.assertEqual(discard.tolineno, 5)
callfunc = discard.value
self.assertIsInstance(callfunc, nodes.Call)
- self.assertEqual(callfunc.fromlineno, 4)
+ self.assertEqual(callfunc.fromlineno, 5)
self.assertEqual(callfunc.tolineno, 5)
name = callfunc.func
self.assertIsInstance(name, nodes.Name)
- self.assertEqual(name.fromlineno, 4)
- self.assertEqual(name.tolineno, 4)
+ self.assertEqual(name.fromlineno, 5)
+ self.assertEqual(name.tolineno, 5)
strarg = callfunc.args[0]
self.assertIsInstance(strarg, nodes.Const)
if hasattr(sys, 'pypy_version_info'):
@@ -263,10 +297,6 @@ class BuilderTest(unittest.TestCase):
with self.assertRaises(exceptions.AstroidSyntaxError):
self.builder.string_build('"\\x1"')
- def test_missing_newline(self):
- """check that a file with no trailing new line is parseable"""
- resources.build_file('data/noendingnewline.py')
-
def test_missing_file(self):
with self.assertRaises(exceptions.AstroidBuildingError):
resources.build_file('data/inexistant.py')
@@ -711,7 +741,8 @@ class FileBuildTest(unittest.TestCase):
def test_unknown_encoding(self):
with self.assertRaises(exceptions.AstroidSyntaxError):
- resources.build_file('data/invalid_encoding.py')
+ with resources.tempfile_with_content(b'# -*- coding: lala -*-') as tmp:
+ builder.AstroidBuilder().file_build(tmp)
class ModuleBuildTest(resources.SysPathSetup, FileBuildTest):
diff --git a/astroid/tests/unittest_modutils.py b/astroid/tests/unittest_modutils.py
index 3740aa26..6dfd3bd8 100644
--- a/astroid/tests/unittest_modutils.py
+++ b/astroid/tests/unittest_modutils.py
@@ -244,6 +244,7 @@ class GetModuleFilesTest(unittest.TestCase):
def test_get_module_files_1(self):
package = resources.find('data/find_test')
modules = set(modutils.get_module_files(package, []))
+
expected = ['__init__.py', 'module.py', 'module2.py',
'noendingnewline.py', 'nonregr.py']
self.assertEqual(modules,
@@ -254,6 +255,7 @@ class GetModuleFilesTest(unittest.TestCase):
"""
non_package = resources.find('data/notamodule')
modules = modutils.get_module_files(non_package, [], list_all=True)
+
self.assertEqual(
modules,
[os.path.join(non_package, 'file.py')],
diff --git a/astroid/tests/unittest_nodes.py b/astroid/tests/unittest_nodes.py
index aeab26e2..419df968 100644
--- a/astroid/tests/unittest_nodes.py
+++ b/astroid/tests/unittest_nodes.py
@@ -106,6 +106,7 @@ class AsStringTest(resources.SysPathSetup, unittest.TestCase):
with open(resources.find('data/module.py'), 'r') as fobj:
self.assertMultiLineEqual(module.as_string(), fobj.read())
+ maxDiff = None
def test_module2_as_string(self):
"""check as_string on a whole module prepared to be returned identically
"""
@@ -491,6 +492,9 @@ class NameNodeTest(unittest.TestCase):
class ArgumentsNodeTC(unittest.TestCase):
+
+ @unittest.skipIf(sys.version_info[:2] == (3, 3),
+ "Line numbering is broken on Python 3.3.")
def test_linenumbering(self):
ast = builder.parse('''
def func(a,
@@ -509,14 +513,6 @@ class ArgumentsNodeTC(unittest.TestCase):
self.skipTest('FIXME http://bugs.python.org/issue10445 '
'(no line number on function args)')
- def test_builtin_fromlineno_missing(self):
- cls = test_utils.extract_node('''
- class Foo(Exception): #@
- pass
- ''')
- new = cls.getattr('__new__')[-1]
- self.assertEqual(new.args.fromlineno, 0)
-
class UnboundMethodNodeTest(unittest.TestCase):
diff --git a/astroid/tests/unittest_python3.py b/astroid/tests/unittest_python3.py
index 1dd07c61..3cd7b1f5 100644
--- a/astroid/tests/unittest_python3.py
+++ b/astroid/tests/unittest_python3.py
@@ -20,6 +20,7 @@ import unittest
from astroid import nodes
from astroid.tree.node_classes import Assign, Expr, YieldFrom, Name, Const
+from astroid import raw_building
from astroid.builder import AstroidBuilder
from astroid.tree.scoped_nodes import ClassDef, FunctionDef
from astroid.test_utils import require_version, extract_node
@@ -187,31 +188,31 @@ class Python3TC(unittest.TestCase):
pass
"""))
func = astroid['test']
- self.assertIsInstance(func.args.varargannotation, Name)
- self.assertEqual(func.args.varargannotation.name, 'float')
- self.assertIsInstance(func.args.kwargannotation, Name)
- self.assertEqual(func.args.kwargannotation.name, 'int')
+ self.assertIsInstance(func.args.vararg.annotation, Name)
+ self.assertEqual(func.args.vararg.annotation.name, 'float')
+ self.assertIsInstance(func.args.kwarg.annotation, Name)
+ self.assertEqual(func.args.kwarg.annotation.name, 'int')
self.assertIsInstance(func.returns, Name)
self.assertEqual(func.returns.name, 'int')
arguments = func.args
- self.assertIsInstance(arguments.annotations[0], Name)
- self.assertEqual(arguments.annotations[0].name, 'int')
- self.assertIsInstance(arguments.annotations[1], Name)
- self.assertEqual(arguments.annotations[1].name, 'str')
- self.assertIsInstance(arguments.annotations[2], Const)
- self.assertIsNone(arguments.annotations[2].value)
- self.assertIsNone(arguments.annotations[3])
- self.assertIsNone(arguments.annotations[4])
+ self.assertIsInstance(arguments.args[0].annotation, Name)
+ self.assertEqual(arguments.args[0].annotation.name, 'int')
+ self.assertIsInstance(arguments.args[1].annotation, Name)
+ self.assertEqual(arguments.args[1].annotation.name, 'str')
+ self.assertIsInstance(arguments.args[2].annotation, Const)
+ self.assertIsNone(arguments.args[2].annotation.value)
+ self.assertIs(arguments.args[3].annotation, nodes.Empty)
+ self.assertIs(arguments.args[4].annotation, nodes.Empty)
astroid = self.builder.string_build(dedent("""
def test(a: int=1, b: str=2):
pass
"""))
func = astroid['test']
- self.assertIsInstance(func.args.annotations[0], Name)
- self.assertEqual(func.args.annotations[0].name, 'int')
- self.assertIsInstance(func.args.annotations[1], Name)
- self.assertEqual(func.args.annotations[1].name, 'str')
+ self.assertIsInstance(func.args.args[0].annotation, Name)
+ self.assertEqual(func.args.args[0].annotation.name, 'int')
+ self.assertIsInstance(func.args.args[1].annotation, Name)
+ self.assertEqual(func.args.args[1].annotation.name, 'str')
self.assertIsNone(func.returns)
@require_version('3.0')
@@ -249,6 +250,13 @@ class Python3TC(unittest.TestCase):
self.assertIsInstance(value, nodes.Const)
self.assertEqual(value.value, expected)
+ @require_version('3.4')
+ def test_positional_only_parameters(self):
+ ast = raw_building.ast_from_object(issubclass)
+ self.assertEqual(len(ast.args.positional_only), 2)
+ for name, arg in zip(('cls', 'class_or_tuple'), ast.args.positional_only):
+ self.assertEqual(arg.name, name)
+
if __name__ == '__main__':
unittest.main()
diff --git a/astroid/tests/unittest_regrtest.py b/astroid/tests/unittest_regrtest.py
index 9d36befc..21b93dc8 100644
--- a/astroid/tests/unittest_regrtest.py
+++ b/astroid/tests/unittest_regrtest.py
@@ -24,6 +24,7 @@ import six
from astroid import MANAGER, Instance, nodes
from astroid.builder import AstroidBuilder
from astroid import exceptions
+from astroid.interpreter import lookup
from astroid.manager import AstroidManager
from astroid import raw_building
from astroid.test_utils import require_version, extract_node, bootstrap
@@ -310,6 +311,13 @@ def test():
with self.assertRaises(AttributeError):
node.qname
+ def test_null_fromlineno_does_not_crash_lookup(self):
+ node = nodes.ImportFrom('test', [('a', 'a')])
+ function = nodes.FunctionDef()
+ locals_ = {'a': [function]}
+ lookup._get_locals(node, locals_)
+
+
class Whatever(object):
a = property(lambda x: x, lambda x: x)
diff --git a/astroid/tests/unittest_scoped_nodes.py b/astroid/tests/unittest_scoped_nodes.py
index d9600365..c362f274 100644
--- a/astroid/tests/unittest_scoped_nodes.py
+++ b/astroid/tests/unittest_scoped_nodes.py
@@ -110,9 +110,23 @@ class ModuleNodeTest(ModuleLoader, unittest.TestCase):
self.assertRaises(InferenceError, self.nonregr.igetattr, 'YOAA')
def test_wildcard_import_names(self):
- m = resources.build_file('data/all.py', 'all')
+ m = builder.parse('''
+ name = 'a'
+ _bla = 2
+ other = 'o'
+ class Aaa: pass
+ def func(): print('yo')
+ __all__ = 'Aaa', '_bla', 'name'
+ ''')
self.assertEqual(m.wildcard_import_names(), ['Aaa', '_bla', 'name'])
- m = resources.build_file('data/notall.py', 'notall')
+ m = builder.parse('''
+ name = 'a'
+ _bla = 2
+ other = 'o'
+ class Aaa: pass
+
+ def func(): return 'yo'
+ ''')
res = sorted(m.wildcard_import_names())
self.assertEqual(res, ['Aaa', 'func', 'name', 'other'])
@@ -214,14 +228,14 @@ class ModuleNodeTest(ModuleLoader, unittest.TestCase):
self.assertEqual(stream.read().decode(), data)
def test_file_stream_physical(self):
- path = resources.find('data/all.py')
+ path = resources.find('data/absimport.py')
astroid = builder.AstroidBuilder().file_build(path, 'all')
with open(path, 'rb') as file_io:
with astroid.stream() as stream:
self.assertEqual(stream.read(), file_io.read())
def test_stream_api(self):
- path = resources.find('data/all.py')
+ path = resources.find('data/absimport.py')
astroid = builder.AstroidBuilder().file_build(path, 'all')
stream = astroid.stream()
self.assertTrue(hasattr(stream, 'close'))
@@ -284,7 +298,7 @@ class FunctionNodeTest(ModuleLoader, unittest.TestCase):
tree = builder.parse(code)
func = tree['nested_args']
self.assertEqual(sorted(func.locals), ['a', 'b', 'c', 'd'])
- self.assertEqual(func.args.format_args(), 'a, (b, c, d)')
+ self.assertEqual(func.args.format_args(), 'a, b, c, d')
def test_four_args(self):
func = self.module['four_args']
diff --git a/astroid/tree/base.py b/astroid/tree/base.py
index 43f77d12..58298b8d 100644
--- a/astroid/tree/base.py
+++ b/astroid/tree/base.py
@@ -226,33 +226,12 @@ class NodeNG(object):
"""return the previous sibling statement"""
return self.parent.previous_sibling()
- def nearest(self, nodes):
- """return the node which is the nearest before this one in the
- given list of nodes
- """
- myroot = self.root()
- mylineno = self.fromlineno
- nearest = None, 0
- for node in nodes:
- assert node.root() is myroot, \
- 'nodes %s and %s are not from the same module' % (self, node)
- lineno = node.fromlineno
- if node.fromlineno > mylineno:
- break
- if lineno > nearest[1]:
- nearest = node, lineno
- # FIXME: raise an exception if nearest is None ?
- return nearest[0]
-
# these are lazy because they're relatively expensive to compute for every
# single node, and they rarely get looked at
@decorators.cachedproperty
def fromlineno(self):
- if self.lineno is None:
- return self._fixed_source_line()
- else:
- return self.lineno
+ return self.lineno
@decorators.cachedproperty
def tolineno(self):
@@ -266,29 +245,6 @@ class NodeNG(object):
else:
return lastchild.tolineno
- # TODO / FIXME:
- assert self.fromlineno is not None, self
- assert self.tolineno is not None, self
-
- def _fixed_source_line(self):
- """return the line number where the given node appears
-
- we need this method since not all nodes have the lineno attribute
- correctly set...
- """
- line = self.lineno
- _node = self
- try:
- while line is None:
- _node = next(_node.get_children())
- line = _node.lineno
- except StopIteration:
- _node = self.parent
- while _node and line is None:
- line = _node.lineno
- _node = _node.parent
- return line
-
def block_range(self, lineno):
"""handle block line numbers range for non block opening statements
"""
@@ -610,7 +566,6 @@ class LookupMixIn(object):
# take care node may be missing lineno information (this is the case for
# nodes inserted for living objects)
if myframe is frame and mystmt.fromlineno is not None:
- assert mystmt.fromlineno is not None, mystmt
mylineno = mystmt.fromlineno + offset
else:
# disabling lineno filtering
@@ -620,7 +575,7 @@ class LookupMixIn(object):
for node in stmts:
stmt = node.statement()
# line filtering is on and we have reached our location, break
- if mylineno > 0 and stmt.fromlineno > mylineno:
+ if mylineno > 0 and stmt.fromlineno and stmt.fromlineno > mylineno:
break
assert hasattr(node, 'assign_type'), (node, node.scope(),
node.scope().locals)
@@ -678,7 +633,7 @@ class LookupMixIn(object):
if not (optional_assign or interpreterutil.are_exclusive(_stmts[pindex], node)):
del _stmt_parents[pindex]
del _stmts[pindex]
- if isinstance(node, treeabc.AssignName):
+ if isinstance(node, (treeabc.Parameter, treeabc.AssignName)):
if not optional_assign and stmt.parent is mystmt.parent:
_stmts = []
_stmt_parents = []
diff --git a/astroid/tree/node_classes.py b/astroid/tree/node_classes.py
index 78a9afc8..7189b068 100644
--- a/astroid/tree/node_classes.py
+++ b/astroid/tree/node_classes.py
@@ -98,18 +98,36 @@ class AssignedStmtsMixin(object):
# Name classes
-@util.register_implementation(treeabc.AssignName)
-class AssignName(base.LookupMixIn, base.ParentAssignTypeMixin,
- AssignedStmtsMixin, base.NodeNG):
- """class representing an AssignName node"""
+
+class BaseAssignName(base.LookupMixIn, base.ParentAssignTypeMixin,
+ AssignedStmtsMixin, base.NodeNG):
_other_fields = ('name',)
def __init__(self, name=None, lineno=None, col_offset=None, parent=None):
self.name = name
- super(AssignName, self).__init__(lineno, col_offset, parent)
+ super(BaseAssignName, self).__init__(lineno, col_offset, parent)
infer_lhs = inference.infer_name
+@util.register_implementation(treeabc.AssignName)
+class AssignName(BaseAssignName):
+ """class representing an AssignName node"""
+
+
+@util.register_implementation(treeabc.Parameter)
+class Parameter(BaseAssignName):
+
+ _astroid_fields = ('default', 'annotation')
+ _other_fields = ('name', )
+
+ def __init__(self, name=None, lineno=None, col_offset=None, parent=None):
+ super(Parameter, self).__init__(name=name, lineno=lineno,
+ col_offset=col_offset, parent=parent)
+
+ def postinit(self, default, annotation):
+ self.default = default
+ self.annotation = annotation
+
@util.register_implementation(treeabc.DelName)
class DelName(base.LookupMixIn, base.ParentAssignTypeMixin, base.NodeNG):
@@ -129,54 +147,25 @@ class Name(base.LookupMixIn, base.NodeNG):
def __init__(self, name=None, lineno=None, col_offset=None, parent=None):
self.name = name
super(Name, self).__init__(lineno, col_offset, parent)
-
+
@util.register_implementation(treeabc.Arguments)
class Arguments(base.AssignTypeMixin, AssignedStmtsMixin, base.NodeNG):
"""class representing an Arguments node"""
- if six.PY3:
- # Python 3.4+ uses a different approach regarding annotations,
- # each argument is a new class, _ast.arg, which exposes an
- # 'annotation' attribute. In astroid though, arguments are exposed
- # as is in the Arguments node and the only way to expose annotations
- # is by using something similar with Python 3.3:
- # - we expose 'varargannotation' and 'kwargannotation' of annotations
- # of varargs and kwargs.
- # - we expose 'annotation', a list with annotations for
- # for each normal argument. If an argument doesn't have an
- # annotation, its value will be None.
-
- _astroid_fields = ('args', 'defaults', 'kwonlyargs',
- 'kw_defaults', 'annotations', 'kwonly_annotations',
- 'varargannotation', 'kwargannotation')
- varargannotation = None
- kwargannotation = None
- else:
- _astroid_fields = ('args', 'defaults', 'kwonlyargs', 'kw_defaults')
- _other_fields = ('vararg', 'kwarg')
- def __init__(self, vararg=None, kwarg=None, parent=None):
+ _astroid_fields = ('args', 'vararg', 'kwarg', 'keyword_only', 'positional_only')
+
+ def __init__(self, parent=None):
+ # We don't want lineno and col_offset from the parent's __init__.
+ super(Arguments, self).__init__(parent=parent)
+
+ def postinit(self, args, vararg, kwarg, keyword_only, positional_only):
+ self.args = args
self.vararg = vararg
self.kwarg = kwarg
- self.parent = parent
- self.args = []
- self.defaults = []
- self.kwonlyargs = []
- self.kw_defaults = []
- self.annotations = []
- self.kwonly_annotations = []
-
- def postinit(self, args, defaults, kwonlyargs, kw_defaults,
- annotations, kwonly_annotations, varargannotation=None,
- kwargannotation=None):
- self.args = args
- self.defaults = defaults
- self.kwonlyargs = kwonlyargs
- self.kw_defaults = kw_defaults
- self.annotations = annotations
- self.varargannotation = varargannotation
- self.kwargannotation = kwargannotation
- self.kwonly_annotations = kwonly_annotations
+ self.keyword_only = keyword_only
+ self.positional_only = positional_only
+ self.positional_and_keyword = self.args + self.positional_only
def _infer_name(self, frame, name):
if self.parent is frame:
@@ -185,25 +174,25 @@ class Arguments(base.AssignTypeMixin, AssignedStmtsMixin, base.NodeNG):
@decorators.cachedproperty
def fromlineno(self):
- lineno = super(Arguments, self).fromlineno
- return max(lineno, self.parent.fromlineno or 0)
+ # Let the Function's lineno be the lineno for this.
+ if self.parent.fromlineno:
+ return self.parent.fromlineno
+
+ return super(Arguments, self).fromlineno
def format_args(self):
"""return arguments formatted as string"""
result = []
- if self.args:
- result.append(
- _format_args(self.args, self.defaults,
- getattr(self, 'annotations', None))
- )
+ if self.positional_and_keyword:
+ result.append(_format_args(self.positional_and_keyword))
if self.vararg:
- result.append('*%s' % self.vararg)
- if self.kwonlyargs:
+ result.append('*%s' % _format_args((self.vararg, )))
+ if self.keyword_only:
if not self.vararg:
result.append('*')
- result.append(_format_args(self.kwonlyargs, self.kw_defaults))
+ result.append(_format_args(self.keyword_only))
if self.kwarg:
- result.append('**%s' % self.kwarg)
+ result.append('**%s' % _format_args((self.kwarg, )))
return ', '.join(result)
def default_value(self, argname):
@@ -211,28 +200,28 @@ class Arguments(base.AssignTypeMixin, AssignedStmtsMixin, base.NodeNG):
:raise `NoDefault`: if there is no default value defined
"""
- i = _find_arg(argname, self.args)[0]
- if i is not None:
- idx = i - (len(self.args) - len(self.defaults))
- if idx >= 0:
- return self.defaults[idx]
- i = _find_arg(argname, self.kwonlyargs)[0]
- if i is not None and self.kw_defaults[i] is not None:
- return self.kw_defaults[i]
+ for place in (self.positional_and_keyword, self.keyword_only):
+ i = _find_arg(argname, place)[0]
+ if i is not None:
+ value = place[i]
+ if not value.default:
+ continue
+ return value.default
+
raise exceptions.NoDefault(func=self.parent, name=argname)
def is_argument(self, name):
"""return True if the name is defined in arguments"""
- if name == self.vararg:
+ if self.vararg and name == self.vararg.name:
return True
- if name == self.kwarg:
+ if self.kwarg and name == self.kwarg.name:
return True
return self.find_argname(name, True)[1] is not None
def find_argname(self, argname, rec=False):
"""return index and Name node with given name"""
- if self.args: # self.args may be None in some cases (builtin function)
- return _find_arg(argname, self.args, rec)
+ if self.positional_and_keyword: # self.args may be None in some cases (builtin function)
+ return _find_arg(argname, self.positional_and_keyword, rec)
return None, None
def get_children(self):
@@ -254,27 +243,24 @@ def _find_arg(argname, args, rec=False):
return None, None
-def _format_args(args, defaults=None, annotations=None):
+def _format_args(args):
values = []
- if args is None:
+ if not args:
return ''
- if annotations is None:
- annotations = []
- if defaults is not None:
- default_offset = len(args) - len(defaults)
- packed = six.moves.zip_longest(args, annotations)
- for i, (arg, annotation) in enumerate(packed):
+ for i, arg in enumerate(args):
if isinstance(arg, Tuple):
values.append('(%s)' % _format_args(arg.elts))
else:
argname = arg.name
- if annotation is not None:
+ annotation = arg.annotation
+ if annotation:
argname += ':' + annotation.as_string()
values.append(argname)
+
+ default = arg.default
+ if default:
+ values[-1] += '=' + default.as_string()
- if defaults is not None and i >= default_offset:
- if defaults[i-default_offset] is not None:
- values[-1] += '=' + defaults[i-default_offset].as_string()
return ', '.join(values)
@@ -1319,6 +1305,22 @@ class DictUnpack(base.NodeNG):
"""Represents the unpacking of dicts into dicts using PEP 448."""
+@object.__new__
+@util.register_implementation(treeabc.Empty)
+class Empty(base.NodeNG):
+ """Empty nodes represents the lack of something
+
+ For instance, they can be used to represent missing annotations
+ or defaults for arguments or anything where None is a valid
+ value.
+ """
+
+ def __bool__(self):
+ return False
+
+ __nonzero__ = __bool__
+
+
# Register additional inference dispatched functions. We do
# this here, since we need to pass this module as an argument
# to these functions, in order to avoid circular dependencies
diff --git a/astroid/tree/rebuilder.py b/astroid/tree/rebuilder.py
index 90a02f73..074aea1e 100644
--- a/astroid/tree/rebuilder.py
+++ b/astroid/tree/rebuilder.py
@@ -20,6 +20,7 @@ order to get a single Astroid representation
"""
import ast
+import collections
import sys
import astroid
@@ -113,6 +114,53 @@ def _get_context(node):
return CONTEXTS.get(type(node.ctx), astroid.Load)
+class ParameterVisitor(object):
+ """A visitor which is used for building the components of Arguments node."""
+
+ def __init__(self, visitor):
+ self._visitor = visitor
+
+ def visit(self, param_node, *args):
+ cls_name = param_node.__class__.__name__
+ visit_name = 'visit_' + REDIRECT.get(cls_name, cls_name).lower()
+ visit_method = getattr(self, visit_name)
+ return visit_method(param_node, *args)
+
+ def visit_arg(self, param_node, *args):
+ name = param_node.arg
+ return self._build_parameter(param_node, name, *args)
+
+ def visit_name(self, param_node, *args):
+ name = param_node.id
+ return self._build_parameter(param_node, name, *args)
+
+ def visit_tuple(self, param_node, parent, default):
+ # We're not supporting nested arguments anymore, but in order to
+ # simply not crash when running on Python 2, we're unpacking the elements
+ # before hand. We simply don't want to support this feature anymore,
+ # so it's possible to be broken.
+ converted_node = self._visitor.visit(param_node, parent)
+ for element in converted_node.elts:
+ param = nodes.Parameter(name=element.name, lineno=param_node.lineno,
+ col_offset=param_node.col_offset,
+ parent=parent)
+ param.postinit(default=default, annotation=nodes.Empty)
+ yield param
+
+ def _build_parameter(self, param_node, name, parent, default):
+ param = nodes.Parameter(name=name, lineno=getattr(param_node, 'lineno', None),
+ col_offset=getattr(param_node, 'col_offset', None),
+ parent=parent)
+ annotation = nodes.Empty
+ param_annotation = getattr(param_node, 'annotation', None)
+ if param_annotation:
+ annotation = self._visitor.visit(param_annotation, param)
+
+ param.postinit(default=default, annotation=annotation)
+ yield param
+
+
+
class TreeRebuilder(object):
"""Rebuilds the ast tree to become an Astroid tree"""
@@ -141,57 +189,64 @@ class TreeRebuilder(object):
def visit_arguments(self, node, parent):
"""visit a Arguments node by returning a fresh instance of it"""
- vararg, kwarg = node.vararg, node.kwarg
- if PY34:
- newnode = nodes.Arguments(vararg.arg if vararg else None,
- kwarg.arg if kwarg else None,
- parent)
- else:
- newnode = nodes.Arguments(vararg, kwarg, parent)
- args = [self.visit(child, newnode) for child in node.args]
- defaults = [self.visit(child, newnode)
- for child in node.defaults]
- varargannotation = None
- kwargannotation = None
- # change added in 82732 (7c5c678e4164), vararg and kwarg
- # are instances of `ast.arg`, not strings
- if vararg:
- if PY34:
- if node.vararg.annotation:
- varargannotation = self.visit(node.vararg.annotation,
- newnode)
- vararg = vararg.arg
- elif PY3 and node.varargannotation:
- varargannotation = self.visit(node.varargannotation,
- newnode)
- if kwarg:
- if PY34:
- if node.kwarg.annotation:
- kwargannotation = self.visit(node.kwarg.annotation,
- newnode)
- kwarg = kwarg.arg
- elif PY3:
- if node.kwargannotation:
- kwargannotation = self.visit(node.kwargannotation,
- newnode)
- if PY3:
- kwonlyargs = [self.visit(child, newnode) for child
- in node.kwonlyargs]
- kw_defaults = [self.visit(child, newnode) if child else
- None for child in node.kw_defaults]
- annotations = [self.visit(arg.annotation, newnode) if
- arg.annotation else None for arg in node.args]
- kwonly_annotations = [self.visit(arg.annotation, newnode)
- if arg.annotation else None
- for arg in node.kwonlyargs]
- else:
- kwonlyargs = []
- kw_defaults = []
- annotations = []
- kwonly_annotations = []
- newnode.postinit(args, defaults, kwonlyargs, kw_defaults,
- annotations, kwonly_annotations,
- varargannotation, kwargannotation)
+ def _build_variadic(field_name):
+ param = nodes.Empty
+ variadic = getattr(node, field_name)
+
+ if variadic:
+ # Various places to get the name from.
+ try:
+ param_name = variadic.id
+ except AttributeError:
+ try:
+ param_name = variadic.arg
+ except AttributeError:
+ param_name = variadic
+
+ param = nodes.Parameter(name=param_name,
+ lineno=newnode.lineno,
+ col_offset=newnode.col_offset,
+ parent=newnode)
+ # Get the annotation of the variadic node.
+ annotation = nodes.Empty
+ default = nodes.Empty
+ variadic_annotation = getattr(variadic, 'annotation', None)
+ if variadic_annotation is None:
+ # Support for Python 3.3.
+ variadic_annotation = getattr(node, field_name + 'annotation', None)
+ if variadic_annotation:
+ annotation = self.visit(variadic_annotation, param)
+
+ param.postinit(default=default, annotation=annotation)
+ return param
+
+ def _build_args(params, defaults):
+ # Pad the list of defaults so that each arguments gets a default.
+ defaults = collections.deque(defaults)
+ while len(defaults) != len(params):
+ defaults.appendleft(nodes.Empty)
+
+ param_visitor = ParameterVisitor(self)
+ for parameter in params:
+ default = defaults.popleft()
+ if default:
+ default = self.visit(default, newnode)
+
+ for param in param_visitor.visit(parameter, newnode, default):
+ yield param
+
+ newnode = nodes.Arguments(parent=parent)
+ # Build the arguments list.
+ positional_args = list(_build_args(node.args, node.defaults))
+ kwonlyargs = list(_build_args(getattr(node, 'kwonlyargs', ()),
+ getattr(node, 'kw_defaults', ())))
+ # Build vararg and kwarg.
+ vararg = _build_variadic('vararg')
+ kwarg = _build_variadic('kwarg')
+ # Prepare the arguments new node.
+ newnode.postinit(args=positional_args, vararg=vararg, kwarg=kwarg,
+ keyword_only=kwonlyargs,
+ positional_only=[])
return newnode
def visit_assert(self, node, parent):
@@ -729,11 +784,6 @@ class TreeRebuilder(object):
class TreeRebuilder3(TreeRebuilder):
"""extend and overwrite TreeRebuilder for python3k"""
- def visit_arg(self, node, parent):
- """visit a arg node by returning a fresh AssName instance"""
- # TODO(cpopa): introduce an Arg node instead of using AssignName.
- return self.visit_assignname(node, parent, node.arg)
-
def visit_nameconstant(self, node, parent):
# in Python 3.4 we have NameConstant for True / False / None
return nodes.NameConstant(node.value, getattr(node, 'lineno', None),
diff --git a/astroid/tree/scoped_nodes.py b/astroid/tree/scoped_nodes.py
index d04b549b..6744ec82 100644
--- a/astroid/tree/scoped_nodes.py
+++ b/astroid/tree/scoped_nodes.py
@@ -686,7 +686,7 @@ class CallSite(object):
pass
# Too many arguments given and no variable arguments.
- if len(self.positional_arguments) > len(self._funcnode.args.args):
+ if len(self.positional_arguments) > len(self._funcnode.args.positional_and_keyword):
if not self._funcnode.args.vararg:
raise exceptions.InferenceError('Too many positional arguments '
'passed to {func!r} that does '
@@ -694,10 +694,10 @@ class CallSite(object):
call_site=self, func=self._funcnode,
arg=name, context=context)
- positional = self.positional_arguments[:len(self._funcnode.args.args)]
- vararg = self.positional_arguments[len(self._funcnode.args.args):]
+ positional = self.positional_arguments[:len(self._funcnode.args.positional_and_keyword)]
+ vararg = self.positional_arguments[len(self._funcnode.args.positional_and_keyword):]
argindex = self._funcnode.args.find_argname(name)[0]
- kwonlyargs = set(arg.name for arg in self._funcnode.args.kwonlyargs)
+ kwonlyargs = set(arg.name for arg in self._funcnode.args.keyword_only)
kwargs = {
key: value for key, value in self.keyword_arguments.items()
if key not in kwonlyargs
@@ -707,8 +707,8 @@ class CallSite(object):
# if the missing positional arguments were passed
# as keyword arguments and if so, place them into the
# positional args list.
- if len(positional) < len(self._funcnode.args.args):
- for func_arg in self._funcnode.args.args:
+ if len(positional) < len(self._funcnode.args.positional_and_keyword):
+ for func_arg in self._funcnode.args.positional_and_keyword:
if func_arg.name in kwargs:
arg = kwargs.pop(func_arg.name)
positional.append(arg)
@@ -748,7 +748,7 @@ class CallSite(object):
except IndexError:
pass
- if self._funcnode.args.kwarg == name:
+ if self._funcnode.args.kwarg and self._funcnode.args.kwarg.name == name:
# It wants all the keywords that were passed into
# the call site.
if self.has_invalid_keywords():
@@ -769,7 +769,7 @@ class CallSite(object):
kwarg.postinit(keys, values)
return iter((kwarg, ))
- elif self._funcnode.args.vararg == name:
+ if self._funcnode.args.vararg and self._funcnode.args.vararg.name == name:
# It wants all the args that were passed into
# the call site.
if self.has_invalid_arguments():
@@ -813,7 +813,9 @@ class LambdaFunctionMixin(QualifiedNameMixin, base.FilterStmtsMixin):
return CallSite(self, args, keywords)
def scope_lookup(self, node, name, offset=0):
- if node in self.args.defaults or node in self.args.kw_defaults:
+
+ if node in itertools.chain((self.args.positional_and_keyword,
+ self.args.keyword_only)):
frame = self.parent.frame()
# line offset to avoid that def func(f=func) resolve the default
# value to the defined function
@@ -825,14 +827,16 @@ class LambdaFunctionMixin(QualifiedNameMixin, base.FilterStmtsMixin):
def argnames(self):
"""return a list of argument names"""
- if self.args.args: # maybe None with builtin functions
- names = _rec_get_names(self.args.args)
+ if self.args.positional_and_keyword: # maybe None with builtin functions
+ names = _rec_get_names(self.args.positional_and_keyword)
else:
names = []
if self.args.vararg:
- names.append(self.args.vararg)
+ names.append(self.args.vararg.name)
if self.args.kwarg:
- names.append(self.args.kwarg)
+ names.append(self.args.kwarg.name)
+ if self.args.keyword_only:
+ names.extend([arg.name for arg in self.keyword_only])
return names
def callable(self):
diff --git a/astroid/tree/treeabc.py b/astroid/tree/treeabc.py
index 6ad96ba8..5c008255 100644
--- a/astroid/tree/treeabc.py
+++ b/astroid/tree/treeabc.py
@@ -67,6 +67,10 @@ class Name(NodeNG):
"""Class representing a Name node"""
+class Parameter(NodeNG):
+ """Class representing a parameter node."""
+
+
class Arguments(NodeNG):
"""Class representing an Arguments node"""
@@ -339,3 +343,12 @@ class ReservedName(NodeNG):
class Unknown(NodeNG):
pass
+
+
+class Empty(NodeNG):
+ """Empty nodes represents the lack of something
+
+ For instance, they can be used to represent missing annotations
+ or defaults for arguments or anything where None is a valid
+ value.
+ """
diff --git a/doc/source/conf.py b/doc/source/conf.py
index 980fd31e..f4ceb2a8 100644
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -48,9 +48,9 @@ copyright = u'2013, Logilab S.A.'
# built documents.
#
# The short X.Y version.
-version = '1.3.4'
+from astroid.__pkginfo__ import version
# The full version, including alpha/beta/rc tags.
-release = '1.3.4'
+release = version
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -125,7 +125,7 @@ html_theme = 'default'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
-html_static_path = ['_static']
+html_static_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
diff --git a/doc/source/inference.rst b/doc/source/inference.rst
index bf67993f..7fed194f 100644
--- a/doc/source/inference.rst
+++ b/doc/source/inference.rst
@@ -81,7 +81,7 @@ of the :mod:`inference`.
.. todo:: actually annotate the doc to structure its approach
-.. automodule:: inference
+.. automodule:: astroid.inference
:members:
:undoc-members:
.. :special-members: in autodoc/sphinx 1.1
diff --git a/setup.py b/setup.py
index 2150d1c2..3a3cc621 100644
--- a/setup.py
+++ b/setup.py
@@ -64,8 +64,8 @@ def install():
include_package_data = True,
install_requires = install_requires,
packages = find_packages(),
- cmdclass={'install_lib': AstroidInstallLib,
- 'easy_install': AstroidEasyInstallLib}
+ cmdclass = {'install_lib': AstroidInstallLib,
+ 'easy_install': AstroidEasyInstallLib}
)
diff --git a/tox.ini b/tox.ini
index 9b328e9b..fa66a2d5 100644
--- a/tox.ini
+++ b/tox.ini
@@ -10,8 +10,8 @@ commands = coverage erase
[testenv:coverage-stats]
commands =
- coverage report --ignore-errors --include="astroid*"
- coverage html --ignore-errors --include="astroid*"
+ coverage report --ignore-errors
+ coverage html --ignore-errors
[testenv]
deps =
@@ -32,4 +32,4 @@ deps =
# Disable warnings because they overflow the Travis log on 3.5
setenv = PYTHONWARNINGS = i
# {posargs} allows passing command line arguments to unittest
-commands = coverage run --append --branch -m unittest discover {posargs} -s {envsitepackagesdir}/astroid/tests -p "unittest*.py"
+commands = coverage run --source astroid --append --branch -m unittest discover {posargs} -s {envsitepackagesdir}/astroid/tests -p "unittest*.py"