-
-
Notifications
You must be signed in to change notification settings - Fork 33.6k
Description
Bug report
Bug description:
In Python 3.14, imaplib.IMAP4.file was changed from a normal attribute to a read-only property.
This breaks legitimate subclassing patterns used by third-party libraries such as imapclient, which override open() and assign to self.file.
Example failure
Running imapclient’s IMAP4_TLS on Python 3.14 produces:
AttributeError: property 'file' of 'IMAP4_TLS' object has no setter
Regression cause
In Python 3.14, imaplib.IMAP4.file was changed to:
@property
def file(self):
# The old 'file' attribute is no longer used now that we do our own
# read() and readline() buffering, with which it conflicts.
# As an undocumented interface, it should never have been accessed by
# external code, and therefore does not warrant deprecation.
# Nevertheless, we provide this property for now, to avoid suddenly
# breaking any code in the wild that might have been using it in a
# harmless way.
import warnings
warnings.warn(
'IMAP4.file is unsupported, can cause errors, and may be removed.',
RuntimeWarning,
stacklevel=2)
return self._filewith no setter provided.
https://github.com/python/cpython/blob/3.14/Lib/imaplib.py#L319-L333
Prior to 3.14, file was a normal attribute and writable.
def open(self, host='', port=IMAP4_PORT, timeout=None):
"""Setup connection to remote server on "host:port"
(default: localhost:standard IMAP4 port).
This connection will be used by the routines:
read, readline, send, shutdown.
"""
self.host = host
self.port = port
self.sock = self._create_socket(timeout)
self.file = self.sock.makefile('rb')https://github.com/python/cpython/blob/3.13/Lib/imaplib.py#L307-L316
Why this is a compatibility break
Even though file was undocumented, turning a previously writable instance attribute into a read-only property introduces a silent backward-incompatible change for:
- Subclasses which override the I/O layer
- SSL/TLS IMAP wrappers such as
imapclient’s IMAP4_TLS - Any code that monkeypatches or replaces the socket reader
Making file immutable removes the ability to replace the buffered reader the base class uses.
Expected behavior
At minimum, subclass overrides should continue to work.
Options include:
- Add a setter to the property that writes to
_file - Or rename the internal attribute (e.g., _imaplib_file) instead of shadowing a long-existing public attribute name
- Or provide an explicit API for replacing the buffered input stream
- Or adjust the documentation to specify expected subclass hooks and ensure compatibility
Impact
This change breaks:
imapclient(over 1 million downloads per month)- Libraries layered on top of
imapclient, includingmailsuiteandparsedmarc - All users of IMAP SSL/TLS wrappers relying on custom socket readers
The imapclient maintainers have an open issue tracking this:
mjs/imapclient#618
parsedmarc has an open issue here: domainaware/parsedmarc#636
Request
Please consider restoring backward compatibility by adding a setter or by adjusting the refactor so that subclass assignment to self.file is still possible.
CPython versions tested on:
3.14
Operating systems tested on:
No response