diff --git a/main.py b/main.py index c4d40521..c835ff1b 100644 --- a/main.py +++ b/main.py @@ -2403,7 +2403,10 @@ def parse_args() -> argparse.Namespace: Supports profile IDs, folder URLs, dry-run mode, no-delete flag, and plan JSON output file path. """ - parser = argparse.ArgumentParser(description="Control D folder sync") + parser = argparse.ArgumentParser( + description="✨ Control D Sync: Keep your folders in sync with remote blocklists.", + epilog="Run with --dry-run first to preview changes safely. Made with ❤️ for Control D users.", + ) parser.add_argument( "--profiles", help="Comma-separated list of profile IDs", default=None ) @@ -2727,6 +2730,41 @@ def make_col_separator(left, mid, right, horiz): "🌈 Perfect harmony!", ] print(f"\n{Colors.GREEN}{random.choice(success_msgs)}{Colors.ENDC}") + + # Dry Run Next Steps + if args.dry_run: + print() # Spacer + if all_success: + # Build the suggested command once so it stays consistent between + # color and non-color output modes. + cmd_parts = ["python", "main.py"] + if profile_ids: + # Join multiple profiles if needed + p_str = ",".join(profile_ids) + else: + p_str = "" + cmd_parts.append(f"--profiles {p_str}") + + # Reconstruct other args if they were used (optional but helpful) + if args.folder_url: + for url in args.folder_url: + cmd_parts.append(f"--folder-url {url}") + + cmd_str = " ".join(cmd_parts) + + if USE_COLORS: + print(f"{Colors.BOLD}👉 Ready to sync? Run the following command:{Colors.ENDC}") + print(f" {Colors.CYAN}{cmd_str}{Colors.ENDC}") + else: + print("👉 Ready to sync? Run the following command:") + print(f" {cmd_str}") + else: + if USE_COLORS: + print( + f"{Colors.FAIL}⚠️ Dry run encountered errors. Please check the logs above.{Colors.ENDC}" + ) + else: + print("⚠️ Dry run encountered errors. Please check the logs above.") # Display API statistics total_api_calls = _api_stats["control_d_api_calls"] + _api_stats["blocklist_fetches"] diff --git a/tests/test_retry_jitter.py b/tests/test_retry_jitter.py index 47bcfb9b..9c59eb32 100644 --- a/tests/test_retry_jitter.py +++ b/tests/test_retry_jitter.py @@ -123,6 +123,7 @@ def test_four_hundred_errors_still_fail_fast(self): def test_429_rate_limit_retries_with_jitter(self): """Verify 429 rate limit errors retry with jittered backoff.""" response = Mock(status_code=429) + # Ensure headers is a dict so .get() works properly and returns None instead of a Mock response.headers = {} error = httpx.HTTPStatusError( "Too many requests",