summaryrefslogtreecommitdiff
path: root/astroid/tree/scoped_nodes.py
diff options
context:
space:
mode:
authorClaudiu Popa <pcmanticore@gmail.com>2016-01-03 17:13:30 +0200
committerClaudiu Popa <pcmanticore@gmail.com>2016-01-03 17:14:16 +0200
commit95f8a878bd496af39b700de2748fc315289a11cc (patch)
tree876052504ea7019f92c88f205987e28776ea5632 /astroid/tree/scoped_nodes.py
parent3ed16dc880ade848ec987c4b5b0fef87cf980b4d (diff)
downloadastroid-git-95f8a878bd496af39b700de2748fc315289a11cc.tar.gz
Lambda is no longer at the top of the FunctionDef.
This means that checks such as ``isinstance(node, Lambda)`` will not hold true anymore for Functions. Closes #291
Diffstat (limited to 'astroid/tree/scoped_nodes.py')
-rw-r--r--astroid/tree/scoped_nodes.py110
1 files changed, 59 insertions, 51 deletions
diff --git a/astroid/tree/scoped_nodes.py b/astroid/tree/scoped_nodes.py
index 86e09e92..6e53dc33 100644
--- a/astroid/tree/scoped_nodes.py
+++ b/astroid/tree/scoped_nodes.py
@@ -794,8 +794,53 @@ class CallSite(object):
func=self._funcnode, arg=name, context=context)
+class LambdaFunctionMixin(QualifiedNameMixin, base.FilterStmtsMixin):
+ """Common code for lambda and functions."""
+
+ def called_with(self, args, keywords):
+ """Get a CallSite object with the given arguments
+
+ Given these arguments, this will return an object
+ which considers them as being passed into the current function,
+ which can then be used to infer their values.
+ `args` needs to be a list of arguments, while `keywords`
+ needs to be a list of tuples, where each tuple is formed
+ by a keyword name and a keyword value.
+ """
+ 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:
+ frame = self.parent.frame()
+ # line offset to avoid that def func(f=func) resolve the default
+ # value to the defined function
+ offset = -1
+ else:
+ # check this is not used in function decorators
+ frame = self
+ return frame._scope_lookup(node, name, offset)
+
+ 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)
+ else:
+ names = []
+ if self.args.vararg:
+ names.append(self.args.vararg)
+ if self.args.kwarg:
+ names.append(self.args.kwarg)
+ return names
+
+ def callable(self):
+ return True
+
+ def bool_value(self):
+ return True
+
+
@util.register_implementation(treeabc.Lambda)
-class Lambda(QualifiedNameMixin, base.FilterStmtsMixin, lookup.LocalsDictNode):
+class Lambda(LambdaFunctionMixin, lookup.LocalsDictNode):
_astroid_fields = ('args', 'body',)
_other_other_fields = ('locals',)
name = '<lambda>'
@@ -818,63 +863,19 @@ class Lambda(QualifiedNameMixin, base.FilterStmtsMixin, lookup.LocalsDictNode):
# return MappingProxyType(get_external_assignments(self, collections.defaultdict(list)))
def pytype(self):
- if 'method' in self.type:
- return '%s.instancemethod' % BUILTINS
return '%s.function' % BUILTINS
def display_type(self):
- if 'method' in self.type:
- return 'Method'
return 'Function'
- def callable(self):
- return True
-
- 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)
- else:
- names = []
- if self.args.vararg:
- names.append(self.args.vararg)
- if self.args.kwarg:
- names.append(self.args.kwarg)
- return names
-
def infer_call_result(self, caller, context=None):
"""infer what a function is returning when called"""
return self.body.infer(context)
- def scope_lookup(self, node, name, offset=0):
- 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
- offset = -1
- else:
- # check this is not used in function decorators
- frame = self
- return frame._scope_lookup(node, name, offset)
-
- def bool_value(self):
- return True
-
- def called_with(self, args, keywords):
- """Get a CallSite object with the given arguments
-
- Given these arguments, this will return an object
- which considers them as being passed into the current function,
- which can then be used to infer their values.
- `args` needs to be a list of arguments, while `keywords`
- needs to be a list of tuples, where each tuple is formed
- by a keyword name and a keyword value.
- """
- return CallSite(self, args, keywords)
-
@util.register_implementation(treeabc.FunctionDef)
-class FunctionDef(node_classes.Statement, Lambda):
+class FunctionDef(LambdaFunctionMixin, lookup.LocalsDictNode,
+ node_classes.Statement):
'''Setting FunctionDef.args to Unknown, rather than an Arguments node,
means that the corresponding function's arguments are unknown,
probably because it represents a function implemented in C or that
@@ -904,7 +905,7 @@ class FunctionDef(node_classes.Statement, Lambda):
col_offset=None, parent=None):
self.name = name
self.doc = doc
- self.instance_attrs = {}
+ self.instance_attrs = collections.defaultdict(list)
super(FunctionDef, self).__init__(lineno, col_offset, parent)
# pylint: disable=arguments-differ; different than Lambdas
@@ -914,6 +915,16 @@ class FunctionDef(node_classes.Statement, Lambda):
self.decorators = decorators
self.returns = returns
+ def pytype(self):
+ if 'method' in self.type:
+ return '%s.instancemethod' % BUILTINS
+ return '%s.function' % BUILTINS
+
+ def display_type(self):
+ if 'method' in self.type:
+ return 'Method'
+ return 'Function'
+
@decorators_mod.cachedproperty
def extra_decorators(self):
"""Get the extra decorators that this function can haves
@@ -1148,9 +1159,6 @@ class FunctionDef(node_classes.Statement, Lambda):
except exceptions.InferenceError:
yield util.Uninferable
- def bool_value(self):
- return True
-
@util.register_implementation(treeabc.AsyncFunctionDef)
class AsyncFunctionDef(FunctionDef):