Skip to content

Add a --clean-cache command to clean up locations specified at CIBW_CACHE_PATH #2489

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

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions cibuildwheel/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,12 @@ def main_inner(global_options: GlobalOptions) -> None:
help="Print the build identifiers matched by the current invocation and exit.",
)

parser.add_argument(
"--clean-cache",
action="store_true",
help="Clear the cibuildwheel cache and exit.",
)

parser.add_argument(
"--allow-empty",
action="store_true",
Expand All @@ -197,6 +203,19 @@ def main_inner(global_options: GlobalOptions) -> None:

global_options.print_traceback_on_error = args.debug_traceback

if args.clean_cache:
if CIBW_CACHE_PATH.exists():
print(f"Clearing cache directory: {CIBW_CACHE_PATH}")
try:
shutil.rmtree(CIBW_CACHE_PATH)
print("Cache cleared successfully.")
except OSError as e:
print(f"Error clearing cache: {e}", file=sys.stderr)
sys.exit(1)
else:
print(f"Cache directory does not exist: {CIBW_CACHE_PATH}")
sys.exit(0)

args.package_dir = args.package_dir.resolve()

# This are always relative to the base directory, even in SDist builds
Expand Down
2 changes: 2 additions & 0 deletions cibuildwheel/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class CommandLineArguments:
allow_empty: bool
debug_traceback: bool
enable: list[str]
clean_cache: bool

@classmethod
def defaults(cls) -> Self:
Expand All @@ -77,6 +78,7 @@ def defaults(cls) -> Self:
print_build_identifiers=False,
debug_traceback=False,
enable=[],
clean_cache=False,
)


Expand Down
70 changes: 70 additions & 0 deletions unit_test/main_commands_test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import errno
import shutil
import sys

import pytest

import cibuildwheel.__main__ as main_module
from cibuildwheel.__main__ import main


def test_clean_cache_when_cache_exists(tmp_path, monkeypatch, capfd):
fake_cache_dir = (tmp_path / "cibw_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)

fake_cache_dir.mkdir(parents=True, exist_ok=True)
assert fake_cache_dir.exists()

dummy_file = fake_cache_dir / "dummy.txt"
dummy_file.write_text("hello")

monkeypatch.setattr(sys, "argv", ["cibuildwheel", "--clean-cache"])

with pytest.raises(SystemExit) as e:
main()

assert e.value.code == 0

out, err = capfd.readouterr()
assert f"Clearing cache directory: {fake_cache_dir}" in out
assert "Cache cleared successfully." in out
assert not fake_cache_dir.exists()


def test_clean_cache_when_cache_does_not_exist(tmp_path, monkeypatch, capfd):
fake_cache_dir = (tmp_path / "nonexistent_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)

monkeypatch.setattr(sys, "argv", ["cibuildwheel", "--clean-cache"])

with pytest.raises(SystemExit) as e:
main()

assert e.value.code == 0

out, err = capfd.readouterr()
assert f"Cache directory does not exist: {fake_cache_dir}" in out


def test_clean_cache_with_error(tmp_path, monkeypatch, capfd):
fake_cache_dir = (tmp_path / "cibw_cache").resolve()
monkeypatch.setattr(main_module, "CIBW_CACHE_PATH", fake_cache_dir)

fake_cache_dir.mkdir(parents=True, exist_ok=True)
assert fake_cache_dir.exists()

monkeypatch.setattr(sys, "argv", ["cibuildwheel", "--clean-cache"])

def fake_rmtree(path): # noqa: ARG001
raise OSError(errno.EACCES, "Permission denied")

monkeypatch.setattr(shutil, "rmtree", fake_rmtree)

with pytest.raises(SystemExit) as e:
main()

assert e.value.code == 1

out, err = capfd.readouterr()
assert f"Clearing cache directory: {fake_cache_dir}" in out
assert "Error clearing cache:" in err