gh-126639: Add ResourceWarning to NamedTemporaryFile (#126677)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
This commit is contained in:
Thomas Grainger 2024-12-18 10:12:24 +00:00 committed by GitHub
parent 2610bccfdf
commit bad3cdefa8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 6 deletions

View File

@ -437,11 +437,19 @@ class _TemporaryFileCloser:
cleanup_called = False
close_called = False
def __init__(self, file, name, delete=True, delete_on_close=True):
def __init__(
self,
file,
name,
delete=True,
delete_on_close=True,
warn_message="Implicitly cleaning up unknown file",
):
self.file = file
self.name = name
self.delete = delete
self.delete_on_close = delete_on_close
self.warn_message = warn_message
def cleanup(self, windows=(_os.name == 'nt'), unlink=_os.unlink):
if not self.cleanup_called:
@ -469,7 +477,10 @@ def close(self):
self.cleanup()
def __del__(self):
close_called = self.close_called
self.cleanup()
if not close_called:
_warnings.warn(self.warn_message, ResourceWarning)
class _TemporaryFileWrapper:
@ -483,8 +494,17 @@ class _TemporaryFileWrapper:
def __init__(self, file, name, delete=True, delete_on_close=True):
self.file = file
self.name = name
self._closer = _TemporaryFileCloser(file, name, delete,
delete_on_close)
self._closer = _TemporaryFileCloser(
file,
name,
delete,
delete_on_close,
warn_message=f"Implicitly cleaning up {self!r}",
)
def __repr__(self):
file = self.__dict__['file']
return f"<{type(self).__name__} {file=}>"
def __getattr__(self, name):
# Attribute lookups are delegated to the underlying file

View File

@ -1112,11 +1112,14 @@ def my_func(dir):
# Testing extreme case, where the file is not explicitly closed
# f.close()
return tmp_name
# Make sure that the garbage collector has finalized the file object.
gc.collect()
dir = tempfile.mkdtemp()
try:
tmp_name = my_func(dir)
with self.assertWarnsRegex(
expected_warning=ResourceWarning,
expected_regex=r"Implicitly cleaning up <_TemporaryFileWrapper file=.*>",
):
tmp_name = my_func(dir)
support.gc_collect()
self.assertFalse(os.path.exists(tmp_name),
f"NamedTemporaryFile {tmp_name!r} "
f"exists after finalizer ")

View File

@ -0,0 +1 @@
:class:`tempfile.NamedTemporaryFile` will now issue a :exc:`ResourceWarning` when it is finalized by the garbage collector without being explicitly closed.