builtins.pyi: Use two type vars#3291
Conversation
srittau
left a comment
There was a problem hiding this comment.
Unfortunately this does not work, at least with mypy. The best we can probably do here is to use a liberal sprinkling of Any. Testing also revealed that special-casing Optional works with the example provided in #3201. Since None is most likely often used as sentinel, special casing it makes sense to me:
@overload
def iter(__function: Callable[[], Optional[_T]], __sentinel: None) -> Iterator[_T]: ...
@overload
def iter(__function: Callable[[], Any], __sentinel: Any) -> Iterator[Any]: ...cc @JelleZijlstra for another pair of eyes.
Ack, makes sense. Thank you! |
|
thanks all, but it seems to me the fallback the original was: ...which seems more strict and hence more correct? i am curious to learn why adding a special case for the (indeed common) |
|
@wbolster-eiq Without the overload, the following valid case is rejected: def foo() -> Union[str, int]:
return ""
reveal_type(iter(foo, -1))That said, keeping the other overload as second-to-last makes sense to keep the more precise typing for the common case. Would you care to send a PR? |
|
@srittau do i understand correctly that the complete definition should be like this? @overload
def iter(__iterable: Iterable[_T]) -> Iterator[_T]: ...
@overload
def iter(__function: Callable[[], Optional[_T]], __sentinel: None) -> Iterator[_T]: ...
@overload
def iter(__function: Callable[[], _T], __sentinel: _T) -> Iterator[_T]: ...if so, yeah, i can turn that into a pull request, but right now i'm not sure i understand 100%. |
|
@wbolster-eiq: We would still need the |
| def iter(__function: Callable[[], _T], __sentinel: _T) -> Iterator[_T]: ... | ||
| def iter(__function: Callable[[], Optional[_T]], __sentinel: None) -> Iterator[_T]: ... | ||
| @overload | ||
| def iter(__function: Callable[[], Any], __sentinel: Any) -> Iterator[Any]: ... |
There was a problem hiding this comment.
the Any is too relaxed here. the output from the callable will always be the same as the value yielded by the iterator, regardless of what the sentinel type is. i will open a pull request to make this more strict.
|
i've opened #3326 as a follow-up to this pull request. |
) This is a continuation of #3291, which was the initial fix for #3201. The 2-arg version of iter() turns a callable into an iterator. The changes made in #3291 introduce an Any return type for both the callable's return type and the iterator's type, while in reality the return type of the function is always the same as the iterator's type.
Fixes: #3201