Serhiy Storchaka added the comment:

And here are patches for 2.7 and 3.2 (there are some peculiarities, i.e. in 
exception handling).

----------
Added file: 
http://bugs.python.org/file28968/fix_tempfile_leaving_files_behind_2-2.7.patch
Added file: 
http://bugs.python.org/file28969/fix_tempfile_leaving_files_behind_2-3.2.patch

_______________________________________
Python tracker <rep...@bugs.python.org>
<http://bugs.python.org/issue16800>
_______________________________________
diff -r 20f0c5398e97 Lib/tempfile.py
--- a/Lib/tempfile.py   Mon Feb 04 10:29:38 2013 -0500
+++ b/Lib/tempfile.py   Tue Feb 05 20:57:18 2013 +0200
@@ -193,14 +193,16 @@
             name = namer.next()
             filename = _os.path.join(dir, name)
             try:
-                fd = _os.open(filename, flags, 0600)
-                fp = _os.fdopen(fd, 'w')
-                fp.write('blat')
-                fp.close()
-                _os.unlink(filename)
-                del fp, fd
+                fd = _os.open(filename, flags, 0o600)
+                try:
+                    try:
+                        _os.write(fd, b'blat')
+                    finally:
+                        _os.close(fd)
+                finally:
+                    _os.unlink(filename)
                 return dir
-            except (OSError, IOError), e:
+            except (OSError, IOError) as e:
                 if e[0] != _errno.EEXIST:
                     break # no point trying more names in this directory
                 pass
diff -r 20f0c5398e97 Lib/test/test_support.py
--- a/Lib/test/test_support.py  Mon Feb 04 10:29:38 2013 -0500
+++ b/Lib/test/test_support.py  Tue Feb 05 20:57:18 2013 +0200
@@ -1298,6 +1298,33 @@
             except:
                 break
 
