1
0
forked from VimPlug/jedi

Better wrapping of BoundMethod

This commit is contained in:
Dave Halter
2018-10-18 19:18:20 +02:00
parent dddd302980
commit 228440c03f
3 changed files with 28 additions and 32 deletions

View File

@@ -37,7 +37,7 @@ class LambdaName(AbstractNameDefinition):
return ContextSet([self._lambda_context]) return ContextSet([self._lambda_context])
class AbstractFunction(TreeContext): class FunctionMixin(object):
api_type = u'function' api_type = u'function'
def get_filters(self, search_global=False, until_position=None, origin_scope=None): def get_filters(self, search_global=False, until_position=None, origin_scope=None):
@@ -65,13 +65,16 @@ class AbstractFunction(TreeContext):
return ContextName(self, self.tree_node.name) return ContextName(self, self.tree_node.name)
def get_function_execution(self, arguments=None): def get_function_execution(self, arguments=None):
raise NotImplementedError if arguments is None:
arguments = AnonymousArguments()
return FunctionExecutionContext(self.evaluator, self.parent_context, self, arguments)
def py__name__(self): def py__name__(self):
return self.name.string_name return self.name.string_name
class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)): class FunctionContext(use_metaclass(CachedMetaClass, FunctionMixin, TreeContext)):
""" """
Needed because of decorators. Decorators are evaluated here. Needed because of decorators. Decorators are evaluated here.
""" """
@@ -116,12 +119,6 @@ class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)):
return NO_CONTEXTS return NO_CONTEXTS
return function_execution.infer() return function_execution.infer()
def get_function_execution(self, arguments=None):
if arguments is None:
arguments = AnonymousArguments()
return FunctionExecutionContext(self.evaluator, self.parent_context, self, arguments)
def py__class__(self): def py__class__(self):
return compiled.get_special_object(self.evaluator, u'FUNCTION_CLASS') return compiled.get_special_object(self.evaluator, u'FUNCTION_CLASS')
@@ -135,10 +132,10 @@ class FunctionContext(use_metaclass(CachedMetaClass, AbstractFunction)):
class MethodContext(FunctionContext): class MethodContext(FunctionContext):
def __init__(self, evaluator, class_context, *args, **kwargs): def __init__(self, evaluator, class_context, *args, **kwargs):
super(MethodContext, self).__init__(evaluator, *args, **kwargs) super(MethodContext, self).__init__(evaluator, *args, **kwargs)
self.class_context = class_context self._class_context = class_context
def get_default_param_context(self): def get_default_param_context(self):
return self.class_context return self._class_context
class FunctionExecutionContext(TreeContext): class FunctionExecutionContext(TreeContext):

View File

