typeshed
typeshed copied to clipboard
OSError stubs don't match actual types for TimeoutError subclass
OSError is currently stubbed as:
class OSError(Exception):
errno: int
strerror: str
# filename, filename2 are actually str | bytes | None
filename: Any
filename2: Any
if sys.platform == "win32":
winerror: int
The CPython TimeoutError subclass of it returned by socket functions will sometimes have errno and strerror None depending on which underlying syscall detected the timeout (select() reporting 0 sockets ready vs something failing with ETIMEDOUT)
Example:
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(0.1)
try:
# Try to connect to a host that doesn't exist on your
# network
s.connect(("10.10.10.10", 22))
except OSError as ex:
print(repr(ex))
print(f"errno is {type(ex.errno)} - {ex.errno}")
print(f"strerror is {type(ex.strerror)} - {ex.strerror}")
produces
TimeoutError('timed out')
errno is <class 'NoneType'> - None
strerror is <class 'NoneType'> - None
on
Python 3.10.9 | packaged by conda-forge | (main, Feb 2 2023, 20:14:58) [MSC v.1929 64 bit (AMD64)]
The CPython implementation looks like it would do the same on all platforms
(@srittau 2024-09-02) Deferred until python/cpython#109601 and python/cpython#109714 are decided on.
Interesting -- the docs pretty clearly imply that errno and strerror should always be (respectively) int and str for OSError: https://docs.python.org/3/library/exceptions.html#OSError. And there's nothing in the docs for TimeoutError to suggest that the types for these attributes on the subclass should be any different: https://docs.python.org/3/library/exceptions.html#TimeoutError.
I wonder if this is a bug in CPython (or, at the very least, a bug in the CPython docs for OSError/TimeoutError?).
@AlexWaygood
According to https://docs.python.org/3/library/exceptions.html#TimeoutError and the corresponding errno https://docs.python.org/3/library/errno.html#errno.ETIMEDOUT should by default have a value, so on Linux 110 and on Windows 138 if I'm not wrong.
I'll open an issue in CPython repo with reference to this to see if this is an docs issue or implementation in CPython.
I've marked this as deferred for now, pending the outcome of python/cpython#109601 and python/cpython#109714.
Any change in CPython would almost certainly apply only to 3.14, so we may still want to change the types in typeshed for earlier versions.
That makes sense. Based on the PR I think it's not only the TimeoutError and other subclasses of OSError could be like this.
Do we want to change all of them or just TimeoutError? This could be coming from different places so I'm not sure how to decide this.
While we could try an exploratory PR, I suspect that adding None will be very disruptive.