66import os
77import shutil
88import sys
9+ import types
910import uuid
1011import warnings
1112from enum import Enum
2829from typing import Iterator
2930from typing import Optional
3031from typing import Set
32+ from typing import Tuple
33+ from typing import Type
3134from typing import TypeVar
3235from typing import Union
3336
@@ -63,21 +66,33 @@ def get_lock_path(path: _AnyPurePath) -> _AnyPurePath:
6366 return path .joinpath (".lock" )
6467
6568
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 :
6779 """Handle known read-only errors during rmtree.
6880
6981 The returned value is used only by our own tests.
7082 """
71- exctype , excvalue = exc [:2 ]
83+ if isinstance (excinfo , BaseException ):
84+ exc = excinfo
85+ else :
86+ exc = excinfo [1 ]
7287
7388 # Another process removed the file in the middle of the "rm_rf" (xdist for example).
7489 # More context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018
75- if isinstance (excvalue , FileNotFoundError ):
90+ if isinstance (exc , FileNotFoundError ):
7691 return False
7792
78- if not isinstance (excvalue , PermissionError ):
93+ if not isinstance (exc , PermissionError ):
7994 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 } " )
8196 )
8297 return False
8398
@@ -86,7 +101,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path: Path) -> bool:
86101 warnings .warn (
87102 PytestWarning (
88103 "(rm_rf) unknown function {} when removing {}:\n {}: {}" .format (
89- func , path , exctype , excvalue
104+ func , path , type ( exc ), exc
90105 )
91106 )
92107 )
@@ -149,7 +164,10 @@ def rm_rf(path: Path) -> None:
149164 are read-only."""
150165 path = ensure_extended_length_path (path )
151166 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 )
153171
154172
155173def find_prefixed (root : Path , prefix : str ) -> Iterator [Path ]:
0 commit comments