mirror of
https://github.com/python/cpython.git
synced 2025-07-19 01:05:26 +00:00
[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 5b0e827521
)
Co-authored-by: Cody Maloney <cmaloney@users.noreply.github.com>
This commit is contained in:
parent
74dde92903
commit
fade04e0f4
3 changed files with 19 additions and 6 deletions
18
Lib/_pyio.py
18
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.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue