You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Sep 3, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Sep 3, 2026. It is now read-only.
How are annotations that are not types treated? #1451
reject it as in simply raise an error saying that foo(False) is not a type? yeah, pytype probably should do that too - don't count on it as a guarantee. (pytype's general philosophy is to be lenient towards things that are technically wrong but used frequently in existing code, and gradually add stricter checks; this lets projects adopt pytype without having to fix hundreds of issues in currently common practices)
Might help if I explain my use case. I'm frequently writing bindings to another language that also has classes. It's useful to me to be able to express this with the class and annotation syntax. I can write out directly in Python what the class from the other lang looks like:
@make_bindingclassExample:
x: lang_inty: lang_str
However occasionally figuring out what the type should be needs to involve some logic and processing of input files. This means I can't always just write a known type directly into the source code. I may want to write something like:
This can happen because of things like C enum types where the underlying integer width depends on how many elements there are. Similarly it would be nice to be able to write
Official PEP 484 annotations aren't supposed to contain anything other than types, this the need for Literal, but CPython can be made to accept the above either with the annotations future import or having lang_array be a class with a metaclass that defines __getitem__.
I'd also be happy to use no_type_checking_decorator on make_binding but alas none of the major checkers seem to respect it.
this sounds like something typing.Annotated would work well for. you could e.g. say z: Annotated[Any, determine_z_type] and your runtime code would be responsible for pulling the value out and using it but the typecheckers would ignore it.
In [1]: from typing import Annotated, Any
In [2]: def f(x): return int if x else str
In [3]: class A:
...: x: Annotated[Any, f(True)]
...:
In [4]: A.__annotations__
Out[4]: {'x': typing.Annotated[typing.Any, <class 'int'>]}
ifTYPE_CHECKING:
# what you want type checkers to thinklang_int=intlang_str=strlang_z=intelse:
# what you need for your bindingslang_int= ?
lang_str= ?
lang_z=determine_z_type()
@make_bindingclassExample:
x: lang_inty: lang_strz: lang_z
You can put the if almost anywhere, but it might be the easiest to have it in one/few places and define aliases that you can use for multiple struct definitions. If you really don't care about type checking at all, you can make all these types alias to Any when TYPE_CHECKING is true.
If you want more help from type checkers, you can always cheat less. For example, for enums, you can define python Enums or IntEnums to mirror your C enums and use them in the type annotations. Your code will then determine the correct C type to use based on the members of the python enum type. For fixed-size arrays you can use Annotated or a generic class with Literal, depending on what type you want to use in python. But the point is, you can mix and match more precise types with cheating as you like.
@eltoder that's a good hack, thanks. It's still too onerous for users of my decorator though, they would have to make up an identifier and do that check every time they wanted an expression.
Hi, thank you for your report. Google is shifting its effort to a different approach for type checking apart from pytype, and we're not planning to put in any effort in the near future in pytype, so we'll close this issue. Please see the announcement here.
Activity
martindemello commentedon Jun 27, 2023
the annotations are treated as
Anywhich does disable type checking for them.jgarvin commentedon Jun 27, 2023
As a user can I count on this being the behavior going forward? I'm hesitant because mypy and pyright both reject it.
martindemello commentedon Jun 27, 2023
reject it as in simply raise an error saying that
foo(False)is not a type? yeah, pytype probably should do that too - don't count on it as a guarantee. (pytype's general philosophy is to be lenient towards things that are technically wrong but used frequently in existing code, and gradually add stricter checks; this lets projects adopt pytype without having to fix hundreds of issues in currently common practices)jgarvin commentedon Jun 28, 2023
Might help if I explain my use case. I'm frequently writing bindings to another language that also has classes. It's useful to me to be able to express this with the class and annotation syntax. I can write out directly in Python what the class from the other lang looks like:
However occasionally figuring out what the type should be needs to involve some logic and processing of input files. This means I can't always just write a known type directly into the source code. I may want to write something like:
This can happen because of things like C enum types where the underlying integer width depends on how many elements there are. Similarly it would be nice to be able to write
Official PEP 484 annotations aren't supposed to contain anything other than types, this the need for
Literal, but CPython can be made to accept the above either with the annotations future import or having lang_array be a class with a metaclass that defines__getitem__.I'd also be happy to use
no_type_checking_decoratoronmake_bindingbut alas none of the major checkers seem to respect it.martindemello commentedon Jun 28, 2023
this sounds like something
typing.Annotatedwould work well for. you could e.g. sayz: Annotated[Any, determine_z_type]and your runtime code would be responsible for pulling the value out and using it but the typecheckers would ignore it.martindemello commentedon Jun 28, 2023
jgarvin commentedon Jun 28, 2023
That might be the best option, it's just significantly worse ergonomically. :(
eltoder commentedon Jul 18, 2023
@jgarvin You can cheat using
TYPE_CHECKING:You can put the if almost anywhere, but it might be the easiest to have it in one/few places and define aliases that you can use for multiple struct definitions. If you really don't care about type checking at all, you can make all these types alias to
AnywhenTYPE_CHECKINGis true.If you want more help from type checkers, you can always cheat less. For example, for enums, you can define python Enums or IntEnums to mirror your C enums and use them in the type annotations. Your code will then determine the correct C type to use based on the members of the python enum type. For fixed-size arrays you can use
Annotatedor a generic class withLiteral, depending on what type you want to use in python. But the point is, you can mix and match more precise types with cheating as you like.jgarvin commentedon Jul 18, 2023
@eltoder that's a good hack, thanks. It's still too onerous for users of my decorator though, they would have to make up an identifier and do that check every time they wanted an expression.
h-joo commentedon Aug 20, 2025
Hi, thank you for your report. Google is shifting its effort to a different approach for type checking apart from pytype, and we're not planning to put in any effort in the near future in pytype, so we'll close this issue. Please see the announcement here.