3
3
from __future__ import division
4
4
from __future__ import print_function
5
5
6
+ import errno
6
7
import os
7
8
import stat
8
9
import sys
@@ -319,7 +320,20 @@ def test_cleanup_locked(self, tmp_path):
319
320
p , consider_lock_dead_if_created_before = p .stat ().st_mtime + 1
320
321
)
321
322
322
- def test_rmtree (self , tmp_path ):
323
+ def test_cleanup_ignores_symlink (self , tmp_path ):
324
+ the_symlink = tmp_path / (self .PREFIX + "current" )
325
+ attempt_symlink_to (the_symlink , tmp_path / (self .PREFIX + "5" ))
326
+ self ._do_cleanup (tmp_path )
327
+
328
+ def test_removal_accepts_lock (self , tmp_path ):
329
+ folder = pathlib .make_numbered_dir (root = tmp_path , prefix = self .PREFIX )
330
+ pathlib .create_cleanup_lock (folder )
331
+ pathlib .maybe_delete_a_numbered_dir (folder )
332
+ assert folder .is_dir ()
333
+
334
+
335
+ class TestRmRf :
336
+ def test_rm_rf (self , tmp_path ):
323
337
from _pytest .pathlib import rm_rf
324
338
325
339
adir = tmp_path / "adir"
@@ -335,7 +349,7 @@ def test_rmtree(self, tmp_path):
335
349
rm_rf (adir )
336
350
assert not adir .exists ()
337
351
338
- def test_rmtree_with_read_only_file (self , tmp_path ):
352
+ def test_rm_rf_with_read_only_file (self , tmp_path ):
339
353
"""Ensure rm_rf can remove directories with read-only files in them (#5524)"""
340
354
from _pytest .pathlib import rm_rf
341
355
@@ -344,38 +358,58 @@ def test_rmtree_with_read_only_file(self, tmp_path):
344
358
345
359
fn .touch ()
346
360
347
- mode = os .stat (str (fn )).st_mode
348
- os .chmod (str (fn ), mode & ~ stat .S_IWRITE )
361
+ self .chmod_r (fn )
349
362
350
363
rm_rf (fn .parent )
351
364
352
365
assert not fn .parent .is_dir ()
353
366
354
- def test_rmtree_with_read_only_directory (self , tmp_path ):
367
+ def chmod_r (self , path ):
368
+ mode = os .stat (str (path )).st_mode
369
+ os .chmod (str (path ), mode & ~ stat .S_IWRITE )
370
+
371
+ def test_rm_rf_with_read_only_directory (self , tmp_path ):
355
372
"""Ensure rm_rf can remove read-only directories (#5524)"""
356
373
from _pytest .pathlib import rm_rf
357
374
358
375
adir = tmp_path / "dir"
359
376
adir .mkdir ()
360
377
361
378
(adir / "foo.txt" ).touch ()
362
- mode = os .stat (str (adir )).st_mode
363
- os .chmod (str (adir ), mode & ~ stat .S_IWRITE )
379
+ self .chmod_r (adir )
364
380
365
381
rm_rf (adir )
366
382
367
383
assert not adir .is_dir ()
368
384
369
- def test_cleanup_ignores_symlink (self , tmp_path ):
370
- the_symlink = tmp_path / (self .PREFIX + "current" )
371
- attempt_symlink_to (the_symlink , tmp_path / (self .PREFIX + "5" ))
372
- self ._do_cleanup (tmp_path )
385
+ def test_on_rm_rf_error (self , tmp_path ):
386
+ from _pytest .pathlib import on_rm_rf_error
373
387
374
- def test_removal_accepts_lock (self , tmp_path ):
375
- folder = pathlib .make_numbered_dir (root = tmp_path , prefix = self .PREFIX )
376
- pathlib .create_cleanup_lock (folder )
377
- pathlib .maybe_delete_a_numbered_dir (folder )
378
- assert folder .is_dir ()
388
+ adir = tmp_path / "dir"
389
+ adir .mkdir ()
390
+
391
+ fn = adir / "foo.txt"
392
+ fn .touch ()
393
+ self .chmod_r (fn )
394
+
395
+ # unknown exception
396
+ with pytest .warns (pytest .PytestWarning ):
397
+ exc_info = (None , RuntimeError (), None )
398
+ on_rm_rf_error (os .unlink , str (fn ), exc_info , start_path = tmp_path )
399
+ assert fn .is_file ()
400
+
401
+ permission_error = OSError ()
402
+ permission_error .errno = errno .EACCES
403
+
404
+ # unknown function
405
+ with pytest .warns (pytest .PytestWarning ):
406
+ exc_info = (None , permission_error , None )
407
+ on_rm_rf_error (None , str (fn ), exc_info , start_path = tmp_path )
408
+ assert fn .is_file ()
409
+
410
+ exc_info = (None , permission_error , None )
411
+ on_rm_rf_error (os .unlink , str (fn ), exc_info , start_path = tmp_path )
412
+ assert not fn .is_file ()
379
413
380
414
381
415
def attempt_symlink_to (path , to_path ):
0 commit comments