diff --git a/jedi/inference/gradual/annotation.py b/jedi/inference/gradual/annotation.py index 60eb06bd..6839d8c9 100644 --- a/jedi/inference/gradual/annotation.py +++ b/jedi/inference/gradual/annotation.py @@ -12,7 +12,7 @@ from parso import ParserSyntaxError, parse from jedi._compatibility import force_unicode, Parameter from jedi.inference.cache import inference_state_method_cache from jedi.inference.base_value import ValueSet, NO_VALUES -from jedi.inference.gradual.base import DefineGenericBase, GenericClass +from jedi.inference.gradual.base import DefineGenericBase, GenericClass, BaseTypingInstance from jedi.inference.gradual.generics import TupleGenericManager from jedi.inference.gradual.type_var import TypeVar from jedi.inference.helpers import is_string @@ -350,7 +350,7 @@ def merge_pairwise_generics(annotation_value, annotated_argument_class): type_var_dict = {} - if not isinstance(annotated_argument_class, DefineGenericBase): + if not isinstance(annotated_argument_class, (DefineGenericBase, BaseTypingInstance)): return type_var_dict annotation_generics = annotation_value.get_generics() diff --git a/jedi/inference/gradual/base.py b/jedi/inference/gradual/base.py index 8ed1f4bc..de8dee85 100644 --- a/jedi/inference/gradual/base.py +++ b/jedi/inference/gradual/base.py @@ -4,6 +4,7 @@ from jedi.inference.base_value import ValueSet, NO_VALUES, Value, \ from jedi.inference.compiled import builtin_from_name from jedi.inference.value.klass import ClassFilter from jedi.inference.value.klass import ClassMixin +from jedi.inference.value.instance import AbstractInstanceValue from jedi.inference.utils import to_list from jedi.inference.names import AbstractNameDefinition, ValueName from jedi.inference.context import ClassContext @@ -375,3 +376,27 @@ class BaseTypingValueWithGenerics(DefineGenericBase): def __repr__(self): return '%s(%s%s)' % (self.__class__.__name__, self._tree_name.value, self._generics_manager) + + +class BaseTypingInstance(LazyValueWrapper): + def __init__(self, parent_context, class_value, tree_name, generics_manager): + self.inference_state = class_value.inference_state + self.parent_context = parent_context + self._class_value = class_value + self._tree_name = tree_name + self._generics_manager = generics_manager + + def py__class__(self): + return self._class_value + + @property + def name(self): + return ValueName(self, self._tree_name) + + @inference_state_method_cache() + def get_generics(self): + return self._generics_manager.to_tuple() + + def _get_wrapped_value(self): + object_, = builtin_from_name(self.inference_state, u'object').execute_annotation() + return object_ diff --git a/jedi/inference/gradual/typing.py b/jedi/inference/gradual/typing.py index 6ff78c7c..5c30f678 100644 --- a/jedi/inference/gradual/typing.py +++ b/jedi/inference/gradual/typing.py @@ -17,7 +17,8 @@ from jedi.inference.arguments import repack_with_argument_clinic from jedi.inference.filters import FilterWrapper from jedi.inference.names import NameWrapper, ValueName from jedi.inference.value.klass import ClassMixin -from jedi.inference.gradual.base import BaseTypingValue, BaseTypingValueWithGenerics +from jedi.inference.gradual.base import BaseTypingValue, \ + BaseTypingValueWithGenerics, BaseTypingInstance from jedi.inference.gradual.type_var import TypeVarClass from jedi.inference.gradual.generics import LazyGenericManager, TupleGenericManager @@ -129,6 +130,7 @@ class TypingValueWithIndex(BaseTypingValueWithGenerics): cls = mapped[string_name] return ValueSet([cls( self.parent_context, + self, self._tree_name, generics_manager=self._generics_manager, )]) @@ -197,7 +199,7 @@ class TypingClassValueWithIndex(_TypingClassMixin, TypingValueWithIndex): # This is basically a trick to avoid extra code: We execute the # incoming classes to be able to use the normal code for type # var inference. - value_set.execute_with_values(), + value_set.execute_annotation(), ) elif annotation_name == 'Callable': @@ -254,7 +256,7 @@ class TypeAlias(LazyValueWrapper): return ValueSet([self._get_wrapped_value()]) -class Callable(BaseTypingValueWithGenerics): +class Callable(BaseTypingInstance): def py__call__(self, arguments): """ def x() -> Callable[[Callable[..., _T]], _T]: ... @@ -271,7 +273,7 @@ class Callable(BaseTypingValueWithGenerics): return infer_return_for_callable(arguments, param_values, result_values) -class Tuple(BaseTypingValueWithGenerics): +class Tuple(BaseTypingInstance): def _is_homogenous(self): # To specify a variable-length tuple of homogeneous type, Tuple[T, ...] # is used. @@ -307,6 +309,10 @@ class Tuple(BaseTypingValueWithGenerics): .py__getattribute__('tuple').execute_annotation() return tuple_ + @property + def name(self): + return self._wrapped_value.name + def infer_type_vars(self, value_set): # Circular from jedi.inference.gradual.annotation import merge_pairwise_generics, merge_type_var_dicts @@ -352,11 +358,11 @@ class Tuple(BaseTypingValueWithGenerics): return type_var_dict -class Generic(BaseTypingValueWithGenerics): +class Generic(BaseTypingInstance): pass -class Protocol(BaseTypingValueWithGenerics): +class Protocol(BaseTypingInstance): pass diff --git a/test/completion/pep0484_generic_parameters.py b/test/completion/pep0484_generic_parameters.py index 9edcd061..3898b17f 100644 --- a/test/completion/pep0484_generic_parameters.py +++ b/test/completion/pep0484_generic_parameters.py @@ -10,6 +10,7 @@ from typing import ( Type, TypeVar, Union, + Sequence, ) K = TypeVar('K') @@ -165,6 +166,9 @@ some_str = NotImplemented # type: str #? str() first(some_str) +annotated = [len] # type: List[ Callable[[Sequence[float]], int] ] +#? int() +first(annotated)() # Test that the right type is chosen when a partially realised mapping is expected def values(mapping: Mapping[int, T]) -> List[T]: