-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
__match_args__ annotations #5402
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
Comments
I feel like the closest precedent is |
Pyright currently supports all of the following forms within type stubs: __match_args__: Final[Tuple[Literal["left"], Literal["op"], Literal["right"]]]
__match_args__: Tuple[Literal["left"], Literal["op"], Literal["right"]]
__match_args__: Final = ("left", "op", "right")
__match_args__ = ("left", "op", "right") It does not support lists because type inference of list expressions doesn't preserve types of individual elements within the list. (I tried to convince Guido that I realize that your question was specifically focused on type stub files. We also need to consider inlined types in a "py.typed" library. Pyright implements some very specific rules about where it will and won't infer types in a "py.typed" source (".py") file. Inference is used very sparingly for several reasons documented here. These rules, as currently implemented, would require an explicit type annotation (such as |
PEP 634 actually specifies that |
@JelleZijlstra Non-final match args are useless for type checkers, because we can not know if they will be changed at runtime. You could just assume them to be unchanged, but that is obviously unsave. Match args could be made implicitly final, but I feel like that can lead to a lot of confusion and would be inconsistent even with |
This change was made last month: python/peps#1909 |
Ah, that's great to hear. I guess my feedback didn't come in too late to influence the spec. You just made my day. :) |
That just feels overly pedantic to me. There are several other magical attributes that would influence the type checker (e.g., |
I could later lift that restriction if consensus is that it's not needed.
|
Having mypy infer For non- Lines 31 to 34 in 55eb19d
While for typeshed/stdlib/os/__init__.pyi Lines 450 to 463 in 55eb19d
And here's how mypy infers the types on 0.961: from ast import TypeIgnore
from os import uname_result
reveal_type(TypeIgnore.__match_args__) # Revealed type is "Tuple[Literal['lineno']?, Literal['tag']?]"
reveal_type(uname_result.__match_args__) # Revealed type is "Tuple[Literal['sysname']?, Literal['nodename']?, Literal['release']?, Literal['version']?, Literal['machine']?]"
TypeIgnore.__match_args__ = ('foo', 'bar') # error: Cannot assign to "__match_args__" https://mypy-play.net/?mypy=latest&python=3.10&gist=8f8033d871b64b21e5ba9a8cb570cd04 |
Python 3.10 adds the match statement and with it adds the
__match_args__
attribute to some classes.To statically check class patterns in match statements the value of that attribute must be statically known.
I'm currently implementing match statement support for mypy and would like to hear some opinions on how
__match_args__
should be annotated.Let's take
ast.BinOp
as an example. It's__match_args__
is('left', 'op', 'right')
.One option to annotate it would be
That is however very verbose and not easy to read. Mypy can also deal with annotations in the form of
, inferring that the strings must be literal. This approach is much easier to read, but might be harder for type checkers to support and breaks with established typeshed conventions.
I would like to hear some opinions on those two approaches and other suggestions, especially from developers of the other type checkers.
A second point of discussion would be actually adding the annotations. In theory they could be added by hand, however that would be a lot of work. Ideally a program could be written to look up the match args at runtime and automatically add them to the stubs.
People who might be interested in this:
@erictraut
The text was updated successfully, but these errors were encountered: