Repository navigation
Empty typing.Tuple #91137
Description
Activity
There are two empty typing.Tuple. They have the same repr but are not equal.
>>> from typing import * >>> t1 = Tuple[()] >>> t2 = t1.copy_with(()) >>> t1 typing.Tuple[()] >>> t2 typing.Tuple[()] >>> t1 == t2 False >>> t1.__args__ ((),) >>> t2.__args__ ()
The only differences is that one has empty __args__, while other has __args__ containing an empty tuple. There is a code purposed to make __args__ containing an empty tuple in this case. What is the purpose?
It is not pure theoretical question. This affects unpacked TypeVarTuple substitution. With natural implementation Tuple[Unpack[Ts]][()] is not equal to Tuple[()] and I still have not figured which and where code should be added to handle this special case. It would be easier if such special case did not exist.
Built-in tuple does not have a special case:
>>> tuple[()].__args__ ()
- addedstdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
on Mar 11, 2022 Alas, I have no idea. I don't even recall what copy_with() is for (it was apparently introduced in 3.7). Possibly vopy_with() is wrong here? I imaging some of this has to do with the special casing needed so that repr() of an empty Tuple type doesn't print "Tuple[]" (which IIRC it did, long ago).
If for repr(Tuple[()]), it is no longer needed.
I tried out 3.11 on my pyanalyze type checker and got some failures because of this change, because my previous trick for distinguishing between Tuple and Tuple[()] failed.
3.10:
>>> from typing import get_args, Tuple >>> get_args(Tuple[()]) ((),) >>> get_args(Tuple) ()
3.11:
>>> from typing import get_args, Tuple >>> get_args(Tuple[()]) () >>> get_args(Tuple) ()
However, the new behavior is more consistent: get_args(tuple[()]) always returned (). It's also easy enough to work around (just check
... is Tuple).I'll put a note in the What's New for 3.11 about this change.
We get a report about broken pickling of empty
typing.Tuple#94245. Shallow and deep copying are broken too.>>> copy.copy(Tuple[()]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/serhiy/py/cpython3.10/Lib/copy.py", line 102, in copy return _reconstruct(x, None, *rv) File "/home/serhiy/py/cpython3.10/Lib/copy.py", line 265, in _reconstruct y = func(*args) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 312, in inner return func(*args, **kwds) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 1233, in __getitem__ params = tuple(_type_check(p, msg) for p in params) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 1233, in <genexpr> params = tuple(_type_check(p, msg) for p in params) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 176, in _type_check raise TypeError(f"{msg} Got {arg!r:.100}.") TypeError: Tuple[t0, t1, ...]: each t must be a type. Got (). >>> copy.deepcopy(Tuple[()]) Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/home/serhiy/py/cpython3.10/Lib/copy.py", line 172, in deepcopy y = _reconstruct(x, memo, *rv) File "/home/serhiy/py/cpython3.10/Lib/copy.py", line 265, in _reconstruct y = func(*args) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 312, in inner return func(*args, **kwds) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 1233, in __getitem__ params = tuple(_type_check(p, msg) for p in params) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 1233, in <genexpr> params = tuple(_type_check(p, msg) for p in params) File "/home/serhiy/py/cpython3.10/Lib/typing.py", line 176, in _type_check raise TypeError(f"{msg} Got {arg!r:.100}.") TypeError: Tuple[t0, t1, ...]: each t must be a type. Got ().All this can be fixed by backporting this change. But it will break pyanalyze.
I was using python 3.10 and getting the same error while using Gemini-Pro-Vision.
This resolved my issue - pip install pydantic==1.10.13
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: