File tree Expand file tree Collapse file tree 3 files changed +41
-2
lines changed Expand file tree Collapse file tree 3 files changed +41
-2
lines changed Original file line number Diff line number Diff line change 4141import io as _io
4242import os as _os
4343import shutil as _shutil
44+ import stat as _stat
4445import errno as _errno
4546from random import Random as _Random
4647import sys as _sys
@@ -889,8 +890,31 @@ def resetperms(path):
889890
890891 try :
891892 _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
894918 cls ._rmtree (path , ignore_errors = ignore_errors )
895919 except FileNotFoundError :
896920 pass
Original file line number Diff line number Diff line change @@ -1641,6 +1641,17 @@ def test_explicit_cleanup_ignore_errors(self):
16411641 temp_path .exists (),
16421642 f"TemporaryDirectory { temp_path !s} exists after cleanup" )
16431643
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+
16441655 @os_helper .skip_unless_symlink
16451656 def test_cleanup_with_symlink_to_a_directory (self ):
16461657 # 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