https://github.com/python/cpython/commit/bad3cdefa840ff099e5e08cf88dcf6dfed7d37b8
commit: bad3cdefa840ff099e5e08cf88dcf6dfed7d37b8
branch: main
author: Thomas Grainger <[email protected]>
committer: kumaraditya303 <[email protected]>
date: 2024-12-18T10:12:24Z
summary:

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

Co-authored-by: Kumar Aditya <[email protected]>

files:
A Misc/NEWS.d/next/Library/2024-11-11-07-56-03.gh-issue-126639.AmVSt-.rst
M Lib/tempfile.py
M Lib/test/test_tempfile.py

diff --git a/Lib/tempfile.py b/Lib/tempfile.py
index b5a15f7b72c872..0eb9ddeb6ac377 100644
--- a/Lib/tempfile.py
+++ b/Lib/tempfile.py
@@ -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
diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py
index 57e9bd20c77ee1..7adc021d298254 100644
--- a/Lib/test/test_tempfile.py
+++ b/Lib/test/test_tempfile.py
@@ -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 ")
diff --git 
a/Misc/NEWS.d/next/Library/2024-11-11-07-56-03.gh-issue-126639.AmVSt-.rst 
b/Misc/NEWS.d/next/Library/2024-11-11-07-56-03.gh-issue-126639.AmVSt-.rst
new file mode 100644
index 00000000000000..0b75e5858de731
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2024-11-11-07-56-03.gh-issue-126639.AmVSt-.rst
@@ -0,0 +1 @@
+:class:`tempfile.NamedTemporaryFile` will now issue a :exc:`ResourceWarning` 
when it is finalized by the garbage collector without being explicitly closed.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]

Reply via email to