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:
@propertydeffile(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.importwarningswarnings.warn(
'IMAP4.file is unsupported, can cause errors, and may be removed.',
RuntimeWarning,
stacklevel=2)
returnself._file
Prior to 3.14, file was a normal attribute and writable.
defopen(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=hostself.port=portself.sock=self._create_socket(timeout)
self.file=self.sock.makefile('rb')
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
Please consider restoring backward compatibility by adding a setter or by adjusting the refactor so that subclass assignment to self.file is still possible.
So I've been trying various approaches and there are few issues:
While I understand that the package is popular, it's not been updated since 2023 and doesn't officially support Python 3.14.
Making it a different attribute so that people can do whatever they want with their 'file' is also not a good idea because imapclient uses the super shutdown() which calls self.file.close(). So if we renamed the attribute, it would become self._imaplib_file.close() and the file created by imapclient would still be opened.
Making it writable again is annoying because we really don't want to use that attribute actually. If a connection is open, then sock and file are set but need to be synchronized. When opening an SSL connection, we wrap the socket and recreate the file. This is also an issue in our current code where we should have closed the previous file before wrapping the socket. I'm not sure the destructor automatically closes the SocketIO object (that could be annoying!)
I'm inclined to actually not change anything and ask maintainers of imapclient to fix the library. However, I can make it writable again and document that using it is at their own risk. Fixing the synchronization issue is honestly not that interesting either since I prefer removing the attribute altogether in the future so a deprecation is better for Python 3.15. I'll restore the behavior for Python 3.14.
Or rename the internal attribute (e.g., _imaplib_file) instead of shadowing a long-existing public attribute
As per PEP-8, it's not a public attribute. Something that is not documented is not considered part of the public API.
Or adjust the documentation to specify expected subclass hooks and ensure compatibility
The compatibility was never really supported because of the previous file not being closed.
As I read through this whole situation more, yeah. It should really be on the maintainers of imapclient to use an approach that does not use file for something it wasn't intended for. I'm just not sure what that fix would be on their end. Although the repo for that project has shown activity as recently as two months ago, the downstream issue (mjs/imapclient#618 languished without maintainer activity. The ideal situation would be a downstream PR that fixes the issues with Python 3.14+ as-is I'm just not sure what that would be. I appreciate the willingness to revert a change upstream though.
Yes but it's better if other users aren't also affected. It's not just one package that may be affected but everyone else. It's also preferrable to entirely remove the attribute in the future if possible.
I do not understand how making the file attribute writeable will help the code that sets the file attribute. They do this for purpose, expecting that this will affect the following I/O, If this is a no-op (since this value is not used), they will be broken in more subtle way.
So I closed the corresponding PRs. Considering imapclient is the only consumer I could find in the wild, I think it's fine. OTOH, I think we should instead properly deprecate the attribute as it's currently raising a RuntimeWarning. So I'll open another issue and change the refs in the corresponding PR (that way, the discussion here stays for posterity)
Activity
1.10.1
9.0.3
Remove Python 3.14 from testing
picnixz commented on Dec 6, 2025
So I've been trying various approaches and there are few issues:
I'm inclined to actually not change anything and ask maintainers of imapclient to fix the library. However, I can make it writable again and document that using it is at their own risk. Fixing the synchronization issue is honestly not that interesting either since I prefer removing the attribute altogether in the future so a deprecation is better for Python 3.15. I'll restore the behavior for Python 3.14.
As per PEP-8, it's not a public attribute. Something that is not documented is not considered part of the public API.
The compatibility was never really supported because of the previous file not being closed.
pythongh-142307: restore legacy support for altering ``IMAP4.file``
pythongh-142307: restore legacy support for altering ``IMAP4.file``
seanthegeek commented on Dec 6, 2025
As I read through this whole situation more, yeah. It should really be on the maintainers of imapclient to use an approach that does not use file for something it wasn't intended for. I'm just not sure what that fix would be on their end. Although the repo for that project has shown activity as recently as two months ago, the downstream issue (mjs/imapclient#618 languished without maintainer activity. The ideal situation would be a downstream PR that fixes the issues with Python 3.14+ as-is I'm just not sure what that would be. I appreciate the willingness to revert a change upstream though.
seanthegeek commented on Dec 6, 2025
@picnixz Those PRs might not be needed if the imapclient merges my PR and publishes a new release.
mjs/imapclient#629
picnixz commented on Dec 6, 2025
Yes but it's better if other users aren't also affected. It's not just one package that may be affected but everyone else. It's also preferrable to entirely remove the attribute in the future if possible.
9.0.3
Remove Python 3.14 from testing
pythongh-142307: restore legacy support for altering ``IMAP4.file``
serhiy-storchaka commented on Feb 25, 2026
I do not understand how making the file attribute writeable will help the code that sets the file attribute. They do this for purpose, expecting that this will affect the following I/O, If this is a no-op (since this value is not used), they will be broken in more subtle way.
seanthegeek commented on Mar 4, 2026
For what it's worth, imappclient did merge my PR and release it, and there is no reason to access the file attribute writeable again.
picnixz commented on Mar 7, 2026
So I closed the corresponding PRs. Considering imapclient is the only consumer I could find in the wild, I think it's fine. OTOH, I think we should instead properly deprecate the attribute as it's currently raising a RuntimeWarning. So I'll open another issue and change the refs in the corresponding PR (that way, the discussion here stays for posterity)
gh-142307: deprecate legacy support for altering `IMAP4.file` (#142335)