1
0
forked from VimPlug/jedi

Start using ContextWrapper for annotated classes

This commit is contained in:
Dave Halter
2018-10-09 09:58:07 +02:00
parent b14b3d1012
commit 8dca2b81e4
8 changed files with 126 additions and 124 deletions

View File

@@ -316,28 +316,20 @@ class FunctionExecutionContext(TreeContext):
.py__getattribute__('AsyncGenerator')
yield_contexts = self.merge_yield_contexts(is_async=True)
# The contravariant doesn't seem to be defined.
generics = (yield_contexts.py__class__(), NO_CONTEXTS)
return ContextSet(
AnnotatedSubClass(
evaluator,
parent_context=c.parent_context,
tree_node=c.tree_node,
# The contravariant doesn't seem to be defined.
given_types=(yield_contexts.py__class__(), NO_CONTEXTS)
) for c in async_generator_classes
AnnotatedSubClass(c, generics) for c in async_generator_classes
).execute_annotation()
else:
if evaluator.environment.version_info < (3, 5):
return NO_CONTEXTS
async_classes = evaluator.typing_module.py__getattribute__('Coroutine')
return_contexts = self.get_return_values()
# Only the first generic is relevant.
generics = (return_contexts.py__class__(), NO_CONTEXTS, NO_CONTEXTS)
return ContextSet(
AnnotatedSubClass(
evaluator,
parent_context=c.parent_context,
tree_node=c.tree_node,
# Only the first generic is relevant.
given_types=(return_contexts.py__class__(), NO_CONTEXTS, NO_CONTEXTS)
) for c in async_classes
AnnotatedSubClass(c, generics) for c in async_classes
).execute_annotation()
else:
if is_generator:

View File

@@ -210,10 +210,8 @@ class Sequence(BuiltinOverwrite, IterableMixin):
def get_object(self):
from jedi.evaluate.context.typing import AnnotatedSubClass
klass = compiled.builtin_from_name(self.evaluator, self.array_type)
return AnnotatedSubClass(
self.evaluator, klass.parent_context, klass.tree_node,
self._get_generics()
).execute_annotation()
# TODO is this execute annotation wrong? it returns a context set?!
return AnnotatedSubClass(klass, self._get_generics()).execute_annotation()
def py__bool__(self):
return None # We don't know the length, because of appends.

View File

