diff --git a/jedi/inference/gradual/annotation.py b/jedi/inference/gradual/annotation.py index 79481a45..0d5effbd 100644 --- a/jedi/inference/gradual/annotation.py +++ b/jedi/inference/gradual/annotation.py @@ -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: diff --git a/test/completion/pep0484_generic_mismatches.py b/test/completion/pep0484_generic_mismatches.py new file mode 100644 index 00000000..bd7d393a --- /dev/null +++ b/test/completion/pep0484_generic_mismatches.py @@ -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 diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index a7337cfe..f8dab6e6 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -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"',