1
0
forked from VimPlug/jedi

Add support for generic optional parameters (#1559)

* Add support for generic optional parameters

* Tests for passing non-optional arguments to optional parameters

* Remove now-redundant is_class_value handling

This parameter has since been removed from infer_type_vars methods,
much simplifying the code.
This commit is contained in:
Peter Law
2020-05-15 18:56:03 +01:00
committed by GitHub
parent d4aa583e16
commit 43806f8668
2 changed files with 67 additions and 0 deletions

View File

@@ -145,6 +145,24 @@ class TypingClassWithIndex(BaseTypingClassWithGenerics):
generics_manager generics_manager
) )
def infer_type_vars(self, value_set):
annotation_generics = self.get_generics()
if not annotation_generics:
return {}
annotation_name = self.py__name__()
if annotation_name == 'Optional':
# Optional[T] is equivalent to Union[T, None]. In Jedi unions
# are represented by members within a ValueSet, so we extract
# the T from the Optional[T] by removing the None value.
none = builtin_from_name(self.inference_state, u'None')
return annotation_generics[0].infer_type_vars(
value_set.filter(lambda x: x != none),
)
return {}
class ProxyTypingValue(BaseTypingValue): class ProxyTypingValue(BaseTypingValue):
index_class = TypingClassWithIndex index_class = TypingClassWithIndex

View File

@@ -6,6 +6,7 @@ from typing import (
Iterable, Iterable,
List, List,
Mapping, Mapping,
Optional,
Tuple, Tuple,
Type, Type,
TypeVar, TypeVar,
@@ -19,7 +20,11 @@ T_co = TypeVar('T_co', covariant=True)
V = TypeVar('V') V = TypeVar('V')
just_float = 42. # type: float
optional_float = 42. # type: Optional[float]
list_of_ints = [42] # type: List[int] list_of_ints = [42] # type: List[int]
list_of_floats = [42.] # type: List[float]
list_of_optional_floats = [x or None for x in list_of_floats] # type: List[Optional[float]]
list_of_ints_and_strs = [42, 'abc'] # type: List[Union[int, str]] list_of_ints_and_strs = [42, 'abc'] # type: List[Union[int, str]]
# Test that simple parameters are handled # Test that simple parameters are handled
@@ -47,6 +52,50 @@ for z in list_t_to_list_t(list_of_ints_and_strs):
list_of_int_type = [int] # type: List[Type[int]] list_of_int_type = [int] # type: List[Type[int]]
# Test that nested parameters are handled # Test that nested parameters are handled
def list_optional_t_to_list_t(the_list: List[Optional[T]]) -> List[T]:
return [x for x in the_list if x is not None]
for xa in list_optional_t_to_list_t(list_of_optional_floats):
#? float()
xa
# Under covariance rules this is strictly incorrect (because List is mutable,
# the function would be allowed to put `None`s into our List[float], which would
# be bad), however we don't expect jedi to enforce that.
for xa1 in list_optional_t_to_list_t(list_of_floats):
#? float()
xa1
def optional_t_to_list_t(x: Optional[T]) -> List[T]:
return [x] if x is not None else []
for xb in optional_t_to_list_t(optional_float):
#? float()
xb
for xb2 in optional_t_to_list_t(just_float):
#? float()
xb2
def optional_list_t_to_list_t(x: Optional[List[T]]) -> List[T]:
return x if x is not None else []
optional_list_float = None # type: Optional[List[float]]
for xc in optional_list_t_to_list_t(optional_list_float):
#? float()
xc
for xc2 in optional_list_t_to_list_t(list_of_floats):
#? float()
xc2
def list_type_t_to_list_t(the_list: List[Type[T]]) -> List[T]: def list_type_t_to_list_t(the_list: List[Type[T]]) -> List[T]:
return [x() for x in the_list] return [x() for x in the_list]