diff --git a/jedi/evaluate/docstrings.py b/jedi/evaluate/docstrings.py index 106a7879..7ebd963a 100644 --- a/jedi/evaluate/docstrings.py +++ b/jedi/evaluate/docstrings.py @@ -192,6 +192,9 @@ def follow_param(module_context, param): for p in _evaluate_for_statement_string(module_context, param_str)] ) func = param.get_parent_function() + if func.type == 'lambda': + return set() + types = eval_docstring(func.raw_doc) if func.name.value == '__init__': cls = search_ancestor(func, 'classdef') diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index 6ec63ccb..65fa77c6 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -221,6 +221,20 @@ class ClassContext(use_metaclass(CachedMetaClass, context.TreeContext)): return ContextName(self, self.tree_node.name) +class LambdaName(AbstractNameDefinition): + string_name = '' + + def __init__(self, lambda_context): + self._lambda_context = lambda_context + self.parent_context = lambda_context.parent_context + + def start_pos(self): + return self._lambda_context.tree_node.start_pos + + def infer(self): + return set([self._lambda_context]) + + class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext)): """ Needed because of decorators. Decorators are evaluated here. @@ -276,6 +290,8 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext)): @property def name(self): + if self.tree_node.type == 'lambda': + return LambdaName(self) return ContextName(self, self.tree_node.name) def get_param_names(self): diff --git a/jedi/parser/python/tree.py b/jedi/parser/python/tree.py index 139c0e85..56706324 100644 --- a/jedi/parser/python/tree.py +++ b/jedi/parser/python/tree.py @@ -609,7 +609,8 @@ class Function(ClassOrFunc): :rtype: str """ - func_name = func_name or self.name + # Lambdas have no name. + func_name = func_name or getattr(self, 'name', '') code = unicode(func_name) + self._get_paramlist_code() return '\n'.join(textwrap.wrap(code, width)) @@ -639,13 +640,12 @@ class Lambda(Function): def __init__(self, children): # We don't want to call the Function constructor, call its parent. super(Function, self).__init__(children) - lst = self.children[1:-2] # Everything between `lambda` and the `:` operator is a parameter. - self.children[1:-2] = _create_params(self, lst) + # Everything between `lambda` and the `:` operator is a parameter. + self.children[1:-2] = _create_params(self, self.children[1:-2]) @property def name(self): - # Borrow the position of the AST node. - return Name('', self.children[0].start_pos) + raise AttributeError("lambda is not named.") def _get_paramlist_code(self): return '(' + ''.join(param.get_code() for param in self.params).strip() + ')' @@ -664,6 +664,7 @@ class Lambda(Function): @property def yields(self): + # TODO rename return [] def __repr__(self): diff --git a/test/test_parser/test_parser_tree.py b/test/test_parser/test_parser_tree.py index ef38f38b..34421b5f 100644 --- a/test/test_parser/test_parser_tree.py +++ b/test/test_parser/test_parser_tree.py @@ -36,8 +36,9 @@ class TestsFunctionAndLambdaParsing(object): return request.keywords['expected'] def test_name(self, node, expected): - assert isinstance(node.name, tree.Name) - assert unicode(node.name) == u(expected['name']) + if node.type != 'lambda': + assert isinstance(node.name, tree.Name) + assert unicode(node.name) == u(expected['name']) def test_params(self, node, expected): assert isinstance(node.params, list)