Unsoundness with `typing.IO` and friends
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 25/100
Research direction
Start by reviewing the runtime behavior of typing.IO, typing.BinaryIO, typing.TextIO, and io.BytesIO, along with their typeshed relationships and the linked CPython issue. Compare the three proposed approaches and document or implement an agreed specification and runtime direction; done requires resolving how isinstance() and issubclass() should behave.
Written by the indexing model from the issue text.
Description
The classes typing.IO, typing.BinaryIO, and typing.TextIO look like they want to be Protocols or ABCs, but in fact they are defined as regular generic classes, both at runtime and in typeshed. However, they are meant to encompass the concrete IO classes defined in the io module, and in typeshed we implement that by having these classes inherit from typing.*IO classes, even though there is no such inheritance at runtime.
This can easily lead to unsound behavior:
import io, typing
def f(x: int | io.BytesIO) -> int:
if isinstance(x, typing.BinaryIO):
return x.fileno()
return x
f(io.BytesIO()) + 1 # boom
Type checkers think BytesIO is a subclass of BinaryIO, because that's how it's defined in typeshed, but in fact it isn't at runtime.
I can see a few solutions:
- Special-case
typing.*IOin the spec and say that type checkers should rejectisinstance()/issubclass()calls involving them. - Deprecate the
typing.*IOclasses and eventually remove them, nudging people to use their own Protocols (or the newio.Reader/io.Writer) instead. This is conceptually clean but may be annoying for a lot of users; the typing classes are nice to use in simple application code. - Make these classes actually (runtime-checkable?) Protocols at runtime, though they would be unwieldily large.
Even if we do (2) or (3) type checkers might still want to do (1) since it will be a while before the relevant runtime changes take effect.
(Noticed this while looking into https://github.com/python/cpython/issues/133492 .)
- Dominant language
- Python
- Stars
- 1.8k
- Forks
- 302
- Avg merge
- 23h
- Merged PRs (30d)
- 8
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from python/typing
-
topic: typing spec
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
topic: typing spec
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
topic: documentation
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
topic: documentation
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
topic: conformance tests topic: typing spec
Difficulty 3/5 1-2 days Newbie friendliness 72/100
Similar issues
-
Add: hunch Open
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
AbdelStark/awesome-typesafe#104 ·
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
DiamondLightSource/dodal#2211 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
openml/openml-python#1749 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
sipyourdrink-ltd/bernstein#6191 ·