-
Notifications
You must be signed in to change notification settings - Fork 1
π¨ Palette: Add progress bar for fetching existing rules #156
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| # Palette's Journal | ||
|
|
||
| ## 2024-10-24 - Progress Bar in Parallel Tasks | ||
| **Learning:** When using `concurrent.futures`, standard logging can interfere with progress bars. The `render_progress_bar` implementation relies on `\r` to overwrite the line, but if another thread logs to stderr/stdout, it can break the visual. | ||
| **Action:** Always wrap logging calls inside the parallel loop with a line-clearing sequence (`\r\033[K`) if a progress bar is active. | ||
|
|
||
| ## 2024-10-24 - Duplicate Function Definitions | ||
| **Learning:** Duplicate function definitions in Python (later overwrites earlier) can be confusing for static analysis or human reviewers, even if the runtime behavior is well-defined. | ||
| **Action:** Always scan for and remove duplicate definitions when refactoring to avoid confusion. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -159,23 +159,6 @@ | |
| return safe | ||
|
|
||
|
|
||
| def render_progress_bar( | ||
| current: int, total: int, label: str, prefix: str = "π" | ||
| ) -> None: | ||
| if not USE_COLORS or total == 0: | ||
| return | ||
|
|
||
| width = 20 | ||
| progress = min(1.0, current / total) | ||
| filled = int(width * progress) | ||
| bar = "β" * filled + "β" * (width - filled) | ||
| percent = int(progress * 100) | ||
|
|
||
| # Use \033[K to clear line residue | ||
| sys.stderr.write( | ||
| f"\r\033[K{Colors.CYAN}{prefix} {label}: [{bar}] {percent}% ({current}/{total}){Colors.ENDC}" | ||
| ) | ||
| sys.stderr.flush() | ||
|
|
||
|
|
||
| def countdown_timer(seconds: int, message: str = "Waiting") -> None: | ||
|
|
@@ -677,21 +660,39 @@ | |
|
|
||
| # Parallelize fetching rules from folders. | ||
| # Using 5 workers to be safe with rate limits, though GETs are usually cheaper. | ||
| total_folders = len(folders) | ||
| completed_folders = 0 | ||
| render_progress_bar(0, total_folders, "Fetching existing rules", prefix="π") | ||
|
|
||
| with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: | ||
| future_to_folder = { | ||
| executor.submit(_fetch_folder_rules, folder_id): folder_id | ||
| for folder_name, folder_id in folders.items() | ||
| } | ||
|
|
||
| for future in concurrent.futures.as_completed(future_to_folder): | ||
| completed_folders += 1 | ||
| try: | ||
| result = future.result() | ||
| if result: | ||
| all_rules.update(result) | ||
| except Exception as e: | ||
| if USE_COLORS: | ||
| # Clear line to print warning cleanly | ||
| sys.stderr.write("\r\033[K") | ||
| sys.stderr.flush() | ||
|
|
||
| folder_id = future_to_folder[future] | ||
| log.warning(f"Failed to fetch rules for folder ID {folder_id}: {e}") | ||
|
|
||
| render_progress_bar( | ||
| completed_folders, total_folders, "Fetching existing rules", prefix="π" | ||
| ) | ||
|
|
||
| if USE_COLORS: | ||
| sys.stderr.write(f"\r\033[K") | ||
Check noticeCode scanning / Pylintpython3 (reported by Codacy) Using an f-string that does not have any interpolated variables Note
Using an f-string that does not have any interpolated variables
|
||
| sys.stderr.flush() | ||
|
Comment on lines
667
to
+694
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. To ensure the progress bar line is always cleared, even if an error occurs during the fetching process (like a try:
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
future_to_folder = {
executor.submit(_fetch_folder_rules, folder_id): folder_id
for folder_name, folder_id in folders.items()
}
for future in concurrent.futures.as_completed(future_to_folder):
completed_folders += 1
try:
result = future.result()
if result:
all_rules.update(result)
except Exception as e:
if USE_COLORS:
# Clear line to print warning cleanly
sys.stderr.write("\r\033[K")
sys.stderr.flush()
folder_id = future_to_folder[future]
log.warning(f"Failed to fetch rules for folder ID {folder_id}: {e}")
render_progress_bar(
completed_folders, total_folders, "Fetching existing rules", prefix="π"
)
finally:
if USE_COLORS:
sys.stderr.write(f"\r\033[K")
sys.stderr.flush() |
||
|
|
||
| log.info(f"Total existing rules across all folders: {len(all_rules)}") | ||
| return all_rules | ||
| except Exception as e: | ||
|
|
||
Check warning
Code scanning / Prospector (reported by Codacy)
Using an f-string that does not have any interpolated variables (f-string-without-interpolation) Warning