Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commite9b51c0

Browse files
bpo-26660,bpo-35144: Fix permission errors in TemporaryDirectory cleanup. (GH-10320)
TemporaryDirectory.cleanup() failed when non-writeable or non-searchablefiles or directories were created inside a temporary directory.
1 parent38ab7d4 commite9b51c0

File tree

4 files changed

+86
-14
lines changed

4 files changed

+86
-14
lines changed

‎Lib/shutil.py‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -584,11 +584,16 @@ def _rmtree_safe_fd(topfd, path, onerror):
584584
fullname=os.path.join(path,entry.name)
585585
try:
586586
is_dir=entry.is_dir(follow_symlinks=False)
587-
ifis_dir:
588-
orig_st=entry.stat(follow_symlinks=False)
589-
is_dir=stat.S_ISDIR(orig_st.st_mode)
590587
exceptOSError:
591588
is_dir=False
589+
else:
590+
ifis_dir:
591+
try:
592+
orig_st=entry.stat(follow_symlinks=False)
593+
is_dir=stat.S_ISDIR(orig_st.st_mode)
594+
exceptOSError:
595+
onerror(os.lstat,fullname,sys.exc_info())
596+
continue
592597
ifis_dir:
593598
try:
594599
dirfd=os.open(entry.name,os.O_RDONLY,dir_fd=topfd)

‎Lib/tempfile.py‎

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -777,9 +777,39 @@ def __init__(self, suffix=None, prefix=None, dir=None):
777777
self,self._cleanup,self.name,
778778
warn_message="Implicitly cleaning up {!r}".format(self))
779779

780+
@classmethod
781+
def_rmtree(cls,name):
782+
defonerror(func,path,exc_info):
783+
ifissubclass(exc_info[0],PermissionError):
784+
defresetperms(path):
785+
try:
786+
_os.chflags(path,0)
787+
exceptAttributeError:
788+
pass
789+
_os.chmod(path,0o700)
790+
791+
try:
792+
ifpath!=name:
793+
resetperms(_os.path.dirname(path))
794+
resetperms(path)
795+
796+
try:
797+
_os.unlink(path)
798+
# PermissionError is raised on FreeBSD for directories
799+
except (IsADirectoryError,PermissionError):
800+
cls._rmtree(path)
801+
exceptFileNotFoundError:
802+
pass
803+
elifissubclass(exc_info[0],FileNotFoundError):
804+
pass
805+
else:
806+
raise
807+
808+
_shutil.rmtree(name,onerror=onerror)
809+
780810
@classmethod
781811
def_cleanup(cls,name,warn_message):
782-
_shutil.rmtree(name)
812+
cls._rmtree(name)
783813
_warnings.warn(warn_message,ResourceWarning)
784814

785815
def__repr__(self):
@@ -793,4 +823,4 @@ def __exit__(self, exc, value, tb):
793823

794824
defcleanup(self):
795825
ifself._finalizer.detach():
796-
_shutil.rmtree(self.name)
826+
self._rmtree(self.name)

‎Lib/test/test_tempfile.py‎

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,19 +1297,25 @@ def __exit__(self, *exc_info):
12971297
classTestTemporaryDirectory(BaseTestCase):
12981298
"""Test TemporaryDirectory()."""
12991299

1300-
defdo_create(self,dir=None,pre="",suf="",recurse=1):
1300+
defdo_create(self,dir=None,pre="",suf="",recurse=1,dirs=1,files=1):
13011301
ifdirisNone:
13021302
dir=tempfile.gettempdir()
13031303
tmp=tempfile.TemporaryDirectory(dir=dir,prefix=pre,suffix=suf)
13041304
self.nameCheck(tmp.name,dir,pre,suf)
1305-
# Create a subdirectory and some files
1306-
ifrecurse:
1307-
d1=self.do_create(tmp.name,pre,suf,recurse-1)
1308-
d1.name=None
1309-
withopen(os.path.join(tmp.name,"test.txt"),"wb")asf:
1310-
f.write(b"Hello world!")
1305+
self.do_create2(tmp.name,recurse,dirs,files)
13111306
returntmp
13121307

1308+
defdo_create2(self,path,recurse=1,dirs=1,files=1):
1309+
# Create subdirectories and some files
1310+
ifrecurse:
1311+
foriinrange(dirs):
1312+
name=os.path.join(path,"dir%d"%i)
1313+
os.mkdir(name)
1314+
self.do_create2(name,recurse-1,dirs,files)
1315+
foriinrange(files):
1316+
withopen(os.path.join(path,"test%d.txt"%i),"wb")asf:
1317+
f.write(b"Hello world!")
1318+
13131319
deftest_mkdtemp_failure(self):
13141320
# Check no additional exception if mkdtemp fails
13151321
# Previously would raise AttributeError instead
@@ -1349,7 +1355,7 @@ def test_cleanup_with_symlink_to_a_directory(self):
13491355
"TemporaryDirectory %s exists after cleanup"%d1.name)
13501356
self.assertTrue(os.path.exists(d2.name),
13511357
"Directory pointed to by a symlink was deleted")
1352-
self.assertEqual(os.listdir(d2.name), ['test.txt'],
1358+
self.assertEqual(os.listdir(d2.name), ['test0.txt'],
13531359
"Contents of the directory pointed to by a symlink "
13541360
"were deleted")
13551361
d2.cleanup()
@@ -1384,7 +1390,7 @@ def test_del_on_shutdown(self):
13841390
13851391
tmp2 = os.path.join(tmp.name, 'test_dir')
13861392
os.mkdir(tmp2)
1387-
with open(os.path.join(tmp2, "test.txt"), "w") as f:
1393+
with open(os.path.join(tmp2, "test0.txt"), "w") as f:
13881394
f.write("Hello world!")
13891395
13901396
{mod}.tmp = tmp
@@ -1452,6 +1458,33 @@ def test_context_manager(self):
14521458
self.assertEqual(name,d.name)
14531459
self.assertFalse(os.path.exists(name))
14541460

1461+
deftest_modes(self):
1462+
formodeinrange(8):
1463+
mode<<=6
1464+
withself.subTest(mode=format(mode,'03o')):
1465+
d=self.do_create(recurse=3,dirs=2,files=2)
1466+
withd:
1467+
# Change files and directories mode recursively.
1468+
forroot,dirs,filesinos.walk(d.name,topdown=False):
1469+
fornameinfiles:
1470+
os.chmod(os.path.join(root,name),mode)
1471+
os.chmod(root,mode)
1472+
d.cleanup()
1473+
self.assertFalse(os.path.exists(d.name))
1474+
1475+
@unittest.skipUnless(hasattr(os,'chflags'),'requires os.lchflags')
1476+
deftest_flags(self):
1477+
flags=stat.UF_IMMUTABLE|stat.UF_NOUNLINK
1478+
d=self.do_create(recurse=3,dirs=2,files=2)
1479+
withd:
1480+
# Change files and directories flags recursively.
1481+
forroot,dirs,filesinos.walk(d.name,topdown=False):
1482+
fornameinfiles:
1483+
os.chflags(os.path.join(root,name),flags)
1484+
os.chflags(root,flags)
1485+
d.cleanup()
1486+
self.assertFalse(os.path.exists(d.name))
1487+
14551488

14561489
if__name__=="__main__":
14571490
unittest.main()
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Fixed permission errors in:class:`~tempfile.TemporaryDirectory` clean up.
2+
Previously ``TemporaryDirectory.cleanup()`` failed when non-writeable or
3+
non-searchable files or directories were created inside a temporary
4+
directory.

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp