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