diff -r 7ae156f07a90 Lib/tempfile.py --- a/Lib/tempfile.py Sun Feb 15 00:45:57 2015 +0200 +++ b/Lib/tempfile.py Sun Feb 15 11:02:28 2015 +0200 @@ -166,6 +166,13 @@ def _get_default_tempdir(): return dir except FileExistsError: pass + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if _os.name == 'nt' and _os.access(dir, _os.W_OK): + continue + else: + break # no point trying more names in this directory except OSError: break # no point trying more names in this directory raise FileNotFoundError(_errno.ENOENT, @@ -204,7 +211,7 @@ def _mkstemp_inner(dir, pre, suf, flags) except PermissionError: # This exception is thrown when a directory with the chosen name # already exists on windows. - if _os.name == 'nt': + if _os.name == 'nt' and _os.access(dir, _os.W_OK): continue else: raise @@ -296,6 +303,13 @@ def mkdtemp(suffix="", prefix=template, return file except FileExistsError: continue # try again + except PermissionError: + # This exception is thrown when a directory with the chosen name + # already exists on windows. + if _os.name == 'nt' and _os.access(dir, _os.W_OK): + continue + else: + raise raise FileExistsError(_errno.EEXIST, "No usable temporary directory name found") diff -r 7ae156f07a90 Lib/test/test_tempfile.py --- a/Lib/test/test_tempfile.py Sun Feb 15 00:45:57 2015 +0200 +++ b/Lib/test/test_tempfile.py Sun Feb 15 11:02:28 2015 +0200 @@ -274,7 +274,36 @@ def _mock_candidate_names(*names): lambda: iter(names)) -class TestMkstempInner(BaseTestCase): +class TestBadTempdir: + + def test_read_only_directory(self): + with _inside_empty_temp_dir(): + mode = os.stat(tempfile.tempdir).st_mode + mode &= ~(stat.S_IWUSR | stat.S_IWGRP | stat.S_IWOTH) + os.chmod(tempfile.tempdir, mode) + if os.access(tempfile.tempdir, os.W_OK): + self.skipTest("can't set the directory read-only") + with self.assertRaises(PermissionError): + self.make_temp() + self.assertEqual(os.listdir(tempfile.tempdir), []) + + def test_nonexisting_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'nonexistent') + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(FileNotFoundError): + self.make_temp() + + def test_non_directory(self): + with _inside_empty_temp_dir(): + tempdir = os.path.join(tempfile.tempdir, 'file') + open(tempdir, 'wb').close() + with support.swap_attr(tempfile, 'tempdir', tempdir): + with self.assertRaises(NotADirectoryError): + self.make_temp() + + +class TestMkstempInner(TestBadTempdir, BaseTestCase): """Test the internal function _mkstemp_inner.""" class mkstemped: @@ -395,6 +424,8 @@ class TestMkstempInner(BaseTestCase): '', tempfile._bin_openflags) + make_temp = default_mkstemp_inner + def test_collision_with_existing_file(self): # _mkstemp_inner tries another name when a file with # the chosen name already exists @@ -528,9 +559,12 @@ class TestMkstemp(BaseTestCase): os.rmdir(dir) -class TestMkdtemp(BaseTestCase): +class TestMkdtemp(TestBadTempdir, BaseTestCase): """Test mkdtemp().""" + def make_temp(self): + return tempfile.mkdtemp() + def do_create(self, dir=None, pre="", suf=""): if dir is None: dir = tempfile.gettempdir()