6
6
import os
7
7
import shutil
8
8
import sys
9
+ import types
9
10
import uuid
10
11
import warnings
11
12
from enum import Enum
22
23
from pathlib import PurePath
23
24
from posixpath import sep as posix_sep
24
25
from types import ModuleType
25
- from typing import Callable
26
+ from typing import Callable , Tuple , Type
26
27
from typing import Dict
27
28
from typing import Iterable
28
29
from typing import Iterator
@@ -63,21 +64,33 @@ def get_lock_path(path: _AnyPurePath) -> _AnyPurePath:
63
64
return path .joinpath (".lock" )
64
65
65
66
66
- def on_rm_rf_error (func , path : str , exc , * , start_path : Path ) -> bool :
67
+ def on_rm_rf_error (
68
+ func ,
69
+ path : str ,
70
+ excinfo : Union [
71
+ BaseException ,
72
+ Tuple [Type [BaseException ], BaseException , Optional [types .TracebackType ]],
73
+ ],
74
+ * ,
75
+ start_path : Path ,
76
+ ) -> bool :
67
77
"""Handle known read-only errors during rmtree.
68
78
69
79
The returned value is used only by our own tests.
70
80
"""
71
- exctype , excvalue = exc [:2 ]
81
+ if isinstance (excinfo , BaseException ):
82
+ exc = excinfo
83
+ else :
84
+ exc = excinfo [1 ]
72
85
73
86
# Another process removed the file in the middle of the "rm_rf" (xdist for example).
74
87
# More context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018
75
- if isinstance (excvalue , FileNotFoundError ):
88
+ if isinstance (exc , FileNotFoundError ):
76
89
return False
77
90
78
- if not isinstance (excvalue , PermissionError ):
91
+ if not isinstance (exc , PermissionError ):
79
92
warnings .warn (
80
- PytestWarning (f"(rm_rf) error removing { path } \n { exctype } : { excvalue } " )
93
+ PytestWarning (f"(rm_rf) error removing { path } \n { type ( exc ) } : { exc } " )
81
94
)
82
95
return False
83
96
@@ -86,7 +99,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path: Path) -> bool:
86
99
warnings .warn (
87
100
PytestWarning (
88
101
"(rm_rf) unknown function {} when removing {}:\n {}: {}" .format (
89
- func , path , exctype , excvalue
102
+ func , path , type ( exc ), exc
90
103
)
91
104
)
92
105
)
@@ -149,7 +162,10 @@ def rm_rf(path: Path) -> None:
149
162
are read-only."""
150
163
path = ensure_extended_length_path (path )
151
164
onerror = partial (on_rm_rf_error , start_path = path )
152
- shutil .rmtree (str (path ), onerror = onerror )
165
+ if sys .version_info >= (3 , 12 ):
166
+ shutil .rmtree (str (path ), onexc = onerror )
167
+ else :
168
+ shutil .rmtree (str (path ), onerror = onerror )
153
169
154
170
155
171
def find_prefixed (root : Path , prefix : str ) -> Iterator [Path ]:
0 commit comments