Skip to content

Commit cc963aa

Browse files
committed
pathlib: fix Python 3.12 rmtree(onerror=...) deprecation
Fixes pytest-dev#10890 Ref: https://docs.python.org/3.12/library/shutil.html#shutil.rmtree
1 parent 2252404 commit cc963aa

File tree

1 file changed

+24
-8
lines changed

1 file changed

+24
-8
lines changed

src/_pytest/pathlib.py

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import shutil
88
import sys
9+
import types
910
import uuid
1011
import warnings
1112
from enum import Enum
@@ -22,7 +23,7 @@
2223
from pathlib import PurePath
2324
from posixpath import sep as posix_sep
2425
from types import ModuleType
25-
from typing import Callable
26+
from typing import Callable, Tuple, Type
2627
from typing import Dict
2728
from typing import Iterable
2829
from typing import Iterator
@@ -63,21 +64,33 @@ def get_lock_path(path: _AnyPurePath) -> _AnyPurePath:
6364
return path.joinpath(".lock")
6465

6566

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:
6777
"""Handle known read-only errors during rmtree.
6878
6979
The returned value is used only by our own tests.
7080
"""
71-
exctype, excvalue = exc[:2]
81+
if isinstance(excinfo, BaseException):
82+
exc = excinfo
83+
else:
84+
exc = excinfo[1]
7285

7386
# Another process removed the file in the middle of the "rm_rf" (xdist for example).
7487
# More context: https://github.com/pytest-dev/pytest/issues/5974#issuecomment-543799018
75-
if isinstance(excvalue, FileNotFoundError):
88+
if isinstance(exc, FileNotFoundError):
7689
return False
7790

78-
if not isinstance(excvalue, PermissionError):
91+
if not isinstance(exc, PermissionError):
7992
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}")
8194
)
8295
return False
8396

@@ -86,7 +99,7 @@ def on_rm_rf_error(func, path: str, exc, *, start_path: Path) -> bool:
8699
warnings.warn(
87100
PytestWarning(
88101
"(rm_rf) unknown function {} when removing {}:\n{}: {}".format(
89-
func, path, exctype, excvalue
102+
func, path, type(exc), exc
90103
)
91104
)
92105
)
@@ -149,7 +162,10 @@ def rm_rf(path: Path) -> None:
149162
are read-only."""
150163
path = ensure_extended_length_path(path)
151164
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)
153169

154170

155171
def find_prefixed(root: Path, prefix: str) -> Iterator[Path]:

0 commit comments

Comments
 (0)