From 6e4cf9ffc5813d9d6c21fb8c54b34f079949fd15 Mon Sep 17 00:00:00 2001 From: Avasam Date: Fri, 24 May 2024 15:08:04 -0400 Subject: [PATCH] Prevent a TypeError: 'NoneType' object is not callable when ``shutil_rmtree`is called without an`onexc`` parameter on Python<=3.11 --- newsfragments/4382.bugfix.rst | 1 + setuptools/compat/py311.py | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) create mode 100644 newsfragments/4382.bugfix.rst diff --git a/newsfragments/4382.bugfix.rst b/newsfragments/4382.bugfix.rst new file mode 100644 index 0000000000..3aa9e18573 --- /dev/null +++ b/newsfragments/4382.bugfix.rst @@ -0,0 +1 @@ +Prevent a ``TypeError: 'NoneType' object is not callable`` when ``shutil_rmtree`` is called without an ``onexc`` parameter on Python<=3.11 -- by :user:`Avasam` diff --git a/setuptools/compat/py311.py b/setuptools/compat/py311.py index 28175b1f75..5069c441c4 100644 --- a/setuptools/compat/py311.py +++ b/setuptools/compat/py311.py @@ -1,12 +1,26 @@ -import sys +from __future__ import annotations + import shutil +import sys +from typing import Any, Callable, TYPE_CHECKING + +if TYPE_CHECKING: + from _typeshed import StrOrBytesPath, ExcInfo + +# Same as shutil._OnExcCallback from typeshed +_OnExcCallback = Callable[[Callable[..., Any], str, BaseException], object] -def shutil_rmtree(path, ignore_errors=False, onexc=None): +def shutil_rmtree( + path: StrOrBytesPath, + ignore_errors: bool = False, + onexc: _OnExcCallback | None = None, +) -> None: if sys.version_info >= (3, 12): return shutil.rmtree(path, ignore_errors, onexc=onexc) - def _handler(fn, path, excinfo): - return onexc(fn, path, excinfo[1]) + def _handler(fn: Callable[..., Any], path: str, excinfo: ExcInfo) -> None: + if onexc: + onexc(fn, path, excinfo[1]) return shutil.rmtree(path, ignore_errors, onerror=_handler)