summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2025-05-21 15:22:44 (GMT)
committerGitHub <noreply@github.com>2025-05-21 15:22:44 (GMT)
commitfade04e0f441be0ea3ec0ef99dd0af8113df9ed8 (patch)
treefdd86645c540b0337cc78af78aa66bfb0b902bd8
parent74dde92903769b77843152a3603f0e50845ccc81 (diff)
downloadcpython-fade04e0f441be0ea3ec0ef99dd0af8113df9ed8.zip
cpython-fade04e0f441be0ea3ec0ef99dd0af8113df9ed8.tar.gz
cpython-fade04e0f441be0ea3ec0ef99dd0af8113df9ed8.tar.bz2
[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 <cmaloney@users.noreply.github.com>
-rw-r--r--Lib/_pyio.py18
-rw-r--r--Lib/test/test_io.py4
-rw-r--r--Misc/NEWS.d/next/Library/2025-05-17-20-23-57.gh-issue-133982.smS7au.rst3
3 files changed, 19 insertions, 6 deletions
diff --git a/Lib/_pyio.py b/Lib/_pyio.py
index f79674f..300d5b3 100644
--- a/Lib/_pyio.py
+++ b/Lib/_pyio.py
@@ -407,6 +407,9 @@ class IOBase(metaclass=abc.ABCMeta):
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 @@ class _BufferedIOMixin(BufferedIOBase):
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 @@ class FileIO(RawIOBase):
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 @@ class FileIO(RawIOBase):
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 @@ class TextIOWrapper(TextIOBase):
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 4625e3a..aa619a9 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -4417,7 +4417,7 @@ class MiscIOTest(unittest.TestCase):
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 @@ class MiscIOTest(unittest.TestCase):
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 0000000..a675314
--- /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.