File tree 3 files changed +41
-2
lines changed
3 files changed +41
-2
lines changed Original file line number Diff line number Diff line change 41
41
import io as _io
42
42
import os as _os
43
43
import shutil as _shutil
44
+ import stat as _stat
44
45
import errno as _errno
45
46
from random import Random as _Random
46
47
import sys as _sys
@@ -889,8 +890,31 @@ def resetperms(path):
889
890
890
891
try :
891
892
_os .unlink (path )
892
- # PermissionError is raised on FreeBSD for directories
893
- except (IsADirectoryError , PermissionError ):
893
+ except IsADirectoryError :
894
+ cls ._rmtree (path , ignore_errors = ignore_errors )
895
+ except PermissionError :
896
+ # The PermissionError handler was originally added for
897
+ # FreeBSD in directories, but it seems that it is raised
898
+ # on Windows too.
899
+ # bpo-43153: Calling _rmtree again may
900
+ # raise NotADirectoryError and mask the PermissionError.
901
+ # So we must re-raise the current PermissionError if
902
+ # path is not a directory.
903
+ try :
904
+ st = _os .lstat (path )
905
+ except OSError :
906
+ if ignore_errors :
907
+ return
908
+ raise
909
+ if (_stat .S_ISLNK (st .st_mode ) or
910
+ not _stat .S_ISDIR (st .st_mode ) or
911
+ (hasattr (st , 'st_file_attributes' ) and
912
+ st .st_file_attributes & _stat .FILE_ATTRIBUTE_REPARSE_POINT and
913
+ st .st_reparse_tag == _stat .IO_REPARSE_TAG_MOUNT_POINT )
914
+ ):
915
+ if ignore_errors :
916
+ return
917
+ raise
894
918
cls ._rmtree (path , ignore_errors = ignore_errors )
895
919
except FileNotFoundError :
896
920
pass
Original file line number Diff line number Diff line change @@ -1641,6 +1641,17 @@ def test_explicit_cleanup_ignore_errors(self):
1641
1641
temp_path .exists (),
1642
1642
f"TemporaryDirectory { temp_path !s} exists after cleanup" )
1643
1643
1644
+ @unittest .skipUnless (os .name == "nt" , "Only on Windows." )
1645
+ def test_explicit_cleanup_correct_error (self ):
1646
+ with tempfile .TemporaryDirectory () as working_dir :
1647
+ temp_dir = self .do_create (dir = working_dir )
1648
+ with open (os .path .join (temp_dir .name , "example.txt" ), 'wb' ):
1649
+ # Previously raised NotADirectoryError on some OSes
1650
+ # (e.g. Windows). See bpo-43153.
1651
+ with self .assertRaises (PermissionError ):
1652
+ temp_dir .cleanup ()
1653
+
1654
+
1644
1655
@os_helper .skip_unless_symlink
1645
1656
def test_cleanup_with_symlink_to_a_directory (self ):
1646
1657
# cleanup() should not follow symlinks to directories (issue #12464)
Original file line number Diff line number Diff line change
1
+ On Windows, ``tempfile.TemporaryDirectory `` previously masked a
2
+ ``PermissionError `` with ``NotADirectoryError `` during directory cleanup. It
3
+ now correctly raises ``PermissionError `` if errors are not ignored. Patch by
4
+ Andrei Kulakov and Ken Jin.
You can’t perform that action at this time.
0 commit comments