diff --git a/Doc/library/smtplib.rst b/Doc/library/smtplib.rst index 8f5ca0ac300..52220f7a7f3 100644 --- a/Doc/library/smtplib.rst +++ b/Doc/library/smtplib.rst @@ -32,7 +32,7 @@ Protocol) and :rfc:`1869` (SMTP Service Extensions). than a success code, an :exc:`SMTPConnectError` is raised. The optional *timeout* parameter specifies a timeout in seconds for blocking operations like the connection attempt (if not specified, the global default timeout - setting will be used). If the timeout expires, :exc:`socket.timeout` is + setting will be used). If the timeout expires, :exc:`TimeoutError` is raised. The optional source_address parameter allows binding to some specific source address in a machine with multiple network interfaces, and/or to some specific source TCP port. It takes a 2-tuple diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst index faf8a762514..d52b84f610e 100755 --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -283,6 +283,8 @@ Exceptions .. exception:: timeout + A deprecated alias of :exc:`TimeoutError`. + A subclass of :exc:`OSError`, this exception is raised when a timeout occurs on a socket which has had timeouts enabled via a prior call to :meth:`~socket.settimeout` (or implicitly through @@ -292,6 +294,9 @@ Exceptions .. versionchanged:: 3.3 This class was made a subclass of :exc:`OSError`. + .. versionchanged:: 3.10 + This class was made an alias of :exc:`TimeoutError`. + Constants ^^^^^^^^^ @@ -1208,7 +1213,7 @@ to sockets. address family --- see above.) If the connection is interrupted by a signal, the method waits until the - connection completes, or raise a :exc:`socket.timeout` on timeout, if the + connection completes, or raise a :exc:`TimeoutError` on timeout, if the signal handler doesn't raise an exception and the socket is blocking or has a timeout. For non-blocking sockets, the method raises an :exc:`InterruptedError` exception if the connection is interrupted by a diff --git a/Doc/whatsnew/3.10.rst b/Doc/whatsnew/3.10.rst index ad0ec4def0b..826d12704a1 100644 --- a/Doc/whatsnew/3.10.rst +++ b/Doc/whatsnew/3.10.rst @@ -263,6 +263,12 @@ site When a module does not define ``__loader__``, fall back to ``__spec__.loader``. (Contributed by Brett Cannon in :issue:`42133`.) +socket +------ + +The exception :exc:`socket.timeout` is now an alias of :exc:`TimeoutError`. +(Contributed by Christian Heimes in :issue:`42413`.) + sys --- diff --git a/Lib/http/server.py b/Lib/http/server.py index fa204fbc15e..ee991821099 100644 --- a/Lib/http/server.py +++ b/Lib/http/server.py @@ -414,7 +414,7 @@ class BaseHTTPRequestHandler(socketserver.StreamRequestHandler): method = getattr(self, mname) method() self.wfile.flush() #actually send the response if not already done. - except socket.timeout as e: + except TimeoutError as e: #a read or a write timed out. Discard this connection self.log_error("Request timed out: %r", e) self.close_connection = True diff --git a/Lib/idlelib/pyshell.py b/Lib/idlelib/pyshell.py index b69916dbe87..343d2ef32d7 100755 --- a/Lib/idlelib/pyshell.py +++ b/Lib/idlelib/pyshell.py @@ -463,7 +463,7 @@ class ModifiedInterpreter(InteractiveInterpreter): self.rpcclt.listening_sock.settimeout(10) try: self.rpcclt.accept() - except socket.timeout: + except TimeoutError: self.display_no_subprocess_error() return None self.rpcclt.register("console", self.tkconsole) @@ -498,7 +498,7 @@ class ModifiedInterpreter(InteractiveInterpreter): self.spawn_subprocess() try: self.rpcclt.accept() - except socket.timeout: + except TimeoutError: self.display_no_subprocess_error() return None self.transfer_path(with_cwd=with_cwd) diff --git a/Lib/socket.py b/Lib/socket.py index cafa573a30c..54a38078760 100755 --- a/Lib/socket.py +++ b/Lib/socket.py @@ -377,7 +377,7 @@ class socket(_socket.socket): try: while True: if timeout and not selector_select(timeout): - raise _socket.timeout('timed out') + raise TimeoutError('timed out') if count: blocksize = count - total_sent if blocksize <= 0: diff --git a/Lib/test/support/socket_helper.py b/Lib/test/support/socket_helper.py index 7070c12c253..e78712b74b1 100644 --- a/Lib/test/support/socket_helper.py +++ b/Lib/test/support/socket_helper.py @@ -225,7 +225,7 @@ def transient_internet(resource_name, *, timeout=_NOT_SET, errnos=()): def filter_error(err): n = getattr(err, 'errno', None) - if (isinstance(err, socket.timeout) or + if (isinstance(err, TimeoutError) or (isinstance(err, socket.gaierror) and n in gai_errnos) or (isinstance(err, urllib.error.HTTPError) and 500 <= err.code <= 599) or diff --git a/Lib/test/test_asyncio/functional.py b/Lib/test/test_asyncio/functional.py index 5cd0659387d..74490a869de 100644 --- a/Lib/test/test_asyncio/functional.py +++ b/Lib/test/test_asyncio/functional.py @@ -248,7 +248,7 @@ class TestThreadedServer(SocketThread): conn, addr = self._sock.accept() except BlockingIOError: continue - except socket.timeout: + except TimeoutError: if not self._active: return else: diff --git a/Lib/test/test_asyncore.py b/Lib/test/test_asyncore.py index 06c6bc2e99d..3bd904d1774 100644 --- a/Lib/test/test_asyncore.py +++ b/Lib/test/test_asyncore.py @@ -69,7 +69,7 @@ def capture_server(evt, buf, serv): try: serv.listen() conn, addr = serv.accept() - except socket.timeout: + except TimeoutError: pass else: n = 200 diff --git a/Lib/test/test_exception_hierarchy.py b/Lib/test/test_exception_hierarchy.py index 43b4af84039..89fe9ddcefb 100644 --- a/Lib/test/test_exception_hierarchy.py +++ b/Lib/test/test_exception_hierarchy.py @@ -40,10 +40,10 @@ class HierarchyTest(unittest.TestCase): self.assertIs(EnvironmentError, OSError) def test_socket_errors(self): - self.assertIs(socket.error, IOError) + self.assertIs(socket.error, OSError) self.assertIs(socket.gaierror.__base__, OSError) self.assertIs(socket.herror.__base__, OSError) - self.assertIs(socket.timeout.__base__, OSError) + self.assertIs(socket.timeout, TimeoutError) def test_select_error(self): self.assertIs(select.error, OSError) diff --git a/Lib/test/test_ftplib.py b/Lib/test/test_ftplib.py index 39658f22aa1..2424911c7ac 100644 --- a/Lib/test/test_ftplib.py +++ b/Lib/test/test_ftplib.py @@ -1036,7 +1036,7 @@ class TestTimeouts(TestCase): self.evt.set() try: conn, addr = self.sock.accept() - except socket.timeout: + except TimeoutError: pass else: conn.sendall(b"1 Hola mundo\n") diff --git a/Lib/test/test_imaplib.py b/Lib/test/test_imaplib.py index 96bcb09261e..0cab7897a96 100644 --- a/Lib/test/test_imaplib.py +++ b/Lib/test/test_imaplib.py @@ -476,7 +476,7 @@ class NewIMAPTestsMixin(): _, server = self._setup(TimeoutHandler) addr = server.server_address[1] - with self.assertRaises(socket.timeout): + with self.assertRaises(TimeoutError): client = self.imap_class("localhost", addr, timeout=0.001) def test_with_statement(self): diff --git a/Lib/test/test_poplib.py b/Lib/test/test_poplib.py index 2ac345ddd68..548868362a3 100644 --- a/Lib/test/test_poplib.py +++ b/Lib/test/test_poplib.py @@ -501,7 +501,7 @@ class TestTimeouts(TestCase): conn, addr = serv.accept() conn.send(b"+ Hola mundo\n") conn.close() - except socket.timeout: + except TimeoutError: pass finally: serv.close() diff --git a/Lib/test/test_signal.py b/Lib/test/test_signal.py index c6567906321..5a8ff361f96 100644 --- a/Lib/test/test_signal.py +++ b/Lib/test/test_signal.py @@ -528,7 +528,7 @@ class WakeupSocketSignalTests(unittest.TestCase): while True: write.send(chunk) written += chunk_size - except (BlockingIOError, socket.timeout): + except (BlockingIOError, TimeoutError): pass print(f"%s bytes written into the socketpair" % written, flush=True) diff --git a/Lib/test/test_smtplib.py b/Lib/test/test_smtplib.py index 7816ed34886..91985384ec7 100644 --- a/Lib/test/test_smtplib.py +++ b/Lib/test/test_smtplib.py @@ -40,7 +40,7 @@ def server(evt, buf, serv): evt.set() try: conn, addr = serv.accept() - except socket.timeout: + except TimeoutError: pass else: n = 500 @@ -193,7 +193,7 @@ def debugging_server(serv, serv_evt, client_evt): n -= 1 - except socket.timeout: + except TimeoutError: pass finally: if not client_evt.is_set(): diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 80638325ba3..5f57ab2f89d 100755 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -1611,7 +1611,7 @@ class GeneralModuleTests(unittest.TestCase): if with_timeout: signal.signal(signal.SIGALRM, ok_handler) signal.alarm(1) - self.assertRaises(socket.timeout, c.sendall, + self.assertRaises(TimeoutError, c.sendall, b"x" * support.SOCK_MAX_SIZE) finally: signal.alarm(0) @@ -2966,7 +2966,7 @@ class SendmsgStreamTests(SendmsgTests): try: while True: self.sendmsgToServer([b"a"*512]) - except socket.timeout: + except TimeoutError: pass except OSError as exc: if exc.errno != errno.ENOMEM: @@ -2974,7 +2974,7 @@ class SendmsgStreamTests(SendmsgTests): # bpo-33937 the test randomly fails on Travis CI with # "OSError: [Errno 12] Cannot allocate memory" else: - self.fail("socket.timeout not raised") + self.fail("TimeoutError not raised") finally: self.misc_event.set() @@ -3109,7 +3109,7 @@ class RecvmsgGenericTests(SendrecvmsgBase): # Check that timeout works. try: self.serv_sock.settimeout(0.03) - self.assertRaises(socket.timeout, + self.assertRaises(TimeoutError, self.doRecvmsg, self.serv_sock, len(MSG)) finally: self.misc_event.set() @@ -4827,7 +4827,7 @@ class FileObjectClassTestCase(SocketConnectedTest): self.cli_conn.settimeout(1) self.read_file.read(3) # First read raises a timeout - self.assertRaises(socket.timeout, self.read_file.read, 1) + self.assertRaises(TimeoutError, self.read_file.read, 1) # Second read is disallowed with self.assertRaises(OSError) as ctx: self.read_file.read(1) @@ -5092,7 +5092,7 @@ class NetworkConnectionNoServer(unittest.TestCase): class MockSocket(socket.socket): def connect(self, *args): - raise socket.timeout('timed out') + raise TimeoutError('timed out') @contextlib.contextmanager def mocked_socket_module(self): @@ -5142,13 +5142,13 @@ class NetworkConnectionNoServer(unittest.TestCase): with self.mocked_socket_module(): try: socket.create_connection((HOST, 1234)) - except socket.timeout: + except TimeoutError: pass except OSError as exc: if socket_helper.IPV6_ENABLED or exc.errno != errno.EAFNOSUPPORT: raise else: - self.fail('socket.timeout not raised') + self.fail('TimeoutError not raised') class NetworkConnectionAttributesTest(SocketTCPTest, ThreadableTest): @@ -5250,7 +5250,7 @@ class NetworkConnectionBehaviourTest(SocketTCPTest, ThreadableTest): def _testOutsideTimeout(self): self.cli = sock = socket.create_connection((HOST, self.port), timeout=1) - self.assertRaises(socket.timeout, lambda: sock.recv(5)) + self.assertRaises(TimeoutError, lambda: sock.recv(5)) class TCPTimeoutTest(SocketTCPTest): @@ -5259,7 +5259,7 @@ class TCPTimeoutTest(SocketTCPTest): def raise_timeout(*args, **kwargs): self.serv.settimeout(1.0) self.serv.accept() - self.assertRaises(socket.timeout, raise_timeout, + self.assertRaises(TimeoutError, raise_timeout, "Error generating a timeout exception (TCP)") def testTimeoutZero(self): @@ -5267,7 +5267,7 @@ class TCPTimeoutTest(SocketTCPTest): try: self.serv.settimeout(0.0) foo = self.serv.accept() - except socket.timeout: + except TimeoutError: self.fail("caught timeout instead of error (TCP)") except OSError: ok = True @@ -5292,7 +5292,7 @@ class TCPTimeoutTest(SocketTCPTest): try: signal.alarm(2) # POSIX allows alarm to be up to 1 second early foo = self.serv.accept() - except socket.timeout: + except TimeoutError: self.fail("caught timeout instead of Alarm") except Alarm: pass @@ -5316,7 +5316,7 @@ class UDPTimeoutTest(SocketUDPTest): def raise_timeout(*args, **kwargs): self.serv.settimeout(1.0) self.serv.recv(1024) - self.assertRaises(socket.timeout, raise_timeout, + self.assertRaises(TimeoutError, raise_timeout, "Error generating a timeout exception (UDP)") def testTimeoutZero(self): @@ -5324,7 +5324,7 @@ class UDPTimeoutTest(SocketUDPTest): try: self.serv.settimeout(0.0) foo = self.serv.recv(1024) - except socket.timeout: + except TimeoutError: self.fail("caught timeout instead of error (UDP)") except OSError: ok = True @@ -5341,7 +5341,7 @@ class UDPLITETimeoutTest(SocketUDPLITETest): def raise_timeout(*args, **kwargs): self.serv.settimeout(1.0) self.serv.recv(1024) - self.assertRaises(socket.timeout, raise_timeout, + self.assertRaises(TimeoutError, raise_timeout, "Error generating a timeout exception (UDPLITE)") def testTimeoutZero(self): @@ -5349,7 +5349,7 @@ class UDPLITETimeoutTest(SocketUDPLITETest): try: self.serv.settimeout(0.0) foo = self.serv.recv(1024) - except socket.timeout: + except TimeoutError: self.fail("caught timeout instead of error (UDPLITE)") except OSError: ok = True @@ -5365,6 +5365,8 @@ class TestExceptions(unittest.TestCase): self.assertTrue(issubclass(socket.herror, OSError)) self.assertTrue(issubclass(socket.gaierror, OSError)) self.assertTrue(issubclass(socket.timeout, OSError)) + self.assertIs(socket.error, OSError) + self.assertIs(socket.timeout, TimeoutError) def test_setblocking_invalidfd(self): # Regression test for issue #28471 @@ -6167,7 +6169,7 @@ class SendfileUsingSendTest(ThreadedTCPSocketTest): with socket.create_connection(address) as sock: sock.settimeout(0.01) meth = self.meth_from_sock(sock) - self.assertRaises(socket.timeout, meth, file) + self.assertRaises(TimeoutError, meth, file) def testWithTimeoutTriggeredSend(self): conn = self.accept_conn() diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py index 8744e597302..e5cd962e847 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -2574,7 +2574,7 @@ class ThreadedEchoServer(threading.Thread): handler = self.ConnectionHandler(self, newconn, connaddr) handler.start() handler.join() - except socket.timeout: + except TimeoutError: pass except KeyboardInterrupt: self.stop() @@ -3691,7 +3691,7 @@ class ThreadedTests(unittest.TestCase): c.settimeout(0.2) c.connect((host, port)) # Will attempt handshake and time out - self.assertRaisesRegex(socket.timeout, "timed out", + self.assertRaisesRegex(TimeoutError, "timed out", test_wrap_socket, c) finally: c.close() @@ -3700,7 +3700,7 @@ class ThreadedTests(unittest.TestCase): c = test_wrap_socket(c) c.settimeout(0.2) # Will attempt handshake and time out - self.assertRaisesRegex(socket.timeout, "timed out", + self.assertRaisesRegex(TimeoutError, "timed out", c.connect, (host, port)) finally: c.close() diff --git a/Lib/test/test_telnetlib.py b/Lib/test/test_telnetlib.py index 7633901c96c..8e36051cd09 100644 --- a/Lib/test/test_telnetlib.py +++ b/Lib/test/test_telnetlib.py @@ -16,7 +16,7 @@ def server(evt, serv): try: conn, addr = serv.accept() conn.close() - except socket.timeout: + except TimeoutError: pass finally: serv.close() diff --git a/Lib/test/test_timeout.py b/Lib/test/test_timeout.py index ac803f5d638..823d5c3e176 100644 --- a/Lib/test/test_timeout.py +++ b/Lib/test/test_timeout.py @@ -122,7 +122,7 @@ class TimeoutTestCase(unittest.TestCase): """ Test the specified socket method. - The method is run at most `count` times and must raise a socket.timeout + The method is run at most `count` times and must raise a TimeoutError within `timeout` + self.fuzz seconds. """ self.sock.settimeout(timeout) @@ -131,11 +131,11 @@ class TimeoutTestCase(unittest.TestCase): t1 = time.monotonic() try: method(*args) - except socket.timeout as e: + except TimeoutError as e: delta = time.monotonic() - t1 break else: - self.fail('socket.timeout was not raised') + self.fail('TimeoutError was not raised') # These checks should account for timing unprecision self.assertLess(delta, timeout + self.fuzz) self.assertGreater(delta, timeout - 1.0) @@ -204,7 +204,7 @@ class TCPTimeoutTestCase(TimeoutTestCase): sock.settimeout(timeout) try: sock.connect((whitehole)) - except socket.timeout: + except TimeoutError: pass except OSError as err: if err.errno == errno.ECONNREFUSED: diff --git a/Lib/test/test_urllib2net.py b/Lib/test/test_urllib2net.py index c1d55ee8b29..4750ad9600c 100644 --- a/Lib/test/test_urllib2net.py +++ b/Lib/test/test_urllib2net.py @@ -277,7 +277,7 @@ class OtherNetworkTests(unittest.TestCase): ioerror_peer_reset: buf = f.read() debug("read %d bytes" % len(buf)) - except socket.timeout: + except TimeoutError: print("" % url, file=sys.stderr) f.close() time.sleep(0.1) diff --git a/Lib/test/test_xmlrpc.py b/Lib/test/test_xmlrpc.py index 3dfa84bf77d..c54aeb10945 100644 --- a/Lib/test/test_xmlrpc.py +++ b/Lib/test/test_xmlrpc.py @@ -648,7 +648,7 @@ def http_server(evt, numrequests, requestHandler=None, encoding=None): serv.handle_request() numrequests -= 1 - except socket.timeout: + except TimeoutError: pass finally: serv.socket.close() @@ -713,7 +713,7 @@ def http_multi_server(evt, numrequests, requestHandler=None): serv.handle_request() numrequests -= 1 - except socket.timeout: + except TimeoutError: pass finally: serv.socket.close() diff --git a/Misc/NEWS.d/next/Library/2020-11-19-20-27-51.bpo-42413.fjHrHx.rst b/Misc/NEWS.d/next/Library/2020-11-19-20-27-51.bpo-42413.fjHrHx.rst new file mode 100644 index 00000000000..ef1bf0fe9d3 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2020-11-19-20-27-51.bpo-42413.fjHrHx.rst @@ -0,0 +1 @@ +The exception :exc:`socket.timeout` is now an alias of :exc:`TimeoutError`. diff --git a/Modules/_ssl.c b/Modules/_ssl.c index 54c365b88e6..a34313b7854 100644 --- a/Modules/_ssl.c +++ b/Modules/_ssl.c @@ -1102,7 +1102,7 @@ _ssl__SSLSocket_do_handshake_impl(PySSLSocket *self) } if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, ERRSTR("The handshake operation timed out")); goto error; } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { @@ -2419,7 +2419,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) sockstate = PySSL_select(sock, 1, timeout); if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The write operation timed out"); goto error; } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { @@ -2454,7 +2454,7 @@ _ssl__SSLSocket_write_impl(PySSLSocket *self, Py_buffer *b) } if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The write operation timed out"); goto error; } else if (sockstate == SOCKET_HAS_BEEN_CLOSED) { @@ -2609,7 +2609,7 @@ _ssl__SSLSocket_read_impl(PySSLSocket *self, int len, int group_right_1, sockstate = SOCKET_OPERATION_OK; if (sockstate == SOCKET_HAS_TIMED_OUT) { - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The read operation timed out"); goto error; } else if (sockstate == SOCKET_IS_NONBLOCKING) { @@ -2724,10 +2724,10 @@ _ssl__SSLSocket_shutdown_impl(PySSLSocket *self) if (sockstate == SOCKET_HAS_TIMED_OUT) { if (err.ssl == SSL_ERROR_WANT_READ) - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The read operation timed out"); else - PyErr_SetString(PySocketModule.timeout_error, + PyErr_SetString(PyExc_TimeoutError, "The write operation timed out"); goto error; } diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index d7738367029..f8e4de5825f 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -514,7 +514,6 @@ remove_unusable_flags(PyObject *m) by this module (but not argument type or memory errors, etc.). */ static PyObject *socket_herror; static PyObject *socket_gaierror; -static PyObject *socket_timeout; /* A forward reference to the socket type object. The sock_type variable contains pointers to various functions, @@ -886,7 +885,7 @@ sock_call_ex(PySocketSockObject *s, if (err) *err = SOCK_TIMEOUT_ERR; else - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(PyExc_TimeoutError, "timed out"); return -1; } @@ -2880,7 +2879,7 @@ sock_settimeout(PySocketSockObject *s, PyObject *arg) /* Blocking mode for a Python socket object means that operations like :meth:`recv` or :meth:`sendall` will block the execution of the current thread until they are complete or aborted with a - `socket.timeout` or `socket.error` errors. When timeout is `None`, + `TimeoutError` or `socket.error` errors. When timeout is `None`, the underlying FD is in a blocking mode. When timeout is a positive number, the FD is in a non-blocking mode, and socket ops are implemented with a `select()` call. @@ -4206,7 +4205,7 @@ sock_sendall(PySocketSockObject *s, PyObject *args) } if (interval <= 0) { - PyErr_SetString(socket_timeout, "timed out"); + PyErr_SetString(PyExc_TimeoutError, "timed out"); goto done; } } @@ -7123,13 +7122,10 @@ PyInit__socket(void) return NULL; Py_INCREF(socket_gaierror); PyModule_AddObject(m, "gaierror", socket_gaierror); - socket_timeout = PyErr_NewException("socket.timeout", - PyExc_OSError, NULL); - if (socket_timeout == NULL) - return NULL; - PySocketModuleAPI.timeout_error = socket_timeout; - Py_INCREF(socket_timeout); - PyModule_AddObject(m, "timeout", socket_timeout); + + PySocketModuleAPI.timeout_error = PyExc_TimeoutError; + PyModule_AddObjectRef(m, "timeout", PyExc_TimeoutError); + Py_INCREF((PyObject *)&sock_type); if (PyModule_AddObject(m, "SocketType", (PyObject *)&sock_type) != 0)