-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Refactor/unify/extract shutil.rmtree
callbacks (and avoid repetition)
#4682
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
d9975c6
Extract convenience wrapper of rmtree to setuptools._shutil for reuse
abravalheri 1678730
Extract common pattern to remove dir if exists to setuptools._shutil
abravalheri b9be144
Attempt to solve typechecking problems
abravalheri 6ddac39
Ignore some lines for coverage
abravalheri 8272bc3
Refactor usage of shutil.rmtree in other parts of setuptools
abravalheri bb93502
Add docstring
abravalheri db2b206
Extract test for shutil.rmtree callback to its own file
abravalheri File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
"""Convenience layer on top of stdlib's shutil and os""" | ||
|
||
import os | ||
import stat | ||
from typing import Callable, TypeVar | ||
|
||
from .compat import py311 | ||
|
||
from distutils import log | ||
|
||
try: | ||
from os import chmod # pyright: ignore[reportAssignmentType] | ||
# Losing type-safety w/ pyright, but that's ok | ||
except ImportError: # pragma: no cover | ||
# Jython compatibility | ||
def chmod(*args: object, **kwargs: object) -> None: # type: ignore[misc] # Mypy reuses the imported definition anyway | ||
pass | ||
|
||
|
||
_T = TypeVar("_T") | ||
|
||
|
||
def attempt_chmod_verbose(path, mode): | ||
log.debug("changing mode of %s to %o", path, mode) | ||
try: | ||
chmod(path, mode) | ||
except OSError as e: # pragma: no cover | ||
log.debug("chmod failed: %s", e) | ||
|
||
|
||
# Must match shutil._OnExcCallback | ||
def _auto_chmod( | ||
func: Callable[..., _T], arg: str, exc: BaseException | ||
) -> _T: # pragma: no cover | ||
"""shutils onexc callback to automatically call chmod for certain functions.""" | ||
# Only retry for scenarios known to have an issue | ||
if func in [os.unlink, os.remove] and os.name == 'nt': | ||
attempt_chmod_verbose(arg, stat.S_IWRITE) | ||
return func(arg) | ||
raise exc | ||
|
||
|
||
def rmtree(path, ignore_errors=False, onexc=_auto_chmod): | ||
""" | ||
Similar to ``shutil.rmtree`` but automatically executes ``chmod`` | ||
for well know Windows failure scenarios. | ||
""" | ||
return py311.shutil_rmtree(path, ignore_errors, onexc) | ||
|
||
|
||
def rmdir(path, **opts): | ||
if os.path.isdir(path): | ||
rmtree(path, **opts) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import stat | ||
import sys | ||
from unittest.mock import Mock | ||
|
||
from setuptools import _shutil | ||
|
||
|
||
def test_rmtree_readonly(monkeypatch, tmp_path): | ||
"""Verify onerr works as expected""" | ||
|
||
tmp_dir = tmp_path / "with_readonly" | ||
tmp_dir.mkdir() | ||
some_file = tmp_dir.joinpath("file.txt") | ||
some_file.touch() | ||
some_file.chmod(stat.S_IREAD) | ||
|
||
expected_count = 1 if sys.platform.startswith("win") else 0 | ||
abravalheri marked this conversation as resolved.
Show resolved
Hide resolved
|
||
chmod_fn = Mock(wraps=_shutil.attempt_chmod_verbose) | ||
monkeypatch.setattr(_shutil, "attempt_chmod_verbose", chmod_fn) | ||
|
||
_shutil.rmtree(tmp_dir) | ||
assert chmod_fn.call_count == expected_count | ||
assert not tmp_dir.is_dir() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.