https://github.com/python/cpython/commit/fade04e0f441be0ea3ec0ef99dd0af8113df9ed8
commit: fade04e0f441be0ea3ec0ef99dd0af8113df9ed8
branch: 3.14
author: Miss Islington (bot) <31488909+miss-isling...@users.noreply.github.com>
committer: ambv <luk...@langa.pl>
date: 2025-05-21T17:22:44+02:00
summary:

[3.14] gh-133982: Run unclosed file test on all io implementations (gh-134165) 
(gh-134433)

Update `test_io` `_check_warn_on_dealloc` to use `self.` to dispatch to
different I/O implementations.

Update the `_pyio` implementation to match expected behavior, using the
same `_dealloc_warn` design as the C implementation uses to report the
topmost `__del__` object.

The FileIO one now matches all the others, so can use IOBase. There was
a missing check on closing (self._fd must be valid), add that check
(cherry picked from commit 5b0e82752120a5dc66ce6ee778751d71ba2c33b2)

Co-authored-by: Cody Maloney <cmalo...@users.noreply.github.com>

files:
A Misc/NEWS.d/next/Library/2025-05-17-20-23-57.gh-issue-133982.smS7au.rst
M Lib/_pyio.py
M Lib/test/test_io.py

diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index f79674fb7a9f5e..300d5b3cbce32b 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -407,6 +407,9 @@ def __del__(self):
         if closed:
             return
 
+        if dealloc_warn := getattr(self, "_dealloc_warn", None):
+            dealloc_warn(self)
+
         # If close() fails, the caller logs the exception with
         # sys.unraisablehook. close() must be called at the end at __del__().
         self.close()
@@ -853,6 +856,10 @@ def __repr__(self):
         else:
             return "<{}.{} name={!r}>".format(modname, clsname, name)
 
+    def _dealloc_warn(self, source):
+        if dealloc_warn := getattr(self.raw, "_dealloc_warn", None):
+            dealloc_warn(source)
+
     ### Lower-level APIs ###
 
     def fileno(self):
@@ -1601,12 +1608,11 @@ def __init__(self, file, mode='r', closefd=True, 
opener=None):
             raise
         self._fd = fd
 
-    def __del__(self):
+    def _dealloc_warn(self, source):
         if self._fd >= 0 and self._closefd and not self.closed:
             import warnings
-            warnings.warn('unclosed file %r' % (self,), ResourceWarning,
+            warnings.warn(f'unclosed file {source!r}', ResourceWarning,
                           stacklevel=2, source=self)
-            self.close()
 
     def __getstate__(self):
         raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
@@ -1781,7 +1787,7 @@ def close(self):
         if not self.closed:
             self._stat_atopen = None
             try:
-                if self._closefd:
+                if self._closefd and self._fd >= 0:
                     os.close(self._fd)
             finally:
                 super().close()
@@ -2690,6 +2696,10 @@ def readline(self, size=None):
     def newlines(self):
         return self._decoder.newlines if self._decoder else None
 
+    def _dealloc_warn(self, source):
+        if dealloc_warn := getattr(self.buffer, "_dealloc_warn", None):
+            dealloc_warn(source)
+
 
 class StringIO(TextIOWrapper):
     """Text I/O implementation using an in-memory buffer.
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index 4625e3a01faa7b..aa619a96ab7535 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -4417,7 +4417,7 @@ def test_abc_inheritance_official(self):
         self._check_abc_inheritance(io)
 
     def _check_warn_on_dealloc(self, *args, **kwargs):
-        f = open(*args, **kwargs)
+        f = self.open(*args, **kwargs)
         r = repr(f)
         with self.assertWarns(ResourceWarning) as cm:
             f = None
@@ -4446,7 +4446,7 @@ def cleanup_fds():
         r, w = os.pipe()
         fds += r, w
         with warnings_helper.check_no_resource_warning(self):
-            open(r, *args, closefd=False, **kwargs)
+            self.open(r, *args, closefd=False, **kwargs)
 
     @unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
     def test_warn_on_dealloc_fd(self):
diff --git 
a/Misc/NEWS.d/next/Library/2025-05-17-20-23-57.gh-issue-133982.smS7au.rst 
b/Misc/NEWS.d/next/Library/2025-05-17-20-23-57.gh-issue-133982.smS7au.rst
new file mode 100644
index 00000000000000..a6753145981181
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-05-17-20-23-57.gh-issue-133982.smS7au.rst
@@ -0,0 +1,3 @@
+Emit :exc:`RuntimeWarning` in the Python implementation of :mod:`io` when
+the :term:`file-like object <file object>` is not closed explicitly in the
+presence of multiple I/O layers.

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: arch...@mail-archive.com

Reply via email to