@@ -42,7 +42,7 @@ from jedi._compatibility import use_metaclass
from jedi.parser_utils import get_parent_scope
from jedi.evaluate.cache import evaluator_method_cache, CachedMetaClass
from jedi.evaluate import compiled
from jedi.evaluate.lazy_context import LazyKnownContext
from jedi.evaluate.lazy_context import LazyKnownContexts
from jedi.evaluate.filters import ParserTreeFilter, TreeNameDefinition, \
ContextName
from jedi.evaluate.arguments import unpack_arglist
@@ -68,8 +68,9 @@ def py__mro__(context):
except AttributeError:
pass
else:
# Currently only used for compiled objects.
return method()
if not isinstance(context, ClassMixin):
# Currently only used for compiled objects.
return method()
def add(cls):
if cls not in mro:
@@ -161,7 +162,77 @@ class ClassFilter(ParserTreeFilter):
return [name for name in names if self._access_possible(name)]
class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
class ClassMixin(object):
def is_class(self):
return True
def py__call__(self, arguments):
from jedi.evaluate.context import TreeInstance
return ContextSet([TreeInstance(self.evaluator, self.parent_context, self, arguments)])
def py__class__(self):
return compiled.builtin_from_name(self.evaluator, u'type')
@property
def name(self):
return ContextName(self, self.tree_node.name)
def py__name__(self):
return self.name.string_name
def get_function_slot_names(self, name):
for filter in self.get_filters(search_global=False):
names = filter.get(name)
if names:
return names
return []
def get_param_names(self):
for name in self.get_function_slot_names(u'__init__'):
for context_ in name.infer():
try:
method = context_.get_param_names
except AttributeError:
pass
else:
return list(method())[1:]
return []
def py__mro__(self):
return py__mro__(self)
def get_filters(self, search_global=False, until_position=None,
origin_scope=None, is_instance=False):
if search_global:
yield ParserTreeFilter(
self.evaluator,
context=self,
until_position=until_position,
origin_scope=origin_scope
)
else:
for cls in py__mro__(self):
if isinstance(cls, compiled.CompiledObject):
for filter in cls.get_filters(is_instance=is_instance):
yield filter
else:
yield ClassFilter(
self.evaluator, self, node_context=cls,
origin_scope=origin_scope,
is_instance=is_instance
)
if not is_instance and self:
# Return completions of the meta class.
from jedi.evaluate.compiled import builtin_from_name
type_ = builtin_from_name(self.evaluator, u'type')
yield ClassFilter(
self.evaluator, self, node_context=type_,
origin_scope=origin_scope,
is_instance=is_instance
)
class ClassContext(use_metaclass(CachedMetaClass, ClassMixin, TreeContext)):
"""
This class is not only important to extend `tree.Class`, it is also a
important for descriptors (if the descriptor methods are evaluated or not).
@@ -194,72 +265,9 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
args = arguments.TreeArguments(self.evaluator, self.parent_context, arglist)
return [value for key, value in args.unpack() if key is None]
else:
return [LazyKnownContext(compiled.builtin_from_name(self.evaluator, u'object'))]
def py__call__(self, arguments):
from jedi.evaluate.context import TreeInstance
return ContextSet([TreeInstance(self.evaluator, self.parent_context, self, arguments)])
def py__class__(self):
return compiled.builtin_from_name(self.evaluator, u'type')
def get_filters(self, search_global=False, until_position=None,
origin_scope=None, is_instance=False):
if search_global:
yield ParserTreeFilter(
self.evaluator,
context=self,
until_position=until_position,
origin_scope=origin_scope
)
else:
for cls in py__mro__(self):
if isinstance(cls, compiled.CompiledObject):
for filter in cls.get_filters(is_instance=is_instance):
yield filter
else:
yield ClassFilter(
self.evaluator, self, node_context=cls,
origin_scope=origin_scope,
is_instance=is_instance
)
if not is_instance and self:
# Return completions of the meta class.
from jedi.evaluate.compiled import builtin_from_name
type_ = builtin_from_name(self.evaluator, u'type')
yield ClassFilter(
self.evaluator, self, node_context=type_,
origin_scope=origin_scope,
is_instance=is_instance
)
def is_class(self):
return True
def get_function_slot_names(self, name):
for filter in self.get_filters(search_global=False):
names = filter.get(name)
if names:
return names
return []
def get_param_names(self):
for name in self.get_function_slot_names(u'__init__'):
for context_ in name.infer():
try:
method = context_.get_param_names
except AttributeError:
pass
else:
return list(method())[1:]
return []
@property
def name(self):
return ContextName(self, self.tree_node.name)
def py__name__(self):
return self.name.string_name
return [LazyKnownContexts(
self.evaluator.builtins_module.py__getattribute__('object')
)]
def py__getitem__(self, index_context_set, contextualized_node):
from jedi.evaluate.context.typing import AnnotatedClass
@@ -267,9 +275,7 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
return ContextSet([self])
return ContextSet(
AnnotatedClass(
self.evaluator,
self.parent_context,
self.tree_node,
self,
index_context,
context_of_index=contextualized_node.context,
)
@@ -285,9 +291,7 @@ class ClassContext(use_metaclass(CachedMetaClass, TreeContext)):
if type_var_dict:
return AnnotatedSubClass(
self.evaluator,
self.parent_context,
self.tree_node,
self,
given_types=tuple(remap_type_vars())
)
return self

View File

@@ -9,7 +9,7 @@ from jedi.evaluate.cache import evaluator_method_cache
from jedi.evaluate.compiled import builtin_from_name
from jedi.evaluate.base_context import ContextSet, NO_CONTEXTS, Context, \
iterator_to_context_set, HelperContextMixin, ContextWrapper
from jedi.evaluate.lazy_context import LazyKnownContexts, LazyKnownContext
from jedi.evaluate.lazy_context import LazyKnownContexts
from jedi.evaluate.context.iterable import SequenceLiteralContext
from jedi.evaluate.arguments import repack_with_argument_clinic
from jedi.evaluate.utils import to_list
@@ -17,7 +17,7 @@ from jedi.evaluate.filters import FilterWrapper, NameWrapper, \
AbstractTreeName, AbstractNameDefinition, ContextName
from jedi.evaluate.helpers import is_string
from jedi.evaluate.imports import Importer
from jedi.evaluate.context.klass import py__mro__, ClassContext
from jedi.evaluate.context.klass import py__mro__, ClassMixin
_PROXY_CLASS_TYPES = 'Tuple Generic Protocol Callable Type'.split()
_TYPE_ALIAS_TYPES = {
@@ -192,8 +192,10 @@ class TypingContext(_BaseTypingContext):
class TypingClassMixin(object):
def py__bases__(self,):
return [LazyKnownContext(builtin_from_name(self.evaluator, u'object'))]
def py__bases__(self):
return [LazyKnownContexts(
self.evaluator.builtins_module.py__getattribute__('object')
)]
class TypingClassContextWithIndex(TypingClassMixin, TypingContextWithIndex):
@@ -490,7 +492,7 @@ class TypeVarFilter(object):
return []
class AbstractAnnotatedClass(ClassContext):
class AbstractAnnotatedClass(ClassMixin, ContextWrapper):
def get_type_var_filter(self):
return TypeVarFilter(self.get_given_types(), self.list_type_vars())
@@ -564,29 +566,26 @@ class AbstractAnnotatedClass(ClassContext):
return self
return AnnotatedSubClass(
self.evaluator,
self.parent_context,
self.tree_node,
self._wrapped_context,
given_types=tuple(new_generics)
)
def __repr__(self):
return '<%s: %s@%s%s>' % (
return '<%s: %s%s>' % (
self.__class__.__name__,
self.name.string_name,
self.name.tree_name.start_pos,
self._wrapped_context,
list(self.get_given_types()),
)
@to_list
def py__bases__(self):
for base in super(AbstractAnnotatedClass, self).py__bases__():
for base in self._wrapped_context.py__bases__():
yield LazyAnnotatedBaseClass(self, base)
class AnnotatedClass(AbstractAnnotatedClass):
def __init__(self, evaluator, parent_context, tree_node, index_context, context_of_index):
super(AnnotatedClass, self).__init__(evaluator, parent_context, tree_node)
def __init__(self, class_context, index_context, context_of_index):
super(AnnotatedClass, self).__init__(class_context)
self._index_context = index_context
self._context_of_index = context_of_index
@@ -596,8 +595,8 @@ class AnnotatedClass(AbstractAnnotatedClass):
class AnnotatedSubClass(AbstractAnnotatedClass):
def __init__(self, evaluator, parent_context, tree_node, given_types):
super(AnnotatedSubClass, self).__init__(evaluator, parent_context, tree_node)
def __init__(self, class_context, given_types):
super(AnnotatedSubClass, self).__init__(class_context)
self._given_types = given_types
def get_given_types(self):
@@ -616,8 +615,7 @@ class LazyAnnotatedBaseClass(object):
# Here we have to recalculate the given types.
yield AnnotatedSubClass.create_cached(
base.evaluator,
base.parent_context,
base.tree_node,
base._wrapped_context,
tuple(self._remap_type_vars(base)),
)
else: