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

Narrow x is Sentinel where x is Union[type[Sentinel], ...] and Sentinel is @final #15553

Open
jonathanslenders opened this issue Jun 29, 2023 · 2 comments · May be fixed by #15646
Open

Narrow x is Sentinel where x is Union[type[Sentinel], ...] and Sentinel is @final #15553

jonathanslenders opened this issue Jun 29, 2023 · 2 comments · May be fixed by #15646
Labels
feature topic-final PEP 591 topic-type-narrowing Conditional type narrowing / binder

Comments

@jonathanslenders
Copy link

jonathanslenders commented Jun 29, 2023

Feature

Apply type narrowing in case of x is not C where x is of type Union[type[C], SomethingElse], from that union to SomethingElse in case when C is made final.

If C is final, then C is the only possible value that satisfies the type type[C]. So, if we compare identity, that means we can narrow the type in either direction.

Pitch

Empty class definitions are often used as sentinel values in a union, together with something else. These sentinel values can be made @final.

Consider this code:

from typing import final, Union, Literal

@final
class Sentinel:
    pass

x: Union[type[Sentinel], int]

if x is Sentinel:
    pass
else:
    # Should be `int`
    # But is: "Union[Type[x.Sentinel], builtins.int]"
    reveal_type(x)

An example can be found in the h11 library:
https://github.com/python-hyper/h11/blob/cdccbeff44a39426b58010eb454a75015ec6f8bc/h11/_connection.py#L426

    def next_event(self) -> Union[Event, Type[NEED_DATA], Type[PAUSED]]:

Many libraries are doing that. A workaround that currently works is to use instantiated objects instead of types for sentinel values and narrow them by using an isinstance() check on the sentinel type, but that's far less clean, because for every sentinel we now have to deal with both the class and the instance.

@jonathanslenders jonathanslenders changed the title is based type narrowing of x is (not) C where x is Union[type[C], ...] and C is @final Narrow x is Sentinel where x is Union[type[Sentinel], ...] and Sentinel is @final Jun 29, 2023
@AlexWaygood AlexWaygood added topic-type-narrowing Conditional type narrowing / binder topic-final PEP 591 labels Jun 30, 2023
@sobolevn
Copy link
Member

I have a prototype ready :)

@jonathanslenders
Copy link
Author

Thank you @sobolevn!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature topic-final PEP 591 topic-type-narrowing Conditional type narrowing / binder
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants