-
-
Notifications
You must be signed in to change notification settings - Fork 31.9k
Discrepancy between __args__
of typing.Callable
and collections.abc.Callable
#103452
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
Oh no 🔥 🚒 😆 |
This is not about >>> import typing
>>> list[None].__args__
(None,)
>>> typing.List[None].__args__
(<class 'NoneType'>,)
>>> set[None]
set[None]
>>> typing.Set[None]
typing.Set[NoneType] |
Problem is here: Lines 160 to 166 in 9666387
|
So, we can roughly delete this two lines from >>> import typing, collections.abc
>>> Ts = typing.TypeVarTuple("Ts")
>>> typing.Callable[[*Ts], None].__args__
(*Ts, None)
>>> collections.abc.Callable[[*Ts], None].__args__
(*Ts, None) |
No, it is not a problem :) The problem is in |
@sobolevn is correct. The objects in But the fact that all |
__args__
of typing.Callable
and collections.abc.Callable
__args__
of typing.Callable
and collections.abc.Callable
The behavior is specified here: https://peps.python.org/pep-0484/#using-none
https://peps.python.org/pep-0483/#pragmatics
https://peps.python.org/pep-0483/#fundamental-building-blocks
But I do not find any wording about This sounds like a bug to me. I think the correct behavior here is to make collections.abc.Callable[[*Ts], None] == collections.abc.Callable[[*Ts], type(None)] evaluates to Perhaps a PEP is needed to resolve this? |
Fwiw as the one who wrote the original test, I don't have a strong opinion about this - I don't think there's anything about the way that My personal vote is that it should be I do agree with @sunmy2019 that it seems correct for this to be the case: collections.abc.Callable[[*Ts], None] == collections.abc.Callable[[*Ts], type(None)] But I'd expect that to be true because >>> None is type(None)
False
>>> None == type(None)
False This seems super weird to me considering that those PEPs @sunmy2019 is quoting explicitly says they should be equivalent. How difficult would this be to change? |
It is not hard at all, but this is breaking change. We have Python 3.9.15 (main, Nov 22 2022, 17:18:20)
[Clang 11.0.0 (clang-1100.0.33.16)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> list[None].__args__[0]
>>> import typing
>>> typing.List[None].__args__[0]
<class 'NoneType'> I am pretty sure many libraries rely on this. I've tried >>> from pydantic import BaseModel
>>> class My(BaseModel):
... x: list[None]
...
>>> import types
>>> class Other(BaseModel):
... y: list[types.NoneType]
...
>>> My(x=[None])
My(x=[None])
>>> My(x=[type(None)])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pydantic/main.py", line 341, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for My
x -> 0
value is not None (type=type_error.not_none)
>>> Other(y=[None])
Other(y=[None])
>>> Other(y=[type(None)])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "pydantic/main.py", line 341, in pydantic.main.BaseModel.__init__
pydantic.error_wrappers.ValidationError: 1 validation error for Other
y -> 0
value is not None (type=type_error.not_none) Looks like this exact lib handles |
Found this in their code
|
I am a little bit in favor of So, I think either way is acceptable. |
Funny timing as I recently had some runtime type manipulation code run into this None vs NoneType with annotations past week. I'm fairly neutral as to whether get_type_hints converts None -> NoneType or not. It is one special case rules that's very easy to miss and debug much later. I suspect a fair number of runtime type libraries have some special case for NoneType (or should). I do not want to backport any change related to this though. If 3.12/13 wants to change None/NoneType special casing sure. I don't want to worry about sys.version on patch version and which behavior is right feels very unclear to me. |
This seems like an obvious omission/oversight in >>> typing.get_args(dict[str, None])
(<class 'str'>, None) Moreover, the equality is broken as well
|
I agree that It is usually expected to find Version 3.9 introduced This behavior of However, not only The same goes for dataclasses: So even if If there is an intent to unify the behavior of converting |
I feel strongly that we should not make I know we do processing like |
I concur with @JelleZijlstra. The discrepancy here is unfortunate, but the behaviour of I'm not sure what, if anything, is really to be done here. |
On both Python 3.11 and
main
@ b57105a:According to this assertion in the test suite for
typing.py
, the behaviour oftyping.Callable
is correct here, whereas the behaviour ofcollections.abc.Callable
is incorrect:cpython/Lib/test/test_typing.py
Lines 1290 to 1292 in b57105a
However, the test is currently only run with
typing.Callable
, whereas it should be run withcollections.abc.Callable
as well.Cc. @mrahtz, who wrote this test. This may also be of interest to @sobolevn :)
The text was updated successfully, but these errors were encountered: