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
28
29
from typing import Iterator
29
30
from typing import Optional
30
31
from typing import Set
32
+ from typing import Tuple
33
+ from typing import Type
31
34
from typing import TypeVar
32
35
from typing import Union
33
36
@@ -63,21 +66,33 @@ def get_lock_path(path: _AnyPurePath) -> _AnyPurePath:
63
66
return path .joinpath (".lock" )
64
67
65
68
66
- def on_rm_rf_error (func , path : str , exc , * , start_path : Path ) -> bool :
69
+ def on_rm_rf_error (
70
+ func ,
71
+ path : str ,
72
+ excinfo : Union [
73
+ BaseException ,
74
+ Tuple [Type [BaseException ], BaseException , Optional [types .TracebackType ]],
75
+ ],
76
+ * ,
77
+ start_path : Path ,
78
+ ) -> bool :
67
79
"""Handle known read-only errors during rmtree.
68
80
69
81
The returned value is used only by our own tests.
70
82
"""
71
- exctype , excvalue = exc [:2 ]
83
+ if isinstance (excinfo , BaseException ):
84
+ exc = excinfo
85
+ else :
86
+ exc = excinfo [1 ]
72
87
73
88
# Another process removed the file in the middle of the "rm_rf" (xdist for example).
74
89
# More context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018
75
- if isinstance (excvalue , FileNotFoundError ):
90
+ if isinstance (exc , FileNotFoundError ):
76
91
return False
77
92
78
- if not isinstance (excvalue , PermissionError ):
93
+ if not isinstance (exc , PermissionError ):
79
94
warnings .warn (
80
- PytestWarning (f"(rm_rf) error removing { path } \n { exctype } : { excvalue } " )
95
+ PytestWarning (f"(rm_rf) error removing { path } \n { type ( exc ) } : { exc } " )
81
96
)
82
97
return False
83
98
@@ -86,7 +101,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path: Path) -> bool:
86
101
warnings .warn (
87
102
PytestWarning (
88
103
"(rm_rf) unknown function {} when removing {}:\n {}: {}" .format (
89
- func , path , exctype , excvalue
104
+ func , path , type ( exc ), exc
90
105
)
91
106
)
92
107
)
@@ -149,7 +164,10 @@ def rm_rf(path: Path) -> None:
149
164
are read-only."""
150
165
path = ensure_extended_length_path (path )
151
166
onerror = partial (on_rm_rf_error , start_path = path )
152
- shutil .rmtree (str (path ), onerror = onerror )
167
+ if sys .version_info >= (3 , 12 ):
168
+ shutil .rmtree (str (path ), onexc = onerror )
169
+ else :
170
+ shutil .rmtree (str (path ), onerror = onerror )
153
171
154
172
155
173
def find_prefixed (root : Path , prefix : str ) -> Iterator [Path ]:
0 commit comments