Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit abb755d

Browse files
committed
Merge.
2 parents b109515 + a75cd1c commit abb755d

2 files changed

Lines changed: 35 additions & 3 deletions

File tree

Lib/shutil.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ def _rmtree_safe_fd(topfd, path, onerror):
380380
for name in names:
381381
fullname = os.path.join(path, name)
382382
try:
383-
orig_st = os.stat(name, dir_fd=topfd)
383+
orig_st = os.stat(name, dir_fd=topfd, follow_symlinks=False)
384384
mode = orig_st.st_mode
385385
except os.error:
386386
mode = 0
@@ -445,7 +445,7 @@ def onerror(*args):
445445
if (stat.S_ISDIR(orig_st.st_mode) and
446446
os.path.samestat(orig_st, os.fstat(fd))):
447447
_rmtree_safe_fd(fd, path, onerror)
448-
elif (stat.S_ISREG(orig_st.st_mode)):
448+
else:
449449
raise NotADirectoryError(20,
450450
"Not a directory: '{}'".format(path))
451451
finally:

Lib/test/test_shutil.py

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,38 @@ def test_rmtree_works_on_bytes(self):
117117
self.assertIsInstance(victim, bytes)
118118
shutil.rmtree(victim)
119119

120+
@support.skip_unless_symlink
121+
def test_rmtree_fails_on_symlink(self):
122+
tmp = self.mkdtemp()
123+
dir_ = os.path.join(tmp, 'dir')
124+
os.mkdir(dir_)
125+
link = os.path.join(tmp, 'link')
126+
os.symlink(dir_, link)
127+
self.assertRaises(OSError, shutil.rmtree, link)
128+
self.assertTrue(os.path.exists(dir_))
129+
130+
@support.skip_unless_symlink
131+
def test_rmtree_works_on_symlinks(self):
132+
tmp = self.mkdtemp()
133+
dir1 = os.path.join(tmp, 'dir1')
134+
dir2 = os.path.join(dir1, 'dir2')
135+
dir3 = os.path.join(tmp, 'dir3')
136+
for d in dir1, dir2, dir3:
137+
os.mkdir(d)
138+
file1 = os.path.join(tmp, 'file1')
139+
write_file(file1, 'foo')
140+
link1 = os.path.join(dir1, 'link1')
141+
os.symlink(dir2, link1)
142+
link2 = os.path.join(dir1, 'link2')
143+
os.symlink(dir3, link2)
144+
link3 = os.path.join(dir1, 'link3')
145+
os.symlink(file1, link3)
146+
# make sure symlinks are removed but not followed
147+
shutil.rmtree(dir1)
148+
self.assertFalse(os.path.exists(dir1))
149+
self.assertTrue(os.path.exists(dir3))
150+
self.assertTrue(os.path.exists(file1))
151+
120152
def test_rmtree_errors(self):
121153
# filename is guaranteed not to exist
122154
filename = tempfile.mktemp()
@@ -184,7 +216,7 @@ def check_args_to_onerror(self, func, arg, exc):
184216
def test_rmtree_does_not_choke_on_failing_lstat(self):
185217
try:
186218
orig_lstat = os.lstat
187-
def raiser(fn):
219+
def raiser(fn, *args, **kwargs):
188220
if fn != TESTFN:
189221
raise OSError()
190222
else:

0 commit comments

Comments
 (0)