summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Cristau <julien.cristau@logilab.fr>2013-07-18 22:57:13 +0200
committerJulien Cristau <julien.cristau@logilab.fr>2013-07-18 22:57:13 +0200
commitba2393d46474b72bb04b50dce629a9fa2bd6c7c5 (patch)
tree499d0d7df051006e30b85fff4cc9eae87e0a0294
parent5b0746a34b39a9c8d0fb00a1277fd844666a247d (diff)
downloadastroid-git-ba2393d46474b72bb04b50dce629a9fa2bd6c7c5.tar.gz
Add support for py3k's keyword only arguments
PEP 3102
-rw-r--r--ChangeLog2
-rw-r--r--node_classes.py20
-rw-r--r--rebuilder.py10
-rw-r--r--scoped_nodes.py2
4 files changed, 31 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index d53599d5..fee4fe2b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -15,6 +15,8 @@ Change log for the astroid package (used to be astng)
* Added the test_utils module for building ASTs and
extracting deeply nested nodes for easier testing.
+ * Add support for py3k's keyword only arguments (PEP 3102)
+
* rename the project as astroid
2013-04-16 -- 0.24.3
diff --git a/node_classes.py b/node_classes.py
index 8c6ad8aa..97bd9079 100644
--- a/node_classes.py
+++ b/node_classes.py
@@ -253,9 +253,11 @@ class Name(LookupMixIn, NodeNG):
class Arguments(NodeNG, AssignTypeMixin):
"""class representing an Arguments node"""
- _astroid_fields = ('args', 'defaults')
+ _astroid_fields = ('args', 'defaults', 'kwonlyargs', 'kw_defaults')
args = None
defaults = None
+ kwonlyargs = None
+ kw_defaults = None
def __init__(self, vararg=None, kwarg=None):
self.vararg = vararg
@@ -275,6 +277,10 @@ class Arguments(NodeNG, AssignTypeMixin):
result.append('*%s' % self.vararg)
if self.kwarg:
result.append('**%s' % self.kwarg)
+ if self.kwonlyargs:
+ if not self.vararg:
+ result.append('*')
+ result.append(_format_args(self.kwonlyargs, self.kw_defaults))
return ', '.join(result)
def default_value(self, argname):
@@ -287,6 +293,9 @@ class Arguments(NodeNG, AssignTypeMixin):
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]
raise NoDefault()
def is_argument(self, name):
@@ -303,6 +312,12 @@ class Arguments(NodeNG, AssignTypeMixin):
return _find_arg(argname, self.args, rec)
return None, None
+ def get_children(self):
+ """override get_children to skip over None elements in kw_defaults"""
+ for child in super(Arguments, self).get_children():
+ if child is not None:
+ yield child
+
def _find_arg(argname, args, rec=False):
for i, arg in enumerate(args):
@@ -328,7 +343,8 @@ def _format_args(args, defaults=None):
else:
values.append(arg.name)
if defaults is not None and i >= default_offset:
- values[-1] += '=' + defaults[i-default_offset].as_string()
+ if defaults[i-default_offset] is not None:
+ values[-1] += '=' + defaults[i-default_offset].as_string()
return ', '.join(values)
diff --git a/rebuilder.py b/rebuilder.py
index e06adeaf..cf92da09 100644
--- a/rebuilder.py
+++ b/rebuilder.py
@@ -185,6 +185,8 @@ class TreeRebuilder(object):
newnode.args = [self.visit(child, newnode) for child in node.args]
self.asscontext = None
newnode.defaults = [self.visit(child, newnode) for child in node.defaults]
+ newnode.kwonlyargs = []
+ newnode.kw_defaults = []
newnode.vararg = node.vararg
newnode.kwarg = node.kwarg
# save argument names in locals:
@@ -836,6 +838,14 @@ class TreeRebuilder3k(TreeRebuilder):
# XXX or we should instead introduce a Arg node in astroid ?
return self.visit_assname(node, parent, node.arg)
+ def visit_arguments(self, node, parent):
+ newnode = super(TreeRebuilder3k, self).visit_arguments(node, parent)
+ self.asscontext = "Ass"
+ newnode.kwonlyargs = [self.visit(child, newnode) for child in node.kwonlyargs]
+ self.asscontext = None
+ newnode.kw_defaults = [self.visit(child, newnode) if child else None for child in node.kw_defaults]
+ return newnode
+
def visit_excepthandler(self, node, parent):
"""visit an ExceptHandler node by returning a fresh instance of it"""
newnode = new.ExceptHandler()
diff --git a/scoped_nodes.py b/scoped_nodes.py
index dabaf0c7..3886b7e1 100644
--- a/scoped_nodes.py
+++ b/scoped_nodes.py
@@ -506,7 +506,7 @@ class Lambda(LocalsDictNodeNG, FilterStmtsMixin):
return self.body.infer(context)
def scope_lookup(self, node, name, offset=0):
- if node in self.args.defaults:
+ if node in self.args.defaults or node in self.args.kw_defaults:
frame = self.parent.frame()
# line offset to avoid that def func(f=func) resolve the default
# value to the defined function