Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(759)

Delta Between Two Patch Sets: Lib/test/test_shutil.py

Issue 15202: followlinks/follow_symlinks/symlinks flags unification.
Left Patch Set: Created 10 months, 3 weeks ago
Right Patch Set: Created 10 months, 2 weeks ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « Lib/shutil.py ('k') | no next file » | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
1 # Copyright (C) 2003 Python Software Foundation 1 # Copyright (C) 2003 Python Software Foundation
2 2
3 import unittest 3 import unittest
4 import shutil 4 import shutil
5 import tempfile 5 import tempfile
6 import sys 6 import sys
7 import stat 7 import stat
8 import os 8 import os
9 import os.path 9 import os.path
10 import errno 10 import errno
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
109 return d 109 return d
110 110
111 def test_rmtree_works_on_bytes(self): 111 def test_rmtree_works_on_bytes(self):
112 tmp = self.mkdtemp() 112 tmp = self.mkdtemp()
113 victim = os.path.join(tmp, 'killme') 113 victim = os.path.join(tmp, 'killme')
114 os.mkdir(victim) 114 os.mkdir(victim)
115 write_file(os.path.join(victim, 'somefile'), 'foo') 115 write_file(os.path.join(victim, 'somefile'), 'foo')
116 victim = os.fsencode(victim) 116 victim = os.fsencode(victim)
117 self.assertIsInstance(victim, bytes) 117 self.assertIsInstance(victim, bytes)
118 shutil.rmtree(victim) 118 shutil.rmtree(victim)
119
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))
119 151
120 def test_rmtree_errors(self): 152 def test_rmtree_errors(self):
121 # filename is guaranteed not to exist 153 # filename is guaranteed not to exist
122 filename = tempfile.mktemp() 154 filename = tempfile.mktemp()
123 self.assertRaises(OSError, shutil.rmtree, filename) 155 self.assertRaises(OSError, shutil.rmtree, filename)
124 156
125 # See bug #1071513 for why we don't run this on cygwin 157 # See bug #1071513 for why we don't run this on cygwin
126 # and bug #1076467 for why we don't run this as root. 158 # and bug #1076467 for why we don't run this as root.
127 if (hasattr(os, 'chmod') and sys.platform[:6] != 'cygwin' 159 if (hasattr(os, 'chmod') and sys.platform[:6] != 'cygwin'
128 and not (hasattr(os, 'geteuid') and os.geteuid() == 0)): 160 and not (hasattr(os, 'geteuid') and os.geteuid() == 0)):
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 self.errorState += 1 209 self.errorState += 1
178 else: 210 else:
179 self.assertEqual(func, os.rmdir) 211 self.assertEqual(func, os.rmdir)
180 self.assertEqual(arg, TESTFN) 212 self.assertEqual(arg, TESTFN)
181 self.assertTrue(issubclass(exc[0], OSError)) 213 self.assertTrue(issubclass(exc[0], OSError))
182 self.errorState = 3 214 self.errorState = 3
183 215
184 def test_rmtree_does_not_choke_on_failing_lstat(self): 216 def test_rmtree_does_not_choke_on_failing_lstat(self):
185 try: 217 try:
186 orig_lstat = os.lstat 218 orig_lstat = os.lstat
187 def raiser(fn): 219 def raiser(fn, *args, **kwargs):
188 if fn != TESTFN: 220 if fn != TESTFN:
189 raise OSError() 221 raise OSError()
190 else: 222 else:
191 return orig_lstat(fn) 223 return orig_lstat(fn)
192 os.lstat = raiser 224 os.lstat = raiser
193 225
194 os.mkdir(TESTFN) 226 os.mkdir(TESTFN)
195 write_file((TESTFN, 'foo'), 'foo') 227 write_file((TESTFN, 'foo'), 'foo')
196 shutil.rmtree(TESTFN) 228 shutil.rmtree(TESTFN)
197 finally: 229 finally:
198 os.lstat = orig_lstat 230 os.lstat = orig_lstat
199 231
200 @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod') 232 @unittest.skipUnless(hasattr(os, 'chmod'), 'requires os.chmod')
201 @support.skip_unless_symlink 233 @support.skip_unless_symlink
202 def test_copymode_followlinks(self): 234 def test_copymode_follow_symlinks(self):
203 tmp_dir = self.mkdtemp() 235 tmp_dir = self.mkdtemp()
204 src = os.path.join(tmp_dir, 'foo') 236 src = os.path.join(tmp_dir, 'foo')
205 dst = os.path.join(tmp_dir, 'bar') 237 dst = os.path.join(tmp_dir, 'bar')
206 src_link = os.path.join(tmp_dir, 'baz') 238 src_link = os.path.join(tmp_dir, 'baz')
207 dst_link = os.path.join(tmp_dir, 'quux') 239 dst_link = os.path.join(tmp_dir, 'quux')
208 write_file(src, 'foo') 240 write_file(src, 'foo')
209 write_file(dst, 'foo') 241 write_file(dst, 'foo')
210 os.symlink(src, src_link) 242 os.symlink(src, src_link)
211 os.symlink(dst, dst_link) 243 os.symlink(dst, dst_link)
212 os.chmod(src, stat.S_IRWXU|stat.S_IRWXG) 244 os.chmod(src, stat.S_IRWXU|stat.S_IRWXG)
(...skipping 25 matching lines...) Expand all
238 dst_link = os.path.join(tmp_dir, 'quux') 270 dst_link = os.path.join(tmp_dir, 'quux')
239 write_file(src, 'foo') 271 write_file(src, 'foo')
240 write_file(dst, 'foo') 272 write_file(dst, 'foo')
241 os.symlink(src, src_link) 273 os.symlink(src, src_link)
242 os.symlink(dst, dst_link) 274 os.symlink(dst, dst_link)
243 os.chmod(src, stat.S_IRWXU|stat.S_IRWXG) 275 os.chmod(src, stat.S_IRWXU|stat.S_IRWXG)
244 os.chmod(dst, stat.S_IRWXU) 276 os.chmod(dst, stat.S_IRWXU)
245 os.lchmod(src_link, stat.S_IRWXO|stat.S_IRWXG) 277 os.lchmod(src_link, stat.S_IRWXO|stat.S_IRWXG)
246 # link to link 278 # link to link
247 os.lchmod(dst_link, stat.S_IRWXO) 279 os.lchmod(dst_link, stat.S_IRWXO)
248 shutil.copymode(src_link, dst_link, symlinks=True) 280 shutil.copymode(src_link, dst_link, follow_symlinks=False)
249 self.assertEqual(os.lstat(src_link).st_mode, 281 self.assertEqual(os.lstat(src_link).st_mode,
250 os.lstat(dst_link).st_mode) 282 os.lstat(dst_link).st_mode)
251 self.assertNotEqual(os.stat(src).st_mode, os.stat(dst).st_mode) 283 self.assertNotEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
252 # src link - use chmod 284 # src link - use chmod
253 os.lchmod(dst_link, stat.S_IRWXO) 285 os.lchmod(dst_link, stat.S_IRWXO)
254 shutil.copymode(src_link, dst, symlinks=True) 286 shutil.copymode(src_link, dst, follow_symlinks=False)
255 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) 287 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
256 # dst link - use chmod 288 # dst link - use chmod
257 os.lchmod(dst_link, stat.S_IRWXO) 289 os.lchmod(dst_link, stat.S_IRWXO)
258 shutil.copymode(src, dst_link, symlinks=True) 290 shutil.copymode(src, dst_link, follow_symlinks=False)
259 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode) 291 self.assertEqual(os.stat(src).st_mode, os.stat(dst).st_mode)
260 292
261 @unittest.skipIf(hasattr(os, 'lchmod'), 'requires os.lchmod to be missing') 293 @unittest.skipIf(hasattr(os, 'lchmod'), 'requires os.lchmod to be missing')
262 @support.skip_unless_symlink 294 @support.skip_unless_symlink
263 def test_copymode_symlink_to_symlink_wo_lchmod(self): 295 def test_copymode_symlink_to_symlink_wo_lchmod(self):
264 tmp_dir = self.mkdtemp() 296 tmp_dir = self.mkdtemp()
265 src = os.path.join(tmp_dir, 'foo') 297 src = os.path.join(tmp_dir, 'foo')
266 dst = os.path.join(tmp_dir, 'bar') 298 dst = os.path.join(tmp_dir, 'bar')
267 src_link = os.path.join(tmp_dir, 'baz') 299 src_link = os.path.join(tmp_dir, 'baz')
268 dst_link = os.path.join(tmp_dir, 'quux') 300 dst_link = os.path.join(tmp_dir, 'quux')
269 write_file(src, 'foo') 301 write_file(src, 'foo')
270 write_file(dst, 'foo') 302 write_file(dst, 'foo')
271 os.symlink(src, src_link) 303 os.symlink(src, src_link)
272 os.symlink(dst, dst_link) 304 os.symlink(dst, dst_link)
273 shutil.copymode(src_link, dst_link, symlinks=True) # silent fail 305 shutil.copymode(src_link, dst_link, follow_symlinks=False) # silent fai l
274 306
275 @support.skip_unless_symlink 307 @support.skip_unless_symlink
276 def test_copystat_symlinks(self): 308 def test_copystat_symlinks(self):
277 tmp_dir = self.mkdtemp() 309 tmp_dir = self.mkdtemp()
278 src = os.path.join(tmp_dir, 'foo') 310 src = os.path.join(tmp_dir, 'foo')
279 dst = os.path.join(tmp_dir, 'bar') 311 dst = os.path.join(tmp_dir, 'bar')
280 src_link = os.path.join(tmp_dir, 'baz') 312 src_link = os.path.join(tmp_dir, 'baz')
281 dst_link = os.path.join(tmp_dir, 'qux') 313 dst_link = os.path.join(tmp_dir, 'qux')
282 write_file(src, 'foo') 314 write_file(src, 'foo')
283 src_stat = os.stat(src) 315 src_stat = os.stat(src)
284 os.utime(src, (src_stat.st_atime, 316 os.utime(src, (src_stat.st_atime,
285 src_stat.st_mtime - 42.0)) # ensure different mtimes 317 src_stat.st_mtime - 42.0)) # ensure different mtimes
286 write_file(dst, 'bar') 318 write_file(dst, 'bar')
287 self.assertNotEqual(os.stat(src).st_mtime, os.stat(dst).st_mtime) 319 self.assertNotEqual(os.stat(src).st_mtime, os.stat(dst).st_mtime)
288 os.symlink(src, src_link) 320 os.symlink(src, src_link)
289 os.symlink(dst, dst_link) 321 os.symlink(dst, dst_link)
290 if hasattr(os, 'lchmod'): 322 if hasattr(os, 'lchmod'):
291 os.lchmod(src_link, stat.S_IRWXO) 323 os.lchmod(src_link, stat.S_IRWXO)
292 if hasattr(os, 'lchflags') and hasattr(stat, 'UF_NODUMP'): 324 if hasattr(os, 'lchflags') and hasattr(stat, 'UF_NODUMP'):
293 os.lchflags(src_link, stat.UF_NODUMP) 325 os.lchflags(src_link, stat.UF_NODUMP)
294 src_link_stat = os.lstat(src_link) 326 src_link_stat = os.lstat(src_link)
295 # follow 327 # follow
296 if hasattr(os, 'lchmod'): 328 if hasattr(os, 'lchmod'):
297 shutil.copystat(src_link, dst_link, symlinks=False) 329 shutil.copystat(src_link, dst_link, follow_symlinks=True)
298 self.assertNotEqual(src_link_stat.st_mode, os.stat(dst).st_mode) 330 self.assertNotEqual(src_link_stat.st_mode, os.stat(dst).st_mode)
299 # don't follow 331 # don't follow
300 shutil.copystat(src_link, dst_link, symlinks=True) 332 shutil.copystat(src_link, dst_link, follow_symlinks=False)
301 dst_link_stat = os.lstat(dst_link) 333 dst_link_stat = os.lstat(dst_link)
302 if os.utime in os.supports_followlinks: 334 if os.utime in os.supports_follow_symlinks:
303 for attr in 'st_atime', 'st_mtime': 335 for attr in 'st_atime', 'st_mtime':
304 # The modification times may be truncated in the new file. 336 # The modification times may be truncated in the new file.
305 self.assertLessEqual(getattr(src_link_stat, attr), 337 self.assertLessEqual(getattr(src_link_stat, attr),
306 getattr(dst_link_stat, attr) + 1) 338 getattr(dst_link_stat, attr) + 1)
307 if hasattr(os, 'lchmod'): 339 if hasattr(os, 'lchmod'):
308 self.assertEqual(src_link_stat.st_mode, dst_link_stat.st_mode) 340 self.assertEqual(src_link_stat.st_mode, dst_link_stat.st_mode)
309 if hasattr(os, 'lchflags') and hasattr(src_link_stat, 'st_flags'): 341 if hasattr(os, 'lchflags') and hasattr(src_link_stat, 'st_flags'):
310 self.assertEqual(src_link_stat.st_flags, dst_link_stat.st_flags) 342 self.assertEqual(src_link_stat.st_flags, dst_link_stat.st_flags)
311 # tell to follow but dst is not a link 343 # tell to follow but dst is not a link
312 shutil.copystat(src_link, dst, symlinks=True) 344 shutil.copystat(src_link, dst, follow_symlinks=False)
313 self.assertTrue(abs(os.stat(src).st_mtime - os.stat(dst).st_mtime) < 345 self.assertTrue(abs(os.stat(src).st_mtime - os.stat(dst).st_mtime) <
314 00000.1) 346 00000.1)
315 347
316 @unittest.skipUnless(hasattr(os, 'chflags') and 348 @unittest.skipUnless(hasattr(os, 'chflags') and
317 hasattr(errno, 'EOPNOTSUPP') and 349 hasattr(errno, 'EOPNOTSUPP') and
318 hasattr(errno, 'ENOTSUP'), 350 hasattr(errno, 'ENOTSUP'),
319 "requires os.chflags, EOPNOTSUPP & ENOTSUP") 351 "requires os.chflags, EOPNOTSUPP & ENOTSUP")
320 def test_copystat_handles_harmless_chflags_errors(self): 352 def test_copystat_handles_harmless_chflags_errors(self):
321 tmpdir = self.mkdtemp() 353 tmpdir = self.mkdtemp()
322 file1 = os.path.join(tmpdir, 'file1') 354 file1 = os.path.join(tmpdir, 'file1')
323 file2 = os.path.join(tmpdir, 'file2') 355 file2 = os.path.join(tmpdir, 'file2')
324 write_file(file1, 'xxx') 356 write_file(file1, 'xxx')
325 write_file(file2, 'xxx') 357 write_file(file2, 'xxx')
326 358
327 def make_chflags_raiser(err): 359 def make_chflags_raiser(err):
328 ex = OSError() 360 ex = OSError()
329 361
330 def _chflags_raiser(path, flags, *, followlinks=True): 362 def _chflags_raiser(path, flags, *, follow_symlinks=True):
331 ex.errno = err 363 ex.errno = err
332 raise ex 364 raise ex
333 return _chflags_raiser 365 return _chflags_raiser
334 old_chflags = os.chflags 366 old_chflags = os.chflags
335 try: 367 try:
336 for err in errno.EOPNOTSUPP, errno.ENOTSUP: 368 for err in errno.EOPNOTSUPP, errno.ENOTSUP:
337 os.chflags = make_chflags_raiser(err) 369 os.chflags = make_chflags_raiser(err)
338 shutil.copystat(file1, file2) 370 shutil.copystat(file1, file2)
339 # assert others errors break it 371 # assert others errors break it
340 os.chflags = make_chflags_raiser(errno.EOPNOTSUPP + errno.ENOTSUP) 372 os.chflags = make_chflags_raiser(errno.EOPNOTSUPP + errno.ENOTSUP)
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
385 def test_copyxattr_symlinks(self): 417 def test_copyxattr_symlinks(self):
386 # On Linux, it's only possible to access non-user xattr for symlinks; 418 # On Linux, it's only possible to access non-user xattr for symlinks;
387 # which in turn require root privileges. This test should be expanded 419 # which in turn require root privileges. This test should be expanded
388 # as soon as other platforms gain support for extended attributes. 420 # as soon as other platforms gain support for extended attributes.
389 tmp_dir = self.mkdtemp() 421 tmp_dir = self.mkdtemp()
390 src = os.path.join(tmp_dir, 'foo') 422 src = os.path.join(tmp_dir, 'foo')
391 src_link = os.path.join(tmp_dir, 'baz') 423 src_link = os.path.join(tmp_dir, 'baz')
392 write_file(src, 'foo') 424 write_file(src, 'foo')
393 os.symlink(src, src_link) 425 os.symlink(src, src_link)
394 os.setxattr(src, 'trusted.foo', b'42') 426 os.setxattr(src, 'trusted.foo', b'42')
395 os.setxattr(src_link, 'trusted.foo', b'43', followlinks=False) 427 os.setxattr(src_link, 'trusted.foo', b'43', follow_symlinks=False)
396 dst = os.path.join(tmp_dir, 'bar') 428 dst = os.path.join(tmp_dir, 'bar')
397 dst_link = os.path.join(tmp_dir, 'qux') 429 dst_link = os.path.join(tmp_dir, 'qux')
398 write_file(dst, 'bar') 430 write_file(dst, 'bar')
399 os.symlink(dst, dst_link) 431 os.symlink(dst, dst_link)
400 shutil._copyxattr(src_link, dst_link, symlinks=True) 432 shutil._copyxattr(src_link, dst_link, follow_symlinks=False)
401 self.assertEqual(os.getxattr(dst_link, 'trusted.foo', followlinks=False) , b'43') 433 self.assertEqual(os.getxattr(dst_link, 'trusted.foo', follow_symlinks=Fa lse), b'43')
402 self.assertRaises(OSError, os.getxattr, dst, 'trusted.foo') 434 self.assertRaises(OSError, os.getxattr, dst, 'trusted.foo')
403 shutil._copyxattr(src_link, dst, symlinks=True) 435 shutil._copyxattr(src_link, dst, follow_symlinks=False)
404 self.assertEqual(os.getxattr(dst, 'trusted.foo'), b'43') 436 self.assertEqual(os.getxattr(dst, 'trusted.foo'), b'43')
405 437
406 @support.skip_unless_symlink 438 @support.skip_unless_symlink
407 def test_copy_symlinks(self): 439 def test_copy_symlinks(self):
408 tmp_dir = self.mkdtemp() 440 tmp_dir = self.mkdtemp()
409 src = os.path.join(tmp_dir, 'foo') 441 src = os.path.join(tmp_dir, 'foo')
410 dst = os.path.join(tmp_dir, 'bar') 442 dst = os.path.join(tmp_dir, 'bar')
411 src_link = os.path.join(tmp_dir, 'baz') 443 src_link = os.path.join(tmp_dir, 'baz')
412 write_file(src, 'foo') 444 write_file(src, 'foo')
413 os.symlink(src, src_link) 445 os.symlink(src, src_link)
414 if hasattr(os, 'lchmod'): 446 if hasattr(os, 'lchmod'):
415 os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO) 447 os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO)
416 # don't follow 448 # don't follow
417 shutil.copy(src_link, dst, symlinks=False) 449 shutil.copy(src_link, dst, follow_symlinks=True)
418 self.assertFalse(os.path.islink(dst)) 450 self.assertFalse(os.path.islink(dst))
419 self.assertEqual(read_file(src), read_file(dst)) 451 self.assertEqual(read_file(src), read_file(dst))
420 os.remove(dst) 452 os.remove(dst)
421 # follow 453 # follow
422 shutil.copy(src_link, dst, symlinks=True) 454 shutil.copy(src_link, dst, follow_symlinks=False)
423 self.assertTrue(os.path.islink(dst)) 455 self.assertTrue(os.path.islink(dst))
424 self.assertEqual(os.readlink(dst), os.readlink(src_link)) 456 self.assertEqual(os.readlink(dst), os.readlink(src_link))
425 if hasattr(os, 'lchmod'): 457 if hasattr(os, 'lchmod'):
426 self.assertEqual(os.lstat(src_link).st_mode, 458 self.assertEqual(os.lstat(src_link).st_mode,
427 os.lstat(dst).st_mode) 459 os.lstat(dst).st_mode)
428 460
429 @support.skip_unless_symlink 461 @support.skip_unless_symlink
430 def test_copy2_symlinks(self): 462 def test_copy2_symlinks(self):
431 tmp_dir = self.mkdtemp() 463 tmp_dir = self.mkdtemp()
432 src = os.path.join(tmp_dir, 'foo') 464 src = os.path.join(tmp_dir, 'foo')
433 dst = os.path.join(tmp_dir, 'bar') 465 dst = os.path.join(tmp_dir, 'bar')
434 src_link = os.path.join(tmp_dir, 'baz') 466 src_link = os.path.join(tmp_dir, 'baz')
435 write_file(src, 'foo') 467 write_file(src, 'foo')
436 os.symlink(src, src_link) 468 os.symlink(src, src_link)
437 if hasattr(os, 'lchmod'): 469 if hasattr(os, 'lchmod'):
438 os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO) 470 os.lchmod(src_link, stat.S_IRWXU | stat.S_IRWXO)
439 if hasattr(os, 'lchflags') and hasattr(stat, 'UF_NODUMP'): 471 if hasattr(os, 'lchflags') and hasattr(stat, 'UF_NODUMP'):
440 os.lchflags(src_link, stat.UF_NODUMP) 472 os.lchflags(src_link, stat.UF_NODUMP)
441 src_stat = os.stat(src) 473 src_stat = os.stat(src)
442 src_link_stat = os.lstat(src_link) 474 src_link_stat = os.lstat(src_link)
443 # follow 475 # follow
444 shutil.copy2(src_link, dst, symlinks=False) 476 shutil.copy2(src_link, dst, follow_symlinks=True)
445 self.assertFalse(os.path.islink(dst)) 477 self.assertFalse(os.path.islink(dst))
446 self.assertEqual(read_file(src), read_file(dst)) 478 self.assertEqual(read_file(src), read_file(dst))
447 os.remove(dst) 479 os.remove(dst)
448 # don't follow 480 # don't follow
449 shutil.copy2(src_link, dst, symlinks=True) 481 shutil.copy2(src_link, dst, follow_symlinks=False)
450 self.assertTrue(os.path.islink(dst)) 482 self.assertTrue(os.path.islink(dst))
451 self.assertEqual(os.readlink(dst), os.readlink(src_link)) 483 self.assertEqual(os.readlink(dst), os.readlink(src_link))
452 dst_stat = os.lstat(dst) 484 dst_stat = os.lstat(dst)
453 if os.utime in os.supports_followlinks: 485 if os.utime in os.supports_follow_symlinks:
454 for attr in 'st_atime', 'st_mtime': 486 for attr in 'st_atime', 'st_mtime':
455 # The modification times may be truncated in the new file. 487 # The modification times may be truncated in the new file.
456 self.assertLessEqual(getattr(src_link_stat, attr), 488 self.assertLessEqual(getattr(src_link_stat, attr),
457 getattr(dst_stat, attr) + 1) 489 getattr(dst_stat, attr) + 1)
458 if hasattr(os, 'lchmod'): 490 if hasattr(os, 'lchmod'):
459 self.assertEqual(src_link_stat.st_mode, dst_stat.st_mode) 491 self.assertEqual(src_link_stat.st_mode, dst_stat.st_mode)
460 self.assertNotEqual(src_stat.st_mode, dst_stat.st_mode) 492 self.assertNotEqual(src_stat.st_mode, dst_stat.st_mode)
461 if hasattr(os, 'lchflags') and hasattr(src_link_stat, 'st_flags'): 493 if hasattr(os, 'lchflags') and hasattr(src_link_stat, 'st_flags'):
462 self.assertEqual(src_link_stat.st_flags, dst_stat.st_flags) 494 self.assertEqual(src_link_stat.st_flags, dst_stat.st_flags)
463 495
(...skipping 13 matching lines...) Expand all
477 @support.skip_unless_symlink 509 @support.skip_unless_symlink
478 def test_copyfile_symlinks(self): 510 def test_copyfile_symlinks(self):
479 tmp_dir = self.mkdtemp() 511 tmp_dir = self.mkdtemp()
480 src = os.path.join(tmp_dir, 'src') 512 src = os.path.join(tmp_dir, 'src')
481 dst = os.path.join(tmp_dir, 'dst') 513 dst = os.path.join(tmp_dir, 'dst')
482 dst_link = os.path.join(tmp_dir, 'dst_link') 514 dst_link = os.path.join(tmp_dir, 'dst_link')
483 link = os.path.join(tmp_dir, 'link') 515 link = os.path.join(tmp_dir, 'link')
484 write_file(src, 'foo') 516 write_file(src, 'foo')
485 os.symlink(src, link) 517 os.symlink(src, link)
486 # don't follow 518 # don't follow
487 shutil.copyfile(link, dst_link, symlinks=True) 519 shutil.copyfile(link, dst_link, follow_symlinks=False)
488 self.assertTrue(os.path.islink(dst_link)) 520 self.assertTrue(os.path.islink(dst_link))
489 self.assertEqual(os.readlink(link), os.readlink(dst_link)) 521 self.assertEqual(os.readlink(link), os.readlink(dst_link))
490 # follow 522 # follow
491 shutil.copyfile(link, dst) 523 shutil.copyfile(link, dst)
492 self.assertFalse(os.path.islink(dst)) 524 self.assertFalse(os.path.islink(dst))
493 525
494 def test_rmtree_uses_safe_fd_version_if_available(self): 526 def test_rmtree_uses_safe_fd_version_if_available(self):
495 if os.unlink in os.supports_dir_fd and os.open in os.supports_dir_fd: 527 _use_fd_functions = ({os.open, os.stat, os.unlink, os.rmdir} <=
528 os.supports_dir_fd and
529 os.listdir in os.supports_fd and
530 os.stat in os.supports_follow_symlinks)
531 if _use_fd_functions:
496 self.assertTrue(shutil._use_fd_functions) 532 self.assertTrue(shutil._use_fd_functions)
497 self.assertTrue(shutil.rmtree.avoids_symlink_attacks) 533 self.assertTrue(shutil.rmtree.avoids_symlink_attacks)
498 tmp_dir = self.mkdtemp() 534 tmp_dir = self.mkdtemp()
499 d = os.path.join(tmp_dir, 'a') 535 d = os.path.join(tmp_dir, 'a')
500 os.mkdir(d) 536 os.mkdir(d)
501 try: 537 try:
502 real_rmtree = shutil._rmtree_safe_fd 538 real_rmtree = shutil._rmtree_safe_fd
503 class Called(Exception): pass 539 class Called(Exception): pass
504 def _raiser(*args, **kwargs): 540 def _raiser(*args, **kwargs):
505 raise Called 541 raise Called
(...skipping 1059 matching lines...) Expand 10 before | Expand all | Expand 10 after
1565 1601
1566 self.assertEqual(expected, actual) 1602 self.assertEqual(expected, actual)
1567 1603
1568 1604
1569 def test_main(): 1605 def test_main():
1570 support.run_unittest(TestShutil, TestMove, TestCopyFile, 1606 support.run_unittest(TestShutil, TestMove, TestCopyFile,
1571 TermsizeTests, TestWhich) 1607 TermsizeTests, TestWhich)
1572 1608
1573 if __name__ == '__main__': 1609 if __name__ == '__main__':
1574 test_main() 1610 test_main()
LEFTRIGHT

RSS Feeds Recent Issues | This issue
This is Rietveld cbc36f91f3f7