+@contextlib.contextmanager
+def swap_attr(obj, attr, new_val):
+    """Temporary swap out an attribute with a new object.
+
+    Usage:
+        with swap_attr(obj, "attr", 5):
+            ...
+
+        This will set obj.attr to 5 for the duration of the with: block,
+        restoring the old value at the end of the block. If `attr` doesn't
+        exist on `obj`, it will be created and then deleted at the end of the
+        block.
+    """
+    if hasattr(obj, attr):
+        real_val = getattr(obj, attr)
+        setattr(obj, attr, new_val)
+        try:
+            yield
+        finally:
+            setattr(obj, attr, real_val)
+    else:
+        setattr(obj, attr, new_val)
+        try:
+            yield
+        finally:
+            delattr(obj, attr)
+
 def py3k_bytes(b):
     """Emulate the py3k bytes() constructor.
 
diff -r 20f0c5398e97 Lib/test/test_tempfile.py
--- a/Lib/test/test_tempfile.py Mon Feb 04 10:29:38 2013 -0500
+++ b/Lib/test/test_tempfile.py Tue Feb 05 20:57:18 2013 +0200
@@ -1,7 +1,9 @@
 # tempfile.py unit tests.
 import tempfile
+import errno
 import os
 import signal
+import shutil
 import sys
 import re
 import warnings
@@ -202,8 +204,45 @@
 
 test_classes.append(test__candidate_tempdir_list)
 
+# We test _get_default_tempdir some more by testing gettempdir.
 
-# We test _get_default_tempdir by testing gettempdir.
+class TestGetDefaultTempdir(TC):
+    """Test _get_default_tempdir()."""
+
+    def test_no_files_left_behind(self):
+        # use a private empty directory
+        our_temp_directory = tempfile.mkdtemp()
+        try:
+            # force _get_default_tempdir() to consider our empty directory
+            def our_candidate_list():
+                return [our_temp_directory]
+
+            with test_support.swap_attr(tempfile, "_candidate_tempdir_list",
+                                        our_candidate_list):
+                # verify our directory is empty after _get_default_tempdir()
+                tempfile._get_default_tempdir()
+                self.assertEqual(os.listdir(our_temp_directory), [])
+
+                def raise_OSError(*args, **kwargs):
+                    raise OSError(-1)
+
+                with test_support.swap_attr(os, "open", raise_OSError):
+                    # test again with failing os.open()
+                    with self.assertRaises(IOError) as cm:
+                        tempfile._get_default_tempdir()
+                    self.assertEqual(cm.exception.errno, errno.ENOENT)
+                    self.assertEqual(os.listdir(our_temp_directory), [])
+
+                with test_support.swap_attr(os, "write", raise_OSError):
+                    # test again with failing os.write()
+                    with self.assertRaises(IOError) as cm:
+                        tempfile._get_default_tempdir()
+                    self.assertEqual(cm.exception.errno, errno.ENOENT)
+                    self.assertEqual(os.listdir(our_temp_directory), [])
+        finally:
+            shutil.rmtree(our_temp_directory)
+
+test_classes.append(TestGetDefaultTempdir)
 
 
 class test__get_candidate_names(TC):
diff -r 801cb3918212 Lib/tempfile.py
--- a/Lib/tempfile.py   Tue Feb 05 10:49:49 2013 -0500
+++ b/Lib/tempfile.py   Tue Feb 05 20:57:09 2013 +0200
@@ -175,11 +175,13 @@
             filename = _os.path.join(dir, name)
             try:
                 fd = _os.open(filename, _bin_openflags, 0o600)
-                fp = _io.open(fd, 'wb')
-                fp.write(b'blat')
-                fp.close()
-                _os.unlink(filename)
-                del fp, fd
+                try:
+                    try:
+                        _os.write(fd, b'blat')
+                    finally:
+                        _os.close(fd)
+                finally:
+                    _os.unlink(filename)
                 return dir
             except (OSError, IOError) as e:
                 if e.args[0] != _errno.EEXIST:
diff -r 801cb3918212 Lib/test/test_tempfile.py
--- a/Lib/test/test_tempfile.py Tue Feb 05 10:49:49 2013 -0500
+++ b/Lib/test/test_tempfile.py Tue Feb 05 20:57:09 2013 +0200
@@ -1,5 +1,6 @@
 # tempfile.py unit tests.
 import tempfile
+import errno
 import os
 import signal
 import sys
@@ -211,8 +212,42 @@
 
 test_classes.append(test__candidate_tempdir_list)
 
+# We test _get_default_tempdir some more by testing gettempdir.
 
-# We test _get_default_tempdir by testing gettempdir.
+class TestGetDefaultTempdir(TC):
+    """Test _get_default_tempdir()."""
+
+    def test_no_files_left_behind(self):
+        # use a private empty directory
+        with tempfile.TemporaryDirectory() as our_temp_directory:
+            # force _get_default_tempdir() to consider our empty directory
+            def our_candidate_list():
+                return [our_temp_directory]
+
+            with support.swap_attr(tempfile, "_candidate_tempdir_list",
+                                   our_candidate_list):
+                # verify our directory is empty after _get_default_tempdir()
+                tempfile._get_default_tempdir()
+                self.assertEqual(os.listdir(our_temp_directory), [])
+
+                def raise_OSError(*args, **kwargs):
+                    raise OSError(-1)
+
+                with support.swap_attr(os, "open", raise_OSError):
+                    # test again with failing os.open()
+                    with self.assertRaises(IOError) as cm:
+                        tempfile._get_default_tempdir()
+                    self.assertEqual(cm.exception.args[0], errno.ENOENT)
+                    self.assertEqual(os.listdir(our_temp_directory), [])
+
+                with support.swap_attr(os, "write", raise_OSError):
+                    # test again with failing os.write()
+                    with self.assertRaises(IOError) as cm:
+                        tempfile._get_default_tempdir()
+                    self.assertEqual(cm.exception.errno, errno.ENOENT)
+                    self.assertEqual(os.listdir(our_temp_directory), [])
+
+test_classes.append(TestGetDefaultTempdir)
 
 
 class test__get_candidate_names(TC):
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to