Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

builtins.filter compat with typing.TypeGuard #6726

Merged
merged 2 commits into from
Jan 22, 2022
Merged

builtins.filter compat with typing.TypeGuard #6726

merged 2 commits into from
Jan 22, 2022

Conversation

Jasha10
Copy link
Contributor

@Jasha10 Jasha10 commented Dec 28, 2021

Based on microsoft/pyright#2768.

This change enables the following use-case:

def is_not_none(x: Optional[int]) -> TypeGuard[int]:
    return x is not None

list_optional: list[Optional[int]] = [0, None, 1, None, 2]
generate_ints: Iterable[int] = filter(is_not_none, list_optional)

This change enables the following use-case:
```python
def is_not_none(x: Optional[int]) -> TypeGuard[int]:
    return x is not None

list_optional: list[Optional[int]] = [0, None, 1, None, 2]
generate_ints: Iterable[int] = filter(is_not_none, list_optional)
```
@github-actions

This comment has been minimized.

@Jasha10
Copy link
Contributor Author

Jasha10 commented Dec 29, 2021

It has been brought to my attention that this PR is related to issue #5661 and to PR #6140.

@Jasha10
Copy link
Contributor Author

Jasha10 commented Dec 29, 2021

It appears that the diff implemented in this PR is identical to that from #6140.

@JelleZijlstra
Copy link
Member

Interesting, maybe the latest mypy release fixed things. cc @sobolevn.

@sobolevn
Copy link
Member

Yes, this was my PR to mypy: python/mypy#11314 after our initial attempt: #6140

Copy link
Member

@sobolevn sobolevn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please attach a simple manual test to show that it is working?

stdlib/builtins.pyi Outdated Show resolved Hide resolved
@hauntsaninja
Copy link
Collaborator

Yup, #6140 has the correct overload order. I think that wasn't tested against mypy 0.930, so worth trying again.

@sobolevn
Copy link
Member

sobolevn commented Dec 29, 2021

Yup, #6140 has the correct overload order. I think that wasn't tested against mypy 0.930, so worth trying again.

Let's leave this to @Jasha10, this is their first contribution 🙂

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
@github-actions
Copy link
Contributor

Diff from mypy_primer, showing the effect of this PR on open source code:

ibis (https://github.com/ibis-project/ibis)
+ ibis/backends/csv/__init__.py:72: error: Argument 1 to "filter" has incompatible type "Callable[[Any], bool]"; expected "Callable[[Any], TypeGuard[bool]]"
+ ibis/backends/csv/__init__.py:78: error: "bool" has no attribute "name"
+ ibis/backends/csv/__init__.py:82: error: "bool" has no attribute "schema"
+ ibis/backends/csv/__init__.py:91: error: "bool" has no attribute "schema"
+ ibis/backends/csv/__init__.py:92: error: Dict entry 0 has incompatible type "bool": "Any"; expected "Node": "Any"

@AlexWaygood
Copy link
Member

AlexWaygood commented Dec 30, 2021

Diff from mypy_primer, showing the effect of this PR on open source code:

ibis (https://github.com/ibis-project/ibis)
+ ibis/backends/csv/__init__.py:72: error: Argument 1 to "filter" has incompatible type "Callable[[Any], bool]"; expected "Callable[[Any], TypeGuard[bool]]"
+ ibis/backends/csv/__init__.py:78: error: "bool" has no attribute "name"
+ ibis/backends/csv/__init__.py:82: error: "bool" has no attribute "schema"
+ ibis/backends/csv/__init__.py:91: error: "bool" has no attribute "schema"
+ ibis/backends/csv/__init__.py:92: error: Dict entry 0 has incompatible type "bool": "Any"; expected "Node": "Any"

Huh, that's weird. I'm guessing mypy is failing to fall back to the third overload due to some strange bool/TypeGuard subtyping behaviour.

@sobolevn
Copy link
Member

This one is the most strange: Argument 1 to "filter" has incompatible type "Callable[[Any], bool]"; expected "Callable[[Any], TypeGuard[bool]]"

It should just continue with other overload (probably this one: def __init__(self, __function: Callable[[_T], Any], __iterable: Iterable[_T]) -> None: ...). Why does it error?

I will take a look into mypy itself 👍

@sobolevn
Copy link
Member

I am unable to reproduce this locally.
All my regular examples work as intended. But, I am using master branch, not 0.930

@JelleZijlstra
Copy link
Member

Going to merge this since the change is correct and mostly works with mypy. If it does expose a mypy bug, that can be tracked over on the mypy repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants