Skip to content
Open
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
1 change: 1 addition & 0 deletions pyclean/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ def parse_arguments():
if args.yes and not args.erase and not args.git_clean:
parser.error('Specifying --yes only makes sense with --erase or --git-clean.')

args.debris_without_topics = 'debris' in args and not args.debris
if 'debris' in args:
if 'all' in args.debris:
args.debris = debris_default_topics + debris_optional_topics
Expand Down
22 changes: 22 additions & 0 deletions pyclean/debris.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,25 @@ def suggest_debris_option(args):
'Hint: Use --debris to also clean up build artifacts '
'from common Python development tools.',
)


def suggest_optional_debris_topics(args):
"""Suggest optional topics when --debris was used without topic arguments."""
detected_topics = set()
for dir_name in args.directory:
dir_path = Path(dir_name)
if dir_path.exists():
detected_topics.update(detect_debris_in_directory(dir_path))

optional_detected = sorted(detected_topics - set(args.debris))
if optional_detected:
log.info(
'Hint: Use --debris all or specify optional topics to clean up '
'more aggressively. Detected: %s',
' '.join(optional_detected),
)
else:
log.info(
'Hint: Use --debris all or specify optional topics to clean up '
'more aggressively.',
)
8 changes: 7 additions & 1 deletion pyclean/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@
from pathlib import Path

from .bytecode import BYTECODE_DIRS, BYTECODE_FILES
from .debris import remove_debris_for, suggest_debris_option
from .debris import (
remove_debris_for,
suggest_debris_option,
suggest_optional_debris_topics,
)
from .erase import remove_freeform_targets
from .folders import remove_empty_directories
from .gitclean import execute_git_clean
Expand Down Expand Up @@ -67,3 +71,5 @@ def pyclean(args):

if not args.debris:
suggest_debris_option(args)
elif getattr(args, 'debris_without_topics', False):
suggest_optional_debris_topics(args)
2 changes: 2 additions & 0 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ def test_debris_default_args():
args = pyclean.cli.parse_arguments()

assert args.debris == ['cache', 'coverage', 'package', 'pytest', 'ruff']
assert args.debris_without_topics


def test_debris_optional_args():
Expand Down Expand Up @@ -192,6 +193,7 @@ def test_debris_explicit_args():
args = pyclean.cli.parse_arguments()

assert args.debris == ['package', 'pytest']
assert not args.debris_without_topics


def test_debris_invalid_args():
Expand Down
51 changes: 48 additions & 3 deletions tests/test_debris.py
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,59 @@ def test_suggest_debris_with_artifacts(mock_descend, mock_log):
@patch('pyclean.main.descend_and_clean')
def test_no_suggest_debris_when_used(mock_descend, mock_log):
"""
Does pyclean NOT suggest --debris when it's already used?
Does pyclean avoid suggesting the base --debris option when it's already used?
"""
with TemporaryDirectory() as tmp, ArgvContext('pyclean', tmp, '--debris'):
pyclean.cli.main()

# Check that the suggestion was NOT logged
# The base hint is replaced by the optional-topics hint.
log_info_calls = [str(call) for call in mock_log.info.call_args_list]
assert not any('Hint: Use --debris' in msg for msg in log_info_calls)
assert not any(
'Hint: Use --debris to also clean up' in msg for msg in log_info_calls
)
assert any('Hint: Use --debris all' in msg for msg in log_info_calls)


@pytest.mark.parametrize('option', ['-d', '--debris'])
@patch('pyclean.debris.log')
def test_suggest_optional_debris_topics(mock_log, option):
"""Does bare --debris identify optional topics left behind?"""
with TemporaryDirectory() as tmp:
directory = Path(tmp)
(directory / '.ipynb_checkpoints').mkdir()
(directory / '.mypy_cache').mkdir()
(directory / '.pytest_cache').mkdir()

with ArgvContext('pyclean', tmp, option):
pyclean.cli.main()

mock_log.info.assert_called_once_with(
'Hint: Use --debris all or specify optional topics to clean up '
'more aggressively. Detected: %s',
'jupyter mypy',
)


@patch('pyclean.debris.log')
def test_suggest_optional_debris_topics_without_artifacts(mock_log):
"""Does bare --debris still explain how to include optional topics?"""
with TemporaryDirectory() as tmp, ArgvContext('pyclean', tmp, '--debris'):
pyclean.cli.main()

mock_log.info.assert_called_once_with(
'Hint: Use --debris all or specify optional topics to clean up '
'more aggressively.',
)


@pytest.mark.parametrize('topic', ['mypy', 'all'])
@patch('pyclean.debris.log')
def test_no_optional_hint_with_explicit_debris_topics(mock_log, topic):
"""Does an explicit choice suppress the optional topic hint?"""
with TemporaryDirectory() as tmp, ArgvContext('pyclean', tmp, '-d', topic):
pyclean.cli.main()

mock_log.info.assert_not_called()


def test_ignore_with_debris_cleanup():
Expand Down
Loading