From 46730d1661d1862ba10e44a0ef826aac985d46af Mon Sep 17 00:00:00 2001 From: BoulderBadgeDad Date: Sun, 7 Jun 2026 22:13:30 -0700 Subject: [PATCH] Expired Cleaner: rename the safety toggle to dry_run (default ON), matching Re-tag MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The destructive job's findings-vs-auto toggle was 'auto_delete: False'. Renamed to 'dry_run: True' to match the Re-tag job's convention and make the safe default unmistakable: dry run ON (default) = findings only, deletes nothing; dry run OFF = hands-off auto-delete. Behaviour-identical to the previous default — just clearer + consistent. Help text + tests updated. --- core/repair_jobs/expired_download_cleaner.py | 17 +++++++++-------- tests/test_expired_download_cleaner.py | 12 ++++++++++-- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/core/repair_jobs/expired_download_cleaner.py b/core/repair_jobs/expired_download_cleaner.py index bc5fd02a..bde39299 100644 --- a/core/repair_jobs/expired_download_cleaner.py +++ b/core/repair_jobs/expired_download_cleaner.py @@ -69,12 +69,13 @@ class ExpiredDownloadCleanerJob(RepairJob): 'fewer than the keep-threshold (default: played more than once is kept). ' 'It only touches downloads recorded from the Download Origins feature ' 'forward — never your pre-existing or manually-added library.\n\n' - 'By default it creates findings for you to review and delete. Set ' - 'Auto-delete to true for hands-off cleanup.\n\n' + 'Dry run is ON by default: it only creates findings for you to review ' + 'and delete — nothing is deleted automatically. Turn Dry run OFF for ' + 'hands-off auto-cleanup.\n\n' 'Settings:\n' '- Watchlist retention / Playlist retention: off, or a window\n' '- Keep if played at least: play count that protects a track (default 2)\n' - '- Auto-delete: delete automatically instead of creating findings' + '- Dry run: ON = findings only (default); OFF = delete automatically' ) icon = 'repair-icon-cleanup' default_enabled = False @@ -83,12 +84,12 @@ class ExpiredDownloadCleanerJob(RepairJob): 'watchlist_retention': 'off', 'playlist_retention': 'off', 'keep_if_played_at_least': 2, - 'auto_delete': False, + 'dry_run': True, } setting_options = { 'watchlist_retention': RETENTION_OPTIONS, 'playlist_retention': RETENTION_OPTIONS, - 'auto_delete': [False, True], + 'dry_run': [True, False], } auto_fix = False @@ -110,7 +111,7 @@ class ExpiredDownloadCleanerJob(RepairJob): min_plays = int(settings.get('keep_if_played_at_least', 2)) except (TypeError, ValueError): min_plays = 2 - auto_delete = bool(settings.get('auto_delete', False)) + dry_run = bool(settings.get('dry_run', True)) candidates = context.db.get_origin_cleanup_candidates() if not candidates: @@ -150,7 +151,7 @@ class ExpiredDownloadCleanerJob(RepairJob): for i, entry in enumerate(expired): if context.check_stop(): return result - if auto_delete: + if not dry_run: try: res = delete_origin_download(context.db, entry, context.config_manager) if res.get('removed') or res.get('file_deleted'): @@ -191,7 +192,7 @@ class ExpiredDownloadCleanerJob(RepairJob): logger.info("[Expired Cleaner] %d candidates, %d expired (%s)", len(candidates), len(expired), - "auto-deleted" if auto_delete else "findings created") + "findings created (dry run)" if dry_run else "auto-deleted") return result def estimate_scope(self, context: JobContext) -> int: diff --git a/tests/test_expired_download_cleaner.py b/tests/test_expired_download_cleaner.py index 740d9fae..60ffe0bd 100644 --- a/tests/test_expired_download_cleaner.py +++ b/tests/test_expired_download_cleaner.py @@ -104,11 +104,19 @@ def test_scan_protects_watched_artist(): assert findings == [] # still watched → protected -def test_scan_auto_delete_mode(): +def test_scan_dry_run_default_is_findings_only(): + # No dry_run in settings → defaults to True → findings, never deletes. + db = _DB([_cand(1, created=OLD, path="/music/x.flac")]) + findings = [] + res = ExpiredDownloadCleanerJob().scan(_ctx(db, {'playlist_retention': '2mo'}, findings)) + assert res.findings_created == 1 and db.deleted_history == [] # nothing deleted + + +def test_scan_auto_delete_when_dry_run_off(): db = _DB([_cand(1, created=OLD, path="/music/x.flac")]) findings = [] res = ExpiredDownloadCleanerJob().scan(_ctx( - db, {'playlist_retention': '2mo', 'auto_delete': True}, findings)) + db, {'playlist_retention': '2mo', 'dry_run': False}, findings)) assert findings == [] # no findings in auto mode assert res.auto_fixed == 1 assert 1 in db.deleted_history # history row removed