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