python / mypy

Optional static typing for Python
https://www.mypy-lang.org/
Other
18.53k stars 2.83k forks source link

False negative: `Literal[Ellipsis]` #18175

Closed smurfix closed 17 hours ago

smurfix commented 1 day ago

Bug Report

Empty classes and similar types (e.g. Ellipsis) are often used as placeholders for an uber-None parameter, thus they should be allowed in Literal[…]. Currently they are not.

To Reproduce

from typing import Literal,Any
class NotGiven:
    pass
def fn(x:int|None|Literal[NotGiven]=NotGiven) -> Any:
    return 42
print(fn())

or

from typing import Literal,Any
def fn(x:int|None|Literal[Ellipsis]=...) -> Any:
    ...

Expected Behavior

No error.

Actual Behavior

/tmp/tt.py:4: error: Parameter 1 of Literal[...] is invalid [valid-type]

Your Environment

erictraut commented 1 day ago

The behavior you're suggesting here is not allowed by the Python typing spec currently. Mypy is correct to flag this as an error.

If you would like to propose an extension or amendment to the typing spec, you are welcome to follow the steps outlined here. There is already a draft PEP relating to sentinel values that is quite far along. It would cover your NotGiven use case. It wouldn't cover Ellipsis. However, the following is accepted by type checkers (requires Python 3.10 and newer):

from types import EllipsisType

def fn(x: int | None | EllipsisType = ...) -> None: ...
smurfix commented 1 day ago

Ah. Thank you, I was not aware of these issues.

As the PEP seems to be reasonably far along, is there an effort to teach mypy about it?

JelleZijlstra commented 17 hours ago

There is no effort that I know of for supporting PEP 661 in mypy. It may be better to wait for a decision on the PEP.