@@ -5,13 +5,13 @@ from jedi import settings
from jedi.evaluate import compiled from jedi.evaluate import compiled
from jedi.evaluate import filters from jedi.evaluate import filters
from jedi.evaluate.base_context import Context, NO_CONTEXTS, ContextSet, \ from jedi.evaluate.base_context import Context, NO_CONTEXTS, ContextSet, \
iterator_to_context_set iterator_to_context_set, ContextWrapper
from jedi.evaluate.lazy_context import LazyKnownContext, LazyKnownContexts from jedi.evaluate.lazy_context import LazyKnownContext, LazyKnownContexts
from jedi.evaluate.cache import evaluator_method_cache from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.arguments import AbstractArguments, AnonymousArguments, \ from jedi.evaluate.arguments import AbstractArguments, AnonymousArguments, \
ValuesArguments, TreeArgumentsWrapper ValuesArguments, TreeArgumentsWrapper
from jedi.evaluate.context.function import FunctionExecutionContext, \ from jedi.evaluate.context.function import FunctionExecutionContext, \
FunctionContext, AbstractFunction, OverloadedFunctionContext FunctionContext, FunctionMixin, OverloadedFunctionContext
from jedi.evaluate.context.klass import ClassContext, apply_py__get__, \ from jedi.evaluate.context.klass import ClassContext, apply_py__get__, \
py__mro__, ClassFilter py__mro__, ClassFilter
from jedi.evaluate.context import iterable from jedi.evaluate.context import iterable
@@ -355,16 +355,11 @@ class CompiledInstanceClassFilter(filters.AbstractFilter):
] ]
class BoundMethod(AbstractFunction): class BoundMethod(FunctionMixin, ContextWrapper):
def __init__(self, instance, klass, function): def __init__(self, instance, klass, function):
super(BoundMethod, self).__init__( super(BoundMethod, self).__init__(function)
function.evaluator,
function.parent_context,
function.tree_node,
)
self.instance = instance self.instance = instance
self.class_context = klass self.class_context = klass
self._function = function
def py__class__(self): def py__class__(self):
return compiled.get_special_object(self.evaluator, u'BOUND_METHOD_CLASS') return compiled.get_special_object(self.evaluator, u'BOUND_METHOD_CLASS')
@@ -378,33 +373,30 @@ class BoundMethod(AbstractFunction):
def get_function_execution(self, arguments=None): def get_function_execution(self, arguments=None):
arguments = self._get_arguments(arguments) arguments = self._get_arguments(arguments)
if isinstance(self._function, compiled.CompiledObject): if isinstance(self._wrapped_context, compiled.CompiledObject):
# This is kind of weird, because it's coming from a compiled object # This is kind of weird, because it's coming from a compiled object
# and we're not sure if we want that in the future. # and we're not sure if we want that in the future.
return FunctionExecutionContext( return FunctionExecutionContext(
self.evaluator, self.parent_context, self, arguments self.evaluator, self.parent_context, self, arguments
) )
return self._function.get_function_execution(arguments) return super(BoundMethod, self).get_function_execution(arguments)
def get_default_param_context(self):
return self.class_context
def py__call__(self, arguments): def py__call__(self, arguments):
if isinstance(self._function, OverloadedFunctionContext): if isinstance(self._wrapped_context, OverloadedFunctionContext):
return self._function.py__call__(self._get_arguments(arguments)) return self._wrapped_context.py__call__(self._get_arguments(arguments))
function_execution = self.get_function_execution(arguments) function_execution = self.get_function_execution(arguments)
return function_execution.infer() return function_execution.infer()
def get_matching_functions(self, arguments): def get_matching_functions(self, arguments):
for func in self._function.get_matching_functions(arguments): for func in self._wrapped_context.get_matching_functions(arguments):
if func is self: if func is self:
yield self yield self
else: else:
yield BoundMethod(self.instance, self.class_context, func) yield BoundMethod(self.instance, self.class_context, func)
def __repr__(self): def __repr__(self):
return '<%s: %s>' % (self.__class__.__name__, self._function) return '<%s: %s>' % (self.__class__.__name__, self._wrapped_context)
class CompiledBoundMethod(compiled.CompiledObject): class CompiledBoundMethod(compiled.CompiledObject):

View File

@@ -185,8 +185,15 @@ class NameFinder(object):
if not contexts and isinstance(self._name, tree.Name) and \ if not contexts and isinstance(self._name, tree.Name) and \
not self._name_context.is_instance(): not self._name_context.is_instance():
flow_scope = self._name flow_scope = self._name
base_node = self._name_context.tree_node base_nodes = [self._name_context.tree_node]
if base_node.type == 'comp_for': try:
stub_node = self._name_context.stub_context.tree_node
except AttributeError:
pass
else:
base_nodes.append(stub_node)
if any(b.type == 'comp_for' for b in base_nodes):
return contexts return contexts
while True: while True:
flow_scope = get_parent_scope(flow_scope, include_flows=True) flow_scope = get_parent_scope(flow_scope, include_flows=True)
@@ -194,7 +201,7 @@ class NameFinder(object):
self._name, self._position) self._name, self._position)
if n is not None: if n is not None:
return n return n
if flow_scope == base_node: if flow_scope in base_nodes:
break break
return contexts return contexts