From d87a08ca52dfd2d21f50785ca6395ccc7aaf985f Mon Sep 17 00:00:00 2001 From: shrewd-laidback palace Date: Fri, 8 May 2026 10:40:27 +0200 Subject: [PATCH] Fix IMAP4WithTimeout compatibility with Python 3.14 Python 3.14 changed imaplib.IMAP4.file from a plain instance attribute to a read-only property (see cpython commit introducing the change). The open() override in IMAP4WithTimeout assigned to self.file directly, which now raises: AttributeError: property 'file' of 'IMAP4WithTimeout' object has no setter The fix mirrors what was already done for IMAP4_TLS in commit 64250b0: remove the open() override entirely and instead pass the timeout through to the parent __init__, which calls open() itself using self._file internally. The _create_socket override is kept as-is so the stored self._timeout fallback still applies for any call path that omits an explicit timeout. Fixes #638 --- imapclient/imap4.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/imapclient/imap4.py b/imapclient/imap4.py index d07515ec..92ff6075 100644 --- a/imapclient/imap4.py +++ b/imapclient/imap4.py @@ -10,16 +10,7 @@ class IMAP4WithTimeout(imaplib.IMAP4): def __init__(self, address: str, port: int, timeout: Optional[float]) -> None: self._timeout = timeout - imaplib.IMAP4.__init__(self, address, port) - - def open( - self, host: str = "", port: int = 143, timeout: Optional[float] = None - ) -> None: - # This is overridden to make it consistent across Python versions. - self.host = host - self.port = port - self.sock = self._create_socket(timeout) - self.file = self.sock.makefile("rb") + imaplib.IMAP4.__init__(self, address, port, timeout=timeout) def _create_socket(self, timeout: Optional[float] = None) -> socket.socket: return socket.create_connection(