diff options
author | Miss Islington (bot) <31488909+miss-islington@users.noreply.github.com> | 2025-05-21 15:22:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-05-21 15:22:44 (GMT) |
commit | fade04e0f441be0ea3ec0ef99dd0af8113df9ed8 (patch) | |
tree | fdd86645c540b0337cc78af78aa66bfb0b902bd8 | |
parent | 74dde92903769b77843152a3603f0e50845ccc81 (diff) | |
download | cpython-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.py | 18 | ||||
-rw-r--r-- | Lib/test/test_io.py | 4 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2025-05-17-20-23-57.gh-issue-133982.smS7au.rst | 3 |
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. |