8000 [3.13] gh-133982: Run unclosed file test on all io implementations (g… · python/cpython@e1e8533 · GitHub
[go: up one dir, main page]

Skip to content

Commit e1e8533

Browse files
[3.13] gh-133982: Run unclosed file test on all io implementations (gh-134165) (gh-134434)
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 5b0e827) Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com>
1 parent 046125e commit e1e8533

File tree

3 files changed

+19
-6
lines changed

3 files changed

+19
-6
lines changed

Lib/_pyio.py

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,9 @@ def __del__(self):
413413
if closed:
414414
return
415415

416+
if dealloc_warn := getattr(self, "_dealloc_warn", None):
417+
dealloc_warn(self)
418+
416419
# If close() fails, the caller logs the exception with
417420
# sys.unraisablehook. close() must be called at the end at __del__().
418421
self.close()
@@ -859,6 +862,10 @@ def __repr__(self):
859862
else:
860863
return "<{}.{} name={!r}>".format(modname, clsname, name)
861864

865+
def _dealloc_warn(self, source):
866+
if dealloc_warn := getattr(self.raw, "_dealloc_warn", None):
867+
dealloc_warn(source)
868+
862869
### Lower-level APIs ###
863870

864871
def fileno(self):
@@ -1599,12 +1606,11 @@ def __init__(self, file, mode='r', closefd=True, opener=None):
15991606
raise
16001607
self._fd = fd
16011608

1602-
def __del__(self):
1609+
def _dealloc_warn(self, source):
16031610
if self._fd >= 0 and self._closefd and not self.closed:
16041611
import warnings
1605-
warnings.warn('unclosed file %r' % (self,), ResourceWarning,
1612+
warnings.warn(f'unclosed file {source!r}', ResourceWarning,
16061613
stacklevel=2, source=self)
1607-
self.close()
16081614

16091615
def __getstate__(self):
16101616
raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
@@ -1748,7 +1754,7 @@ def close(self):
17481754
"""
17491755
if not self.closed:
17501756
try:
1751-
if self._closefd:
1757+
if self._closefd and self._fd >= 0:
17521758
os.close(self._fd)
17531759
finally:
17541760
super().close()
@@ -2640,6 +2646,10 @@ def readline(self, size=None):
26402646
def newlines(self):
26412647
return self._decoder.newlines if self._decoder else None
26422648

2649+
def _dealloc_warn(self, source):
2650+
if dealloc_warn := getattr(self.buffer, "_dealloc_warn", None):
2651+
dealloc_warn(source)
2652+
264 8000 32653

26442654
class StringIO(TextIOWrapper):
26452655
"""Text I/O implementation using an in-memory buffer.

Lib/test/test_io.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4386,7 +4386,7 @@ def test_abc_inheritance_official(self):
43864386
self._check_abc_inheritance(io)
43874387

43884388
def _check_warn_on_dealloc(self, *args, **kwargs):
4389-
f = open(*args, **kwargs)
4389+
f = self.open(*args, **kwargs)
43904390
r = repr(f)
43914391
with self.assertWarns(ResourceWarning) as cm:
43924392
f = None
@@ -4415,7 +4415,7 @@ def cleanup_fds():
44154415
r, w = os.pipe()
44164416
fds += r, w
44174417
with warnings_helper.check_no_resource_warning(self):
4418-
open(r, *args, closefd=False, **kwargs)
4418+
self.open(r, *args, closefd=False, **kwargs)
44194419

44204420
@unittest.skipUnless(hasattr(os, "pipe"), "requires os.pipe()")
44214421
def test_warn_on_dealloc_fd(self):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Emit :exc:`RuntimeWarning` in the Python implementation of :mod:`io` when
2+
the :term:`file-like object <file object>` is not closed explicitly in the
3+
presence of multiple I/O layers.

0 commit comments

Comments
 (0)
0