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
@@ -876,8 +877,31 @@ def resetperms(path):
876877
877878 try :
878879 _os .unlink (path )
879- # PermissionError is raised on FreeBSD for directories
880- except (IsADirectoryError , PermissionError ):
880+ except IsADirectoryError :
881+ cls ._rmtree (path , ignore_errors = ignore_errors )
882+ except PermissionError :
883+ # The PermissionError handler was originally added for
884+ # FreeBSD in directories, but it seems that it is raised
885+ # on Windows too.
886+ # bpo-43153: Calling _rmtree again may
887+ # raise NotADirectoryError and mask the PermissionError.
888+ # So we must re-raise the current PermissionError if
889+ # path is not a directory.
890+ try :
891+ st = _os .lstat (path )
892+ except OSError :
893+ if ignore_errors :
894+ return
895+ raise
896+ if (_stat .S_ISLNK (st .st_mode ) or
897+ not _stat .S_ISDIR (st .st_mode ) or
898+ (hasattr (st , 'st_file_attributes' ) and
899+ st .st_file_attributes & _stat .FILE_ATTRIBUTE_REPARSE_POINT and
900+ st .st_reparse_tag == _stat .IO_REPARSE_TAG_MOUNT_POINT )
901+ ):
902+ if ignore_errors :
903+ return
904+ raise
881905 cls ._rmtree (path , ignore_errors = ignore_errors )
882906 except FileNotFoundError :
883907 pass
Original file line number Diff line number Diff line change @@ -1533,6 +1533,17 @@ def test_explict_cleanup_ignore_errors(self):
15331533 temp_path .exists (),
15341534 f"TemporaryDirectory { temp_path !s} exists after cleanup" )
15351535
1536+ @unittest .skipUnless (os .name == "nt" , "Only on Windows." )
1537+ def test_explicit_cleanup_correct_error (self ):
1538+ with tempfile .TemporaryDirectory () as working_dir :
1539+ temp_dir = self .do_create (dir = working_dir )
1540+ with open (os .path .join (temp_dir .name , "example.txt" ), 'wb' ):
1541+ # Previously raised NotADirectoryError on some OSes
1542+ # (e.g. Windows). See bpo-43153.
1543+ with self .assertRaises (PermissionError ):
1544+ temp_dir .cleanup ()
1545+
1546+
15361547 @os_helper .skip_unless_symlink
15371548 def test_cleanup_with_symlink_to_a_directory (self ):
15381549 # 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