Add testing for mismatch cases

This should help catch any errors in our handling of invalid cases.
While some of these produce outputs which aren't correct, what
we're checking here is that we don't _error_ while producing that
output.

Also fix a case which this showed up.
This commit is contained in:
Peter Law
2020-03-22 14:58:18 +00:00
parent 95b0cdcb5e
commit 5ca69458d4
3 changed files with 326 additions and 0 deletions

View File

@@ -494,6 +494,11 @@ def _infer_type_vars(annotation_value, value_set, is_class_value=False):
# the elements from the set first, then handle them, even if we put
# them back in a set afterwards.
for element in value_set:
if element.api_type == u'function':
# Functions & methods don't have an MRO and we're not
# expecting a Callable (those are handled separately above).
continue
if element.is_instance():
py_class = element.get_annotated_class_object()
else:

View File

@@ -0,0 +1,320 @@
# python >= 3.4
from typing import (
Callable,
Dict,
Generic,
List,
Sequence,
Tuple,
Type,
TypeVar,
)
T = TypeVar('T')
def foo(x: T) -> T:
return x
class CustomGeneric(Generic[T]):
def __init__(self, val: T) -> None:
self.val = val
class PlainClass(object):
pass
tpl = ("1", 2)
tpl_typed = ("2", 3) # type: Tuple[str, int]
collection = {"a": 1}
collection_typed = {"a": 1} # type: Dict[str, int]
list_of_funcs = [foo] # type: List[Callable[[T], T]]
custom_generic = CustomGeneric(123.45)
plain_instance = PlainClass()
# Test that simple parameters are handled
def list_t_to_list_t(the_list: List[T]) -> List[T]:
return the_list
x0 = list_t_to_list_t("abc")[0]
#?
x0
x1 = list_t_to_list_t(foo)[0]
#?
x1
x2 = list_t_to_list_t(tpl)[0]
#?
x2
x3 = list_t_to_list_t(tpl_typed)[0]
#?
x3
x4 = list_t_to_list_t(collection)[0]
#?
x4
x5 = list_t_to_list_t(collection_typed)[0]
#?
x5
x6 = list_t_to_list_t(custom_generic)[0]
#?
x6
x7 = list_t_to_list_t(plain_instance)[0]
#?
x7
for a in list_t_to_list_t(12):
#?
a
# Test that simple parameters are handled
def list_type_t_to_list_t(the_list: List[Type[T]]) -> List[T]:
return [x() for x in the_list]
x0 = list_type_t_to_list_t("abc")[0]
#?
x0
x1 = list_type_t_to_list_t(foo)[0]
#?
x1
x2 = list_type_t_to_list_t(tpl)[0]
#?
x2
x3 = list_type_t_to_list_t(tpl_typed)[0]
#?
x3
x4 = list_type_t_to_list_t(collection)[0]
#?
x4
x5 = list_type_t_to_list_t(collection_typed)[0]
#?
x5
x6 = list_type_t_to_list_t(custom_generic)[0]
#?
x6
x7 = list_type_t_to_list_t(plain_instance)[0]
#?
x7
for a in list_type_t_to_list_t(12):
#?
a
x0 = list_type_t_to_list_t(["abc"])[0]
#?
x0
x1 = list_type_t_to_list_t([foo])[0]
#?
x1
x2 = list_type_t_to_list_t([tpl])[0]
#?
x2
x3 = list_type_t_to_list_t([tpl_typed])[0]
#?
x3
x4 = list_type_t_to_list_t([collection])[0]
#?
x4
x5 = list_type_t_to_list_t([collection_typed])[0]
#?
x5
x6 = list_type_t_to_list_t([custom_generic])[0]
#?
x6
x7 = list_type_t_to_list_t([plain_instance])[0]
#?
x7
for a in list_type_t_to_list_t([12]):
#?
a
def list_func_t_to_list_t(the_list: List[Callable[[T], T]]) -> List[T]:
# Not actually a viable signature, but should be enough to test our handling
# of the generic parameters.
pass
x0 = list_func_t_to_list_t("abc")[0]
#?
x0
x1 = list_func_t_to_list_t(foo)[0]
#?
x1
x2 = list_func_t_to_list_t(tpl)[0]
#?
x2
x3 = list_func_t_to_list_t(tpl_typed)[0]
#?
x3
x4 = list_func_t_to_list_t(collection)[0]
#?
x4
x5 = list_func_t_to_list_t(collection_typed)[0]
#?
x5
x6 = list_func_t_to_list_t(custom_generic)[0]
#?
x6
x7 = list_func_t_to_list_t(plain_instance)[0]
#?
x7
for a in list_func_t_to_list_t(12):
#?
a
# The following are all actually wrong, however we're mainly testing here that
# we don't error when processing invalid values, rather than that we get the
# right output.
x0 = list_func_t_to_list_t(["abc"])[0]
#? str()
x0
x2 = list_func_t_to_list_t([tpl])[0]
#? tuple()
x2
x3 = list_func_t_to_list_t([tpl_typed])[0]
#? tuple()
x3
x4 = list_func_t_to_list_t([collection])[0]
#? dict()
x4
x5 = list_func_t_to_list_t([collection_typed])[0]
#? dict()
x5
x6 = list_func_t_to_list_t([custom_generic])[0]
#? CustomGeneric()
x6
x7 = list_func_t_to_list_t([plain_instance])[0]
#? PlainClass()
x7
for a in list_func_t_to_list_t([12]):
#? int()
a
def tuple_t(tuple_in: Tuple[T]]) -> Sequence[T]:
return tuple_in
x0 = list_t_to_list_t("abc")[0]
#?
x0
x1 = list_t_to_list_t(foo)[0]
#?
x1
x2 = list_t_to_list_t(tpl)[0]
#?
x2
x3 = list_t_to_list_t(tpl_typed)[0]
#?
x3
x4 = list_t_to_list_t(collection)[0]
#?
x4
x5 = list_t_to_list_t(collection_typed)[0]
#?
x5
x6 = list_t_to_list_t(custom_generic)[0]
#?
x6
x7 = list_t_to_list_t(plain_instance)[0]
#?
x7
for a in list_t_to_list_t(12):
#?
a
def tuple_t_elipsis(tuple_in: Tuple[T, ...]]) -> Sequence[T]:
return tuple_in
x0 = list_t_to_list_t("abc")[0]
#?
x0
x1 = list_t_to_list_t(foo)[0]
#?
x1
x2 = list_t_to_list_t(tpl)[0]
#?
x2
x3 = list_t_to_list_t(tpl_typed)[0]
#?
x3
x4 = list_t_to_list_t(collection)[0]
#?
x4
x5 = list_t_to_list_t(collection_typed)[0]
#?
x5
x6 = list_t_to_list_t(custom_generic)[0]
#?
x6
x7 = list_t_to_list_t(plain_instance)[0]
#?
x7
for a in list_t_to_list_t(12):
#?
a

View File

@@ -342,6 +342,7 @@ def test_file_fuzzy_completion(Script):
script = Script('"{}/ep08_i'.format(path))
expected = [
'pep0484_basic.py"',
'pep0484_generic_mismatches.py"',
'pep0484_generic_parameters.py"',
'pep0484_generic_passthroughs.py"',
'pep0484_typing.py"',