Skip to content

Commit d9975c6

Browse files
committed
Extract convenience wrapper of rmtree to setuptools._shutil for reuse
1 parent e14cfec commit d9975c6

File tree

2 files changed

+44
-36
lines changed

2 files changed

+44
-36
lines changed

setuptools/_shutil.py

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
"""Convenience layer on top of stdlib's shutil and os"""
2+
3+
import os
4+
import stat
5+
from typing import Callable, TypeVar
6+
7+
from .compat import py311
8+
9+
from distutils import log
10+
11+
try:
12+
from os import chmod
13+
except ImportError:
14+
# Jython compatibility
15+
def chmod(*args: object, **kwargs: object) -> None: # type: ignore[misc] # Mypy reuses the imported definition anyway
16+
pass
17+
18+
19+
_T = TypeVar("_T")
20+
21+
22+
def attempt_chmod_verbose(path, mode):
23+
log.debug("changing mode of %s to %o", path, mode)
24+
try:
25+
chmod(path, mode)
26+
except OSError as e:
27+
log.debug("chmod failed: %s", e)
28+
29+
30+
# Must match shutil._OnExcCallback
31+
def _auto_chmod(func: Callable[..., _T], arg: str, exc: BaseException) -> _T:
32+
"""shutils onexc callback to automatically call chmod for certain functions."""
33+
# Only retry for scenarios known to have an issue
34+
if func in [os.unlink, os.remove] and os.name == 'nt':
35+
attempt_chmod_verbose(arg, stat.S_IWRITE)
36+
return func(arg)
37+
raise exc
38+
39+
40+
def rmtree(path, ignore_errors=False, onexc=_auto_chmod):
41+
return py311.shutil_rmtree(path, ignore_errors, onexc)

setuptools/command/easy_install.py

+3-36
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
from collections.abc import Iterable
3535
from glob import glob
3636
from sysconfig import get_path
37-
from typing import TYPE_CHECKING, Callable, NoReturn, TypedDict, TypeVar
37+
from typing import TYPE_CHECKING, NoReturn, TypedDict
3838

3939
from jaraco.text import yield_lines
4040

@@ -63,7 +63,8 @@
6363
from setuptools.wheel import Wheel
6464

6565
from .._path import ensure_directory
66-
from ..compat import py39, py311, py312
66+
from .._shutil import attempt_chmod_verbose as chmod, rmtree as _rmtree
67+
from ..compat import py39, py312
6768

6869
from distutils import dir_util, log
6970
from distutils.command import install
@@ -89,8 +90,6 @@
8990
'get_exe_prefixes',
9091
]
9192

92-
_T = TypeVar("_T")
93-
9493

9594
def is_64bit():
9695
return struct.calcsize("P") == 8
@@ -1789,16 +1788,6 @@ def _first_line_re():
17891788
return re.compile(first_line_re.pattern.decode())
17901789

17911790

1792-
# Must match shutil._OnExcCallback
1793-
def auto_chmod(func: Callable[..., _T], arg: str, exc: BaseException) -> _T:
1794-
"""shutils onexc callback to automatically call chmod for certain functions."""
1795-
# Only retry for scenarios known to have an issue
1796-
if func in [os.unlink, os.remove] and os.name == 'nt':
1797-
chmod(arg, stat.S_IWRITE)
1798-
return func(arg)
1799-
raise exc
1800-
1801-
18021791
def update_dist_caches(dist_path, fix_zipimporter_caches):
18031792
"""
18041793
Fix any globally cached `dist_path` related data
@@ -2021,24 +2010,6 @@ def is_python_script(script_text, filename):
20212010
return False # Not any Python I can recognize
20222011

20232012

2024-
try:
2025-
from os import (
2026-
chmod as _chmod, # pyright: ignore[reportAssignmentType] # Losing type-safety w/ pyright, but that's ok
2027-
)
2028-
except ImportError:
2029-
# Jython compatibility
2030-
def _chmod(*args: object, **kwargs: object) -> None: # type: ignore[misc] # Mypy reuses the imported definition anyway
2031-
pass
2032-
2033-
2034-
def chmod(path, mode):
2035-
log.debug("changing mode of %s to %o", path, mode)
2036-
try:
2037-
_chmod(path, mode)
2038-
except OSError as e:
2039-
log.debug("chmod failed: %s", e)
2040-
2041-
20422013
class _SplitArgs(TypedDict, total=False):
20432014
comments: bool
20442015
posix: bool
@@ -2350,10 +2321,6 @@ def load_launcher_manifest(name):
23502321
return manifest.decode('utf-8') % vars()
23512322

23522323

2353-
def _rmtree(path, ignore_errors: bool = False, onexc=auto_chmod):
2354-
return py311.shutil_rmtree(path, ignore_errors, onexc)
2355-
2356-
23572324
def current_umask():
23582325
tmp = os.umask(0o022)
23592326
os.umask(tmp)

0 commit comments

Comments
 (0)