forked from VimPlug/jedi
Refactor py__get__ support pretty heavily
This commit is contained in:
@@ -53,6 +53,13 @@ class FunctionMixin(object):
|
|||||||
for filter in scope.get_filters(search_global=False, origin_scope=origin_scope):
|
for filter in scope.get_filters(search_global=False, origin_scope=origin_scope):
|
||||||
yield filter
|
yield filter
|
||||||
|
|
||||||
|
def py__get__(self, instance, class_context):
|
||||||
|
from jedi.evaluate.context.instance import BoundMethod
|
||||||
|
if instance is None:
|
||||||
|
# Calling the Foo.bar results in the original bar function.
|
||||||
|
return ContextSet([self])
|
||||||
|
return ContextSet([BoundMethod(instance, class_context, self)])
|
||||||
|
|
||||||
def get_param_names(self):
|
def get_param_names(self):
|
||||||
function_execution = self.get_function_execution()
|
function_execution = self.get_function_execution()
|
||||||
return [ParamName(function_execution, param.name)
|
return [ParamName(function_execution, param.name)
|
||||||
@@ -335,7 +342,7 @@ class FunctionExecutionContext(TreeContext):
|
|||||||
return self.get_return_values()
|
return self.get_return_values()
|
||||||
|
|
||||||
|
|
||||||
class OverloadedFunctionContext(ContextWrapper):
|
class OverloadedFunctionContext(FunctionMixin, ContextWrapper):
|
||||||
def __init__(self, function, overloaded_functions):
|
def __init__(self, function, overloaded_functions):
|
||||||
super(OverloadedFunctionContext, self).__init__(function)
|
super(OverloadedFunctionContext, self).__init__(function)
|
||||||
self.overloaded_functions = overloaded_functions
|
self.overloaded_functions = overloaded_functions
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ from jedi.evaluate.base_context import Context, NO_CONTEXTS, ContextSet, \
|
|||||||
iterator_to_context_set, ContextWrapper
|
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 AnonymousArguments, \
|
||||||
ValuesArguments, TreeArgumentsWrapper
|
ValuesArguments, TreeArgumentsWrapper
|
||||||
from jedi.evaluate.context.function import FunctionExecutionContext, \
|
from jedi.evaluate.context.function import FunctionExecutionContext, \
|
||||||
FunctionContext, FunctionMixin, OverloadedFunctionContext, MethodContext
|
FunctionContext, FunctionMixin, OverloadedFunctionContext, MethodContext
|
||||||
@@ -109,16 +109,17 @@ class AbstractInstanceContext(Context):
|
|||||||
for name in names
|
for name in names
|
||||||
)
|
)
|
||||||
|
|
||||||
def py__get__(self, obj):
|
def py__get__(self, obj, class_context):
|
||||||
|
"""
|
||||||
|
obj may be None.
|
||||||
|
"""
|
||||||
# Arguments in __get__ descriptors are obj, class.
|
# Arguments in __get__ descriptors are obj, class.
|
||||||
# `method` is the new parent of the array, don't know if that's good.
|
# `method` is the new parent of the array, don't know if that's good.
|
||||||
names = self.get_function_slot_names(u'__get__')
|
names = self.get_function_slot_names(u'__get__')
|
||||||
if names:
|
if names:
|
||||||
if obj.is_instance():
|
if obj is None:
|
||||||
return self.execute_function_slots(names, obj, obj.class_context)
|
obj = compiled.builtin_from_name(self.evaluator, u'None')
|
||||||
else:
|
return self.execute_function_slots(names, obj, class_context)
|
||||||
none_obj = compiled.builtin_from_name(self.evaluator, u'None')
|
|
||||||
return self.execute_function_slots(names, none_obj, obj)
|
|
||||||
else:
|
else:
|
||||||
return ContextSet([self])
|
return ContextSet([self])
|
||||||
|
|
||||||
@@ -273,8 +274,10 @@ class TreeInstance(AbstractInstanceContext):
|
|||||||
# Just take the first result, it should always be one, because we
|
# Just take the first result, it should always be one, because we
|
||||||
# control the typeshed code.
|
# control the typeshed code.
|
||||||
c = self.class_context
|
c = self.class_context
|
||||||
if isinstance(func, MethodContext):
|
try:
|
||||||
c = func.class_context
|
c = func.class_context
|
||||||
|
except AttributeError:
|
||||||
|
pass
|
||||||
bound = BoundMethod(self, c, func)
|
bound = BoundMethod(self, c, func)
|
||||||
execution = bound.get_function_execution(self.var_args)
|
execution = bound.get_function_execution(self.var_args)
|
||||||
if not execution.matches_signature():
|
if not execution.matches_signature():
|
||||||
@@ -442,14 +445,8 @@ class LazyInstanceClassName(object):
|
|||||||
@iterator_to_context_set
|
@iterator_to_context_set
|
||||||
def infer(self):
|
def infer(self):
|
||||||
for result_context in self._class_member_name.infer():
|
for result_context in self._class_member_name.infer():
|
||||||
if isinstance(result_context, (FunctionContext, OverloadedFunctionContext)):
|
for c in apply_py__get__(result_context, self._instance, self.class_context):
|
||||||
# Classes are never used to resolve anything within the
|
yield c
|
||||||
# functions. Only other functions and modules will resolve
|
|
||||||
# those things.
|
|
||||||
yield BoundMethod(self._instance, self.class_context, result_context)
|
|
||||||
else:
|
|
||||||
for c in apply_py__get__(result_context, self._instance):
|
|
||||||
yield c
|
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
return getattr(self._class_member_name, name)
|
return getattr(self._class_member_name, name)
|
||||||
|
|||||||
@@ -50,13 +50,13 @@ from jedi.evaluate.base_context import ContextSet, iterator_to_context_set, \
|
|||||||
TreeContext, NO_CONTEXTS
|
TreeContext, NO_CONTEXTS
|
||||||
|
|
||||||
|
|
||||||
def apply_py__get__(context, base_context):
|
def apply_py__get__(context, instance, class_context):
|
||||||
try:
|
try:
|
||||||
method = context.py__get__
|
method = context.py__get__
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
yield context
|
yield context
|
||||||
else:
|
else:
|
||||||
for descriptor_context in method(base_context):
|
for descriptor_context in method(instance, class_context):
|
||||||
yield descriptor_context
|
yield descriptor_context
|
||||||
|
|
||||||
|
|
||||||
@@ -122,7 +122,9 @@ class ClassName(TreeNameDefinition):
|
|||||||
|
|
||||||
for result_context in inferred:
|
for result_context in inferred:
|
||||||
if self._apply_decorators:
|
if self._apply_decorators:
|
||||||
for c in apply_py__get__(result_context, self.parent_context):
|
for c in apply_py__get__(result_context,
|
||||||
|
instance=None,
|
||||||
|
class_context=self.parent_context):
|
||||||
yield c
|
yield c
|
||||||
else:
|
else:
|
||||||
yield result_context
|
yield result_context
|
||||||
|
|||||||
@@ -404,7 +404,7 @@ def import_module(evaluator, import_names, parent_module_context, sys_path):
|
|||||||
import_names=import_names,
|
import_names=import_names,
|
||||||
sys_path=sys_path,
|
sys_path=sys_path,
|
||||||
)
|
)
|
||||||
return ContextSet(module)
|
return ContextSet([module])
|
||||||
|
|
||||||
module_name = '.'.join(import_names)
|
module_name = '.'.join(import_names)
|
||||||
if parent_module_context is None:
|
if parent_module_context is None:
|
||||||
|
|||||||
@@ -284,8 +284,7 @@ class StaticMethodObject(AbstractObjectOverwrite, ContextWrapper):
|
|||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self._wrapped_context
|
return self._wrapped_context
|
||||||
|
|
||||||
@publish_method('__get__')
|
def py__get__(self, instance, klass):
|
||||||
def _py__get__(self):
|
|
||||||
return ContextSet([self._wrapped_context])
|
return ContextSet([self._wrapped_context])
|
||||||
|
|
||||||
|
|
||||||
@@ -302,12 +301,11 @@ class ClassMethodObject(AbstractObjectOverwrite, ContextWrapper):
|
|||||||
def get_object(self):
|
def get_object(self):
|
||||||
return self._wrapped_context
|
return self._wrapped_context
|
||||||
|
|
||||||
def py__get__(self, obj):
|
def py__get__(self, obj, class_context):
|
||||||
actual, = self._wrapped_context.py__getattribute__('__get__')
|
return ContextSet([
|
||||||
klass = obj
|
ClassMethodGet(__get__, class_context, self._function)
|
||||||
if not obj.is_class():
|
for __get__ in self._wrapped_context.py__getattribute__('__get__')
|
||||||
klass = obj.py__class__()
|
])
|
||||||
return ContextSet([ClassMethodGet(actual, klass, self._function)])
|
|
||||||
|
|
||||||
|
|
||||||
class ClassMethodGet(AbstractObjectOverwrite, ContextWrapper):
|
class ClassMethodGet(AbstractObjectOverwrite, ContextWrapper):
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
|
|
||||||
from jedi.plugins import typeshed
|
from jedi.plugins import typeshed
|
||||||
from jedi.evaluate.context import TreeInstance, BoundMethod, \
|
from jedi.evaluate.context import TreeInstance, BoundMethod
|
||||||
ClassContext
|
|
||||||
from parso.utils import PythonVersionInfo
|
from parso.utils import PythonVersionInfo
|
||||||
from jedi.evaluate.filters import TreeNameDefinition
|
from jedi.evaluate.filters import TreeNameDefinition
|
||||||
|
|
||||||
@@ -48,7 +47,7 @@ def test_function(Script):
|
|||||||
def_, = Script(code + '()').goto_definitions()
|
def_, = Script(code + '()').goto_definitions()
|
||||||
context = def_._name._context
|
context = def_._name._context
|
||||||
assert isinstance(context, TreeInstance)
|
assert isinstance(context, TreeInstance)
|
||||||
assert isinstance(context.class_context, ClassContext), context
|
assert isinstance(context.class_context, typeshed.StubOnlyClass), context
|
||||||
|
|
||||||
def_, = Script('import threading; threading.Thread').goto_definitions()
|
def_, = Script('import threading; threading.Thread').goto_definitions()
|
||||||
assert isinstance(def_._name._context, typeshed.StubClassContext), def_
|
assert isinstance(def_._name._context, typeshed.StubClassContext), def_
|
||||||
@@ -86,7 +85,7 @@ def test_method(Script):
|
|||||||
def_, = Script(code).goto_definitions()
|
def_, = Script(code).goto_definitions()
|
||||||
context = def_._name._context
|
context = def_._name._context
|
||||||
assert isinstance(context, BoundMethod), context
|
assert isinstance(context, BoundMethod), context
|
||||||
assert isinstance(context._function, typeshed.StubFunctionContext), context
|
assert isinstance(context._wrapped_context, typeshed.StubFunctionContext), context
|
||||||
|
|
||||||
def_, = Script(code + '()').goto_definitions()
|
def_, = Script(code + '()').goto_definitions()
|
||||||
context = def_._name._context
|
context = def_._name._context
|
||||||
|
|||||||
@@ -3,8 +3,7 @@ import pytest
|
|||||||
from jedi import settings
|
from jedi import settings
|
||||||
from jedi.evaluate.filters import ContextName
|
from jedi.evaluate.filters import ContextName
|
||||||
from jedi.evaluate.compiled import CompiledContextName
|
from jedi.evaluate.compiled import CompiledContextName
|
||||||
from jedi.plugins.typeshed import StubContextWithCompiled
|
from jedi.plugins.typeshed import StubOnlyModuleContext
|
||||||
from jedi.evaluate.context import FunctionContext
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
@pytest.fixture()
|
||||||
@@ -16,8 +15,7 @@ def test_base_auto_import_modules(auto_import_json, Script):
|
|||||||
loads, = Script('import json; json.loads').goto_definitions()
|
loads, = Script('import json; json.loads').goto_definitions()
|
||||||
assert isinstance(loads._name, ContextName)
|
assert isinstance(loads._name, ContextName)
|
||||||
context, = loads._name.infer()
|
context, = loads._name.infer()
|
||||||
assert isinstance(context, StubContextWithCompiled)
|
assert isinstance(context.parent_context, StubOnlyModuleContext)
|
||||||
assert isinstance(context._wrapped_context, FunctionContext)
|
|
||||||
|
|
||||||
|
|
||||||
def test_auto_import_modules_imports(auto_import_json, Script):
|
def test_auto_import_modules_imports(auto_import_json, Script):
|
||||||
|
|||||||
Reference in New Issue
Block a user