mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-09 07:14:48 +08:00
Start using generic managers, for #1413
This commit is contained in:
@@ -12,8 +12,8 @@ from parso import ParserSyntaxError, parse
|
|||||||
from jedi._compatibility import force_unicode, Parameter
|
from jedi._compatibility import force_unicode, Parameter
|
||||||
from jedi.inference.cache import inference_state_method_cache
|
from jedi.inference.cache import inference_state_method_cache
|
||||||
from jedi.inference.base_value import ValueSet, NO_VALUES
|
from jedi.inference.base_value import ValueSet, NO_VALUES
|
||||||
from jedi.inference.gradual.base import LazyGenericClass, \
|
from jedi.inference.gradual.base import DefineGenericBase, GenericClass
|
||||||
DefineGenericBase, GenericClass
|
from jedi.inference.gradual.generics import TupleGenericManager
|
||||||
from jedi.inference.gradual.typing import TypingClassValueWithIndex
|
from jedi.inference.gradual.typing import TypingClassValueWithIndex
|
||||||
from jedi.inference.gradual.type_var import TypeVar
|
from jedi.inference.gradual.type_var import TypeVar
|
||||||
from jedi.inference.helpers import is_string
|
from jedi.inference.helpers import is_string
|
||||||
@@ -118,13 +118,17 @@ def infer_param(function_value, param, ignore_stars=False):
|
|||||||
tuple_ = builtin_from_name(inference_state, 'tuple')
|
tuple_ = builtin_from_name(inference_state, 'tuple')
|
||||||
return ValueSet([GenericClass(
|
return ValueSet([GenericClass(
|
||||||
tuple_,
|
tuple_,
|
||||||
generics=(values,),
|
TupleGenericManager((values,)),
|
||||||
) for c in values])
|
) for c in values])
|
||||||
elif param.star_count == 2:
|
elif param.star_count == 2:
|
||||||
dct = builtin_from_name(inference_state, 'dict')
|
dct = builtin_from_name(inference_state, 'dict')
|
||||||
|
generics = (
|
||||||
|
ValueSet([builtin_from_name(inference_state, 'str')]),
|
||||||
|
values
|
||||||
|
)
|
||||||
return ValueSet([GenericClass(
|
return ValueSet([GenericClass(
|
||||||
dct,
|
dct,
|
||||||
generics=(ValueSet([builtin_from_name(inference_state, 'str')]), values),
|
TupleGenericManager(generics),
|
||||||
) for c in values])
|
) for c in values])
|
||||||
pass
|
pass
|
||||||
return values
|
return values
|
||||||
@@ -325,7 +329,7 @@ def _infer_type_vars(annotation_value, value_set, is_class_value=False):
|
|||||||
value_set.execute_annotation(),
|
value_set.execute_annotation(),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif isinstance(annotation_value, LazyGenericClass):
|
elif isinstance(annotation_value, GenericClass):
|
||||||
name = annotation_value.py__name__()
|
name = annotation_value.py__name__()
|
||||||
if name == 'Iterable':
|
if name == 'Iterable':
|
||||||
given = annotation_value.get_generics()
|
given = annotation_value.get_generics()
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ from jedi.inference.value.klass import ClassMixin
|
|||||||
from jedi.inference.utils import to_list
|
from jedi.inference.utils import to_list
|
||||||
from jedi.inference.names import AbstractNameDefinition, ValueName
|
from jedi.inference.names import AbstractNameDefinition, ValueName
|
||||||
from jedi.inference.context import ClassContext
|
from jedi.inference.context import ClassContext
|
||||||
from jedi.inference.gradual.generics import iter_over_arguments
|
from jedi.inference.gradual.generics import TupleGenericManager
|
||||||
|
|
||||||
|
|
||||||
class BaseTypingValue(Value):
|
class BaseTypingValue(Value):
|
||||||
@@ -149,7 +149,7 @@ class DefineGenericBase(LazyValueWrapper):
|
|||||||
|
|
||||||
return ValueSet([self._get_fixed_generics_cls()(
|
return ValueSet([self._get_fixed_generics_cls()(
|
||||||
self._wrapped_value,
|
self._wrapped_value,
|
||||||
generics=tuple(new_generics)
|
TupleGenericManager(tuple(new_generics))
|
||||||
)])
|
)])
|
||||||
|
|
||||||
def is_same_class(self, other):
|
def is_same_class(self, other):
|
||||||
@@ -197,7 +197,7 @@ class _AbstractAnnotatedClass(ClassMixin, DefineGenericBase):
|
|||||||
|
|
||||||
def py__call__(self, arguments):
|
def py__call__(self, arguments):
|
||||||
instance, = super(_AbstractAnnotatedClass, self).py__call__(arguments)
|
instance, = super(_AbstractAnnotatedClass, self).py__call__(arguments)
|
||||||
return ValueSet([InstanceWrapper(instance)])
|
return ValueSet([_InstanceWrapper(instance)])
|
||||||
|
|
||||||
def _as_context(self):
|
def _as_context(self):
|
||||||
return AnnotatedClassContext(self)
|
return AnnotatedClassContext(self)
|
||||||
@@ -205,30 +205,20 @@ class _AbstractAnnotatedClass(ClassMixin, DefineGenericBase):
|
|||||||
@to_list
|
@to_list
|
||||||
def py__bases__(self):
|
def py__bases__(self):
|
||||||
for base in self._wrapped_value.py__bases__():
|
for base in self._wrapped_value.py__bases__():
|
||||||
yield LazyAnnotatedBaseClass(self, base)
|
yield _LazyAnnotatedBaseClass(self, base)
|
||||||
|
|
||||||
|
|
||||||
class LazyGenericClass(_AbstractAnnotatedClass):
|
|
||||||
def __init__(self, class_value, index_value, context_of_index):
|
|
||||||
super(LazyGenericClass, self).__init__(class_value)
|
|
||||||
self._index_value = index_value
|
|
||||||
self._context_of_index = context_of_index
|
|
||||||
|
|
||||||
@inference_state_method_cache()
|
|
||||||
def get_generics(self):
|
|
||||||
return list(iter_over_arguments(self._index_value, self._context_of_index))
|
|
||||||
|
|
||||||
|
|
||||||
class GenericClass(_AbstractAnnotatedClass):
|
class GenericClass(_AbstractAnnotatedClass):
|
||||||
def __init__(self, class_value, generics):
|
def __init__(self, class_value, generics_manager):
|
||||||
super(GenericClass, self).__init__(class_value)
|
super(GenericClass, self).__init__(class_value)
|
||||||
self._generics = generics
|
self._generics_manager = generics_manager
|
||||||
|
|
||||||
|
@inference_state_method_cache()
|
||||||
def get_generics(self):
|
def get_generics(self):
|
||||||
return self._generics
|
return self._generics_manager.to_tuple()
|
||||||
|
|
||||||
|
|
||||||
class LazyAnnotatedBaseClass(object):
|
class _LazyAnnotatedBaseClass(object):
|
||||||
def __init__(self, class_value, lazy_base_class):
|
def __init__(self, class_value, lazy_base_class):
|
||||||
self._class_value = class_value
|
self._class_value = class_value
|
||||||
self._lazy_base_class = lazy_base_class
|
self._lazy_base_class = lazy_base_class
|
||||||
@@ -241,7 +231,7 @@ class LazyAnnotatedBaseClass(object):
|
|||||||
yield GenericClass.create_cached(
|
yield GenericClass.create_cached(
|
||||||
base.inference_state,
|
base.inference_state,
|
||||||
base._wrapped_value,
|
base._wrapped_value,
|
||||||
tuple(self._remap_type_vars(base)),
|
TupleGenericManager(tuple(self._remap_type_vars(base))),
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
yield base
|
yield base
|
||||||
@@ -265,7 +255,7 @@ class LazyAnnotatedBaseClass(object):
|
|||||||
yield new
|
yield new
|
||||||
|
|
||||||
|
|
||||||
class InstanceWrapper(ValueWrapper):
|
class _InstanceWrapper(ValueWrapper):
|
||||||
def py__stop_iteration_returns(self):
|
def py__stop_iteration_returns(self):
|
||||||
for cls in self._wrapped_value.class_value.py__mro__():
|
for cls in self._wrapped_value.class_value.py__mro__():
|
||||||
if cls.py__name__() == 'Generator':
|
if cls.py__name__() == 'Generator':
|
||||||
|
|||||||
@@ -1,5 +1,10 @@
|
|||||||
|
"""
|
||||||
|
This module is about generics, like the `int` in `List[int]`. It's not about
|
||||||
|
the Generic class.
|
||||||
|
"""
|
||||||
|
|
||||||
from jedi.cache import memoize_method
|
from jedi.cache import memoize_method
|
||||||
from jedi.inference.utils import to_list
|
from jedi.inference.utils import to_tuple
|
||||||
from jedi.inference.base_value import ValueSet
|
from jedi.inference.base_value import ValueSet
|
||||||
from jedi.inference.value.iterable import SequenceLiteralValue
|
from jedi.inference.value.iterable import SequenceLiteralValue
|
||||||
from jedi.inference.helpers import is_string
|
from jedi.inference.helpers import is_string
|
||||||
@@ -36,39 +41,51 @@ class LazyGenericManager(object):
|
|||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
return self._list()[index]()
|
return self._tuple()[index]()
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._list())
|
return len(self._tuple())
|
||||||
|
|
||||||
@memoize_method
|
@memoize_method
|
||||||
@to_list
|
@to_tuple
|
||||||
def _list(self):
|
def _tuple(self):
|
||||||
if isinstance(self._index_value, SequenceLiteralValue):
|
def lambda_scoping_in_for_loop_sucks(lazy_value):
|
||||||
for lazy_value in self._index_value.py__iter__(contextualized_node=None):
|
return lambda: ValueSet(_resolve_forward_references(
|
||||||
yield lambda: _resolve_forward_references(
|
|
||||||
self._context_of_index,
|
self._context_of_index,
|
||||||
lazy_value.infer()
|
lazy_value.infer()
|
||||||
)
|
))
|
||||||
|
|
||||||
|
if isinstance(self._index_value, SequenceLiteralValue):
|
||||||
|
for lazy_value in self._index_value.py__iter__(contextualized_node=None):
|
||||||
|
yield lambda_scoping_in_for_loop_sucks(lazy_value)
|
||||||
else:
|
else:
|
||||||
yield lambda: ValueSet([
|
yield lambda: ValueSet(_resolve_forward_references(
|
||||||
_resolve_forward_references(self._context_of_index, self._index_value)
|
self._context_of_index,
|
||||||
])
|
ValueSet([self._index_value])
|
||||||
|
))
|
||||||
|
|
||||||
def __iter__(self):
|
@to_tuple
|
||||||
return iter(self._iterate())
|
def to_tuple(self):
|
||||||
|
for callable_ in self._tuple():
|
||||||
|
yield callable_()
|
||||||
|
|
||||||
|
#def __iter__(self):
|
||||||
|
# return iter(self._iterate())
|
||||||
|
|
||||||
|
|
||||||
class ListGenericManager(object):
|
class TupleGenericManager(object):
|
||||||
def __init__(self, lst):
|
def __init__(self, tup):
|
||||||
self._lst = lst
|
self._tuple = tup
|
||||||
|
|
||||||
def __getitem__(self, index):
|
def __getitem__(self, index):
|
||||||
return self._lst[index]
|
return self._tuple[index]
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self._lst)
|
return len(self._tuple)
|
||||||
|
|
||||||
def __iter__(self):
|
#def __iter__(self):
|
||||||
for value_set in self._lst:
|
# for value_set in self._tuple:
|
||||||
yield lambda: value_set
|
# yield lambda: value_set
|
||||||
|
|
||||||
|
def to_tuple(self):
|
||||||
|
return self._tuple
|
||||||
|
|||||||
@@ -21,6 +21,12 @@ def to_list(func):
|
|||||||
return wrapper
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
|
def to_tuple(func):
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
return tuple(func(*args, **kwargs))
|
||||||
|
return wrapper
|
||||||
|
|
||||||
|
|
||||||
def unite(iterable):
|
def unite(iterable):
|
||||||
"""Turns a two dimensional array into a one dimensional."""
|
"""Turns a two dimensional array into a one dimensional."""
|
||||||
return set(typ for types in iterable for typ in types)
|
return set(typ for types in iterable for typ in types)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from jedi.inference.value import iterable
|
|||||||
from jedi import parser_utils
|
from jedi import parser_utils
|
||||||
from jedi.inference.parser_cache import get_yield_exprs
|
from jedi.inference.parser_cache import get_yield_exprs
|
||||||
from jedi.inference.helpers import values_from_qualified_names
|
from jedi.inference.helpers import values_from_qualified_names
|
||||||
|
from jedi.inference.gradual.generics import TupleGenericManager
|
||||||
|
|
||||||
|
|
||||||
class LambdaName(AbstractNameDefinition):
|
class LambdaName(AbstractNameDefinition):
|
||||||
@@ -297,7 +298,7 @@ class BaseFunctionExecutionContext(ValueContext, TreeContextMixin):
|
|||||||
generics = (yield_values.py__class__(), NO_VALUES)
|
generics = (yield_values.py__class__(), NO_VALUES)
|
||||||
return ValueSet(
|
return ValueSet(
|
||||||
# In Python 3.6 AsyncGenerator is still a class.
|
# In Python 3.6 AsyncGenerator is still a class.
|
||||||
GenericClass(c, generics)
|
GenericClass(c, TupleGenericManager(generics))
|
||||||
for c in async_generator_classes
|
for c in async_generator_classes
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
else:
|
else:
|
||||||
@@ -308,7 +309,7 @@ class BaseFunctionExecutionContext(ValueContext, TreeContextMixin):
|
|||||||
# Only the first generic is relevant.
|
# Only the first generic is relevant.
|
||||||
generics = (return_values.py__class__(), NO_VALUES, NO_VALUES)
|
generics = (return_values.py__class__(), NO_VALUES, NO_VALUES)
|
||||||
return ValueSet(
|
return ValueSet(
|
||||||
GenericClass(c, generics) for c in async_classes
|
GenericClass(c, TupleGenericManager(generics)) for c in async_classes
|
||||||
).execute_annotation()
|
).execute_annotation()
|
||||||
else:
|
else:
|
||||||
if is_generator:
|
if is_generator:
|
||||||
|
|||||||
@@ -195,8 +195,12 @@ class Sequence(LazyAttributeOverwrite, IterableMixin):
|
|||||||
|
|
||||||
def _get_wrapped_value(self):
|
def _get_wrapped_value(self):
|
||||||
from jedi.inference.gradual.base import GenericClass
|
from jedi.inference.gradual.base import GenericClass
|
||||||
|
from jedi.inference.gradual.generics import TupleGenericManager
|
||||||
klass = compiled.builtin_from_name(self.inference_state, self.array_type)
|
klass = compiled.builtin_from_name(self.inference_state, self.array_type)
|
||||||
c, = GenericClass(klass, self._get_generics()).execute_annotation()
|
c, = GenericClass(
|
||||||
|
klass,
|
||||||
|
TupleGenericManager(self._get_generics())
|
||||||
|
).execute_annotation()
|
||||||
return c
|
return c
|
||||||
|
|
||||||
def py__bool__(self):
|
def py__bool__(self):
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ from jedi.inference.base_value import ValueSet, iterator_to_value_set, \
|
|||||||
NO_VALUES
|
NO_VALUES
|
||||||
from jedi.inference.context import ClassContext
|
from jedi.inference.context import ClassContext
|
||||||
from jedi.inference.value.function import FunctionAndClassBase
|
from jedi.inference.value.function import FunctionAndClassBase
|
||||||
|
from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager
|
||||||
from jedi.plugins import plugin_manager
|
from jedi.plugins import plugin_manager
|
||||||
|
|
||||||
|
|
||||||
@@ -266,14 +267,16 @@ class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase
|
|||||||
)]
|
)]
|
||||||
|
|
||||||
def py__getitem__(self, index_value_set, contextualized_node):
|
def py__getitem__(self, index_value_set, contextualized_node):
|
||||||
from jedi.inference.gradual.base import LazyGenericClass
|
from jedi.inference.gradual.base import GenericClass
|
||||||
if not index_value_set:
|
if not index_value_set:
|
||||||
return ValueSet([self])
|
return ValueSet([self])
|
||||||
return ValueSet(
|
return ValueSet(
|
||||||
LazyGenericClass(
|
GenericClass(
|
||||||
self,
|
self,
|
||||||
index_value,
|
LazyGenericManager(
|
||||||
context_of_index=contextualized_node.context,
|
context_of_index=contextualized_node.context,
|
||||||
|
index_value=index_value,
|
||||||
|
)
|
||||||
)
|
)
|
||||||
for index_value in index_value_set
|
for index_value in index_value_set
|
||||||
)
|
)
|
||||||
@@ -297,7 +300,7 @@ class ClassValue(use_metaclass(CachedMetaClass, ClassMixin, FunctionAndClassBase
|
|||||||
if type_var_dict:
|
if type_var_dict:
|
||||||
return ValueSet([GenericClass(
|
return ValueSet([GenericClass(
|
||||||
self,
|
self,
|
||||||
generics=tuple(remap_type_vars())
|
TupleGenericManager(tuple(remap_type_vars()))
|
||||||
)])
|
)])
|
||||||
return ValueSet({self})
|
return ValueSet({self})
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user