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)