diff --git a/jedi/evaluate/filters.py b/jedi/evaluate/filters.py index 37d0dd78..552bfe37 100644 --- a/jedi/evaluate/filters.py +++ b/jedi/evaluate/filters.py @@ -36,17 +36,17 @@ class AbstractNameDefinition(object): class ContextName(AbstractNameDefinition): - def __init__(self, parent_context, name): + def __init__(self, parent_context, tree_name): self.parent_context = parent_context - self.name = name + self.tree_name = tree_name @property def string_name(self): - return self.name.value + return self.tree_name.value @property def start_pos(self): - return self.name.start_pos + return self.tree_name.start_pos def infer(self): return [self.parent_context] @@ -59,20 +59,20 @@ class TreeNameDefinition(ContextName): def infer(self): # Refactor this, should probably be here. from jedi.evaluate.finder import _name_to_types - return _name_to_types(self.parent_context.evaluator, self.parent_context, self.name, None) + return _name_to_types(self.parent_context.evaluator, self.parent_context, self.tree_name, None) class ParamName(ContextName): - def __init__(self, parent_context, name): + def __init__(self, parent_context, tree_name): self.parent_context = parent_context - self.name = name + self.tree_name = tree_name def infer(self): return self._get_param().infer() def _get_param(self): params = self.parent_context.get_params() - return params[self.name.parent.position_nr] + return params[self.tree_name.parent.position_nr] class AbstractFilter(object): diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 86b972da..7c886d76 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -325,7 +325,7 @@ class NameFinder(object): # The name must not be in the dictionary, but part of the class # definition. __get__ is only called if the descriptor is defined in # the class dictionary. - name_scope = name.get_definition().get_parent_scope() + name_scope = name.tree_name.get_definition().get_parent_scope() if not isinstance(name_scope, (er.Instance, tree.Class)): return types diff --git a/jedi/evaluate/instance.py b/jedi/evaluate/instance.py index 097de2b0..ff0b253a 100644 --- a/jedi/evaluate/instance.py +++ b/jedi/evaluate/instance.py @@ -4,7 +4,7 @@ from jedi.common import unite, to_list from jedi import debug from jedi.evaluate import compiled from jedi.evaluate.filters import ParserTreeFilter, ContextName, TreeNameDefinition -from jedi.evaluate.context import Context +from jedi.evaluate.context import Context, LazyKnownContext from jedi.evaluate.cache import memoize_default from jedi.evaluate import representation as er @@ -17,7 +17,7 @@ class AbstractInstanceContext(Context): super(AbstractInstanceContext, self).__init__(evaluator, parent_context) # Generated instances are classes that are just generated by self # (No var_args) used. - self._class_context = class_context + self.class_context = class_context self.var_args = var_args ##### @@ -69,33 +69,37 @@ class AbstractInstanceContext(Context): return names return [] - def execute_function_slot(self, name, *args): - raise NotImplementedError - method = self.get_subscope_by_name(name) - return self.evaluator.execute_evaluated(method, *args) + def execute_function_slots(self, names, *evaluated_args): + return unite( + self.evaluator.execute_evaluated(method, *evaluated_args) + for name in names + for method in name.infer() + ) def get_descriptor_returns(self, obj): """ Throws a KeyError if there's no method. """ - raise NotImplementedError # Arguments in __get__ descriptors are obj, class. # `method` is the new parent of the array, don't know if that's good. - none_obj = compiled.create(self.evaluator, None) - args = [obj, obj.base] if isinstance(obj, Instance) else [none_obj, obj] - try: - return self.execute_subscope_by_name('__get__', *args) - except KeyError: + names = self._get_function_slot_names('__get__') + if names: + if isinstance(obj, AbstractInstanceContext): + return self.execute_function_slots(names, obj, obj.class_context) + else: + none_obj = compiled.create(self.evaluator, None) + return self.execute_function_slots(names, none_obj, obj) + else: return set([self]) def get_filters(self, search_global=None, until_position=None, origin_scope=None, include_self_names=True): if include_self_names: - for cls in self._class_context.py__mro__(): + for cls in self.class_context.py__mro__(): if isinstance(cls, compiled.CompiledObject): yield SelfNameFilter(self.evaluator, self, cls, origin_scope) else: yield SelfNameFilter(self.evaluator, self, cls, origin_scope) - for cls in self._class_context.py__mro__(): + for cls in self.class_context.py__mro__(): if isinstance(cls, compiled.CompiledObject): yield CompiledInstanceClassFilter(self.evaluator, self, cls) else: @@ -136,20 +140,20 @@ class AbstractInstanceContext(Context): pass def __repr__(self): - return "<%s of %s(%s)>" % (type(self).__name__, self._class_context, + return "<%s of %s(%s)>" % (type(self).__name__, self.class_context, self.var_args) class CompiledInstance(AbstractInstanceContext): @property def name(self): - return compiled.CompiledContextName(self, self._class_context.name.string_name) + return compiled.CompiledContextName(self, self.class_context.name.string_name) class TreeInstance(AbstractInstanceContext): @property def name(self): - return ContextName(self, self._class_context.name) + return ContextName(self, self.class_context.name.tree_name) @memoize_default() def create_instance_context(self, class_context, node): @@ -282,14 +286,14 @@ class LazyInstanceName(TreeNameDefinition): """ This name calculates the parent_context lazily. """ - def __init__(self, instance, class_context, name): + def __init__(self, instance, class_context, tree_name): self._instance = instance self._class_context = class_context - self.name = name + self.tree_name = tree_name @property def parent_context(self): - return self._instance.create_instance_context(self._class_context, self.name) + return self._instance.create_instance_context(self._class_context, self.tree_name) def infer(self): values = super(LazyInstanceName, self).infer() @@ -306,10 +310,13 @@ class InstanceVarArgs(object): self._var_args = var_args def unpack(self, func=None): - yield None, self._instance + yield None, LazyKnownContext(self._instance) for values in self._var_args.unpack(func): yield values + def get_calling_var_args(self): + return self._var_args.get_calling_var_args() + class InstanceFunctionExecution(er.FunctionExecutionContext): def __init__(self, instance, parent_context, funcdef, var_args): diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index d2e7a397..b53d94eb 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -405,12 +405,6 @@ class Wrapper(tree.Base): """ return True - @property - @underscore_memoization - def name(self): - name = self.base.name - return ContextName(self, name) - class ClassContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper)): """ @@ -515,6 +509,10 @@ class ClassContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper)) def __repr__(self): return "<%s of %s>" % (type(self).__name__, self.classdef) + @property + def name(self): + return ContextName(self, self.classdef.name) + class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrapper)): """ @@ -558,7 +556,7 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrappe self.base, params ) - return self.execute_function_(function_execution) + return self.infer_function_execution(function_execution) def py__class__(self): # This differentiation is only necessary for Python2. Python3 does not @@ -572,6 +570,10 @@ class FunctionContext(use_metaclass(CachedMetaClass, context.TreeContext, Wrappe def __repr__(self): return "<%s of %s>" % (type(self).__name__, self.base_func) + @property + def name(self): + return ContextName(self, self.funcdef.name) + class LambdaWrapper(FunctionContext): def get_decorated_func(self):