From ce24836328610ded22b8f46e5e07c4820889b0f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Cardao?= Date: Wed, 21 Aug 2024 15:16:31 +0200 Subject: [PATCH] Add support for `shutils.rmtree(..., onexec=...)` `onexec` parameter cannot be used before 3.12. `onerror` previous parameter is deprecated since 3.12. it/e3-core#11 --- src/e3/fs.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/e3/fs.py b/src/e3/fs.py index ad566cff..f4d89781 100644 --- a/src/e3/fs.py +++ b/src/e3/fs.py @@ -23,7 +23,7 @@ logger = e3.log.getLogger("fs") if TYPE_CHECKING: - from typing import Iterable + from typing import Iterable, Any from collections.abc import Callable, Sequence @@ -434,7 +434,9 @@ def rm(path: str | list[str], recursive: bool = False, glob: bool = True) -> Non else: file_list = set(path) - def onerror(func: Callable, error_path: str, exc_info: tuple) -> None: + def onerror( + func: Callable[..., Any], error_path: str, exc_info: tuple | BaseException + ) -> None: """When shutil.rmtree fail, try again to delete the file. :param func: function to call on error @@ -478,7 +480,10 @@ def onerror(func: Callable, error_path: str, exc_info: tuple) -> None: os.chmod(error_path, 0o700) # And continue to delete the subdir - shutil.rmtree(error_path, onerror=onerror) + if sys.version_info[0] >= 3 and sys.version_info[1] >= 12: + shutil.rmtree(error_path, onexc=onerror) + else: + shutil.rmtree(error_path, onerror=onerror) else: raise FSError(origin="rm", message=f"unknown function: {func.__name__!r}") @@ -497,7 +502,10 @@ def onerror(func: Callable, error_path: str, exc_info: tuple) -> None: # Note: shutil.rmtree requires its argument to be an actual # directory, not a symbolic link to a directory if recursive and os.path.isdir(f) and not os.path.islink(f): - shutil.rmtree(f, onerror=onerror) + if sys.version_info[0] >= 3 and sys.version_info[1] >= 12: + shutil.rmtree(f, onexc=onerror) + else: + shutil.rmtree(f, onerror=onerror) else: e3.os.fs.force_remove_file(f) @@ -514,7 +522,7 @@ def splitall(path: str) -> tuple[str, ...]: :param path: path to split :return: a list of path components """ - dirnames = [] # type: list[str] + dirnames: list[str] = [] while 1: head, tail = os.path.split(path) if head == path: