mirror of
https://github.com/ArchiveBox/ArchiveBox.git
synced 2025-05-13 06:34:25 -04:00
logarithmic progress bars woohoo
This commit is contained in:
parent
ac9e0e356d
commit
b8bbb75f9c
2 changed files with 30 additions and 11 deletions
|
@ -48,7 +48,7 @@ CONFIG_DEFAULTS: Dict[str, ConfigDefaultDict] = {
|
||||||
'SHELL_CONFIG': {
|
'SHELL_CONFIG': {
|
||||||
'IS_TTY': {'type': bool, 'default': lambda _: sys.stdout.isatty()},
|
'IS_TTY': {'type': bool, 'default': lambda _: sys.stdout.isatty()},
|
||||||
'USE_COLOR': {'type': bool, 'default': lambda c: c['IS_TTY']},
|
'USE_COLOR': {'type': bool, 'default': lambda c: c['IS_TTY']},
|
||||||
'SHOW_PROGRESS': {'type': bool, 'default': lambda c: False if platform.system() == 'Darwin' else c['IS_TTY']}, # TODO: remove this temporary hack once progress bars are fixed on macOS
|
'SHOW_PROGRESS': {'type': bool, 'default': lambda c: c['IS_TTY']},
|
||||||
'IN_DOCKER': {'type': bool, 'default': False},
|
'IN_DOCKER': {'type': bool, 'default': False},
|
||||||
# TODO: 'SHOW_HINTS': {'type: bool, 'default': True},
|
# TODO: 'SHOW_HINTS': {'type: bool, 'default': True},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,7 +4,9 @@ import re
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
import platform
|
||||||
import argparse
|
import argparse
|
||||||
|
from math import log
|
||||||
from multiprocessing import Process
|
from multiprocessing import Process
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
@ -99,10 +101,24 @@ class TimedProgress:
|
||||||
if self.SHOW_PROGRESS:
|
if self.SHOW_PROGRESS:
|
||||||
# terminate if we havent already terminated
|
# terminate if we havent already terminated
|
||||||
try:
|
try:
|
||||||
|
# WARNING: HACKY
|
||||||
|
# I've spent over 15 hours trying to get rid of this stupid macOS-only
|
||||||
|
# intermittent (but harmeless) warning when the progress bars end sometimes
|
||||||
|
# Exception ignored in: <_io.TextIOWrapper name='<stdout>' mode='w' encoding='utf-8'>
|
||||||
|
# BrokenPipeError: [Errno 32] Broken pipe
|
||||||
|
# In the end, this is the only thing I found that makes it
|
||||||
|
# happen slightly less often:
|
||||||
|
if platform.system() == 'Darwin':
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# kill the progress bar subprocess
|
||||||
self.p.terminate()
|
self.p.terminate()
|
||||||
self.p.join()
|
self.p.join()
|
||||||
self.p.close()
|
self.p.close()
|
||||||
|
|
||||||
|
if platform.system() == 'Darwin':
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
# clear whole terminal line
|
# clear whole terminal line
|
||||||
try:
|
try:
|
||||||
sys.stdout.write('\r{}{}\r'.format((' ' * TERM_WIDTH()), ANSI['reset']))
|
sys.stdout.write('\r{}{}\r'.format((' ' * TERM_WIDTH()), ANSI['reset']))
|
||||||
|
@ -128,17 +144,18 @@ def progress_bar(seconds: int, prefix: str='') -> None:
|
||||||
sys.stdout.write('\r\n')
|
sys.stdout.write('\r\n')
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
chunks = max_width - len(prefix) - 20
|
chunks = max_width - len(prefix) - 20
|
||||||
progress = s / chunks / seconds * 100
|
pct_complete = s / chunks / seconds * 100
|
||||||
bar_width = round(progress/(100/chunks))
|
log_pct = (log(pct_complete or 1, 10) / 2) * 100 # everyone likes faster progress bars ;)
|
||||||
|
bar_width = round(log_pct/(100/chunks))
|
||||||
last_width = max_width
|
last_width = max_width
|
||||||
|
|
||||||
# ████████████████████ 0.9% (1/60sec)
|
# ████████████████████ 0.9% (1/60sec)
|
||||||
sys.stdout.write('\r{0}{1}{2}{3} {4}% ({5}/{6}sec)'.format(
|
sys.stdout.write('\r{0}{1}{2}{3} {4}% ({5}/{6}sec)'.format(
|
||||||
prefix,
|
prefix,
|
||||||
ANSI['green'],
|
ANSI['green' if pct_complete < 80 else 'lightyellow'],
|
||||||
(chunk * bar_width).ljust(chunks),
|
(chunk * bar_width).ljust(chunks),
|
||||||
ANSI['reset'],
|
ANSI['reset'],
|
||||||
round(progress, 1),
|
round(pct_complete, 1),
|
||||||
round(s/chunks),
|
round(s/chunks),
|
||||||
seconds,
|
seconds,
|
||||||
))
|
))
|
||||||
|
@ -146,7 +163,7 @@ def progress_bar(seconds: int, prefix: str='') -> None:
|
||||||
time.sleep(1 / chunks)
|
time.sleep(1 / chunks)
|
||||||
|
|
||||||
# ██████████████████████████████████ 100.0% (60/60sec)
|
# ██████████████████████████████████ 100.0% (60/60sec)
|
||||||
sys.stdout.write('\r{0}{1}{2}{3} {4}% ({5}/{6}sec)\n'.format(
|
sys.stdout.write('\r{0}{1}{2}{3} {4}% ({5}/{6}sec)'.format(
|
||||||
prefix,
|
prefix,
|
||||||
ANSI['red'],
|
ANSI['red'],
|
||||||
chunk * chunks,
|
chunk * chunks,
|
||||||
|
@ -156,6 +173,10 @@ def progress_bar(seconds: int, prefix: str='') -> None:
|
||||||
seconds,
|
seconds,
|
||||||
))
|
))
|
||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
|
# uncomment to have it disappear when it hits 100% instead of staying full red:
|
||||||
|
# time.sleep(0.5)
|
||||||
|
# sys.stdout.write('\r{}{}\r'.format((' ' * TERM_WIDTH()), ANSI['reset']))
|
||||||
|
# sys.stdout.flush()
|
||||||
except (KeyboardInterrupt, BrokenPipeError):
|
except (KeyboardInterrupt, BrokenPipeError):
|
||||||
print()
|
print()
|
||||||
pass
|
pass
|
||||||
|
@ -242,7 +263,7 @@ def log_archiving_started(num_links: int, resume: Optional[float]=None):
|
||||||
**ANSI,
|
**ANSI,
|
||||||
))
|
))
|
||||||
else:
|
else:
|
||||||
print('{green}[▶] [{}] Collecting content for {} Snapshots in archive...{reset}'.format(
|
print('{green}[▶] [{}] Starting archiving of {} snapshots in index...{reset}'.format(
|
||||||
start_ts.strftime('%Y-%m-%d %H:%M:%S'),
|
start_ts.strftime('%Y-%m-%d %H:%M:%S'),
|
||||||
num_links,
|
num_links,
|
||||||
**ANSI,
|
**ANSI,
|
||||||
|
@ -287,10 +308,8 @@ def log_archiving_finished(num_links: int):
|
||||||
print(' - {} links updated'.format(_LAST_RUN_STATS.succeeded + _LAST_RUN_STATS.failed))
|
print(' - {} links updated'.format(_LAST_RUN_STATS.succeeded + _LAST_RUN_STATS.failed))
|
||||||
print(' - {} links had errors'.format(_LAST_RUN_STATS.failed))
|
print(' - {} links had errors'.format(_LAST_RUN_STATS.failed))
|
||||||
print()
|
print()
|
||||||
print(' {lightred}Hint:{reset} To view your archive index, run:'.format(**ANSI))
|
print(' {lightred}Hint:{reset} To manage your archive in a Web UI, run:'.format(**ANSI))
|
||||||
print(' archivebox server # then visit http://127.0.0.1:8000')
|
print(' archivebox server 0.0.0.0:8000')
|
||||||
print(' Or run the built-in webserver:')
|
|
||||||
print(' archivebox server')
|
|
||||||
|
|
||||||
|
|
||||||
def log_link_archiving_started(link: "Link", link_dir: str, is_new: bool):
|
def log_link_archiving_started(link: "Link", link_dir: str, is_new: bool):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue