1818PERCENT_RE = re .compile (r'\b\d{1,3}%' )
1919POSTFIX_RE = re .compile (r'\b[A-Za-z_][\w-]*=[^\s,]+' )
2020LABEL_RE = re .compile (r'[A-Za-z][\w-]*:?' )
21- ANIMATION_FRAME_SECONDS = 0.12
22- MAX_ANIMATION_FRAMES = 16
21+ ANIMATION_FRAME_SECONDS = 0.08
22+ MAX_ANIMATION_FRAMES = 24
23+ SVG_WIDTH = 1080
2324
2425
2526@dataclass (frozen = True )
@@ -39,16 +40,16 @@ class Demo:
3940import progressbar
4041
4142with progressbar.ProgressBar(
42- total=12 ,
43+ total=24 ,
4344 desc='Build',
4445 fd=sys.stdout,
4546 redirect_stdout=True,
4647 line_breaks=False,
4748 is_terminal=True,
48- term_width=64 ,
49+ term_width=112 ,
4950) as bar:
50- for step in range(12 ):
51- if step in {0, 4, 8 }:
51+ for step in range(24 ):
52+ if step in {8, 16 }:
5253 print(f'log: completed step {step}')
5354 bar.update(step + 1, force=True)
5455 time.sleep(0.005)
@@ -65,32 +66,35 @@ class Demo:
6566fd = io.StringIO()
6667multibar = progressbar.MultiBar(
6768 fd=fd,
68- total=12 ,
69+ total=24 ,
6970 initial_format=None,
7071 finished_format=None,
7172 remove_finished=None,
7273 sort_reverse=False,
73- term_width=64 ,
74+ term_width=112 ,
7475)
7576build = multibar['build']
7677test = multibar['test']
77- multibar.render(force=True, flush=True)
78- fd.seek(0)
79- fd.truncate(0)
8078terminal_control_re = re.compile(r'\\ x1b\\ [[0-9;]*[A-Za-z]')
8179
82- for step in range(12):
83- build.update(step + 1, force=True)
84- test.update(step + 1, force=True)
85- fd.seek(0)
86- fd.truncate(0)
87- multibar.render(force=True, flush=True)
80+ def emit_frame():
8881 output = terminal_control_re.sub('', fd.getvalue())
8982 for line in output.split('\\ r'):
9083 line = line.strip()
9184 if line:
9285 print(line)
9386 print('\f ', end='')
87+ fd.seek(0)
88+ fd.truncate(0)
89+
90+ multibar.render(force=True, flush=True)
91+ emit_frame()
92+
93+ for step in range(24):
94+ build.update(step + 1, force=True)
95+ test.update(step + 1, force=True)
96+ multibar.render(force=True, flush=True)
97+ emit_frame()
9498""" ,
9599 ),
96100 Demo (
@@ -105,9 +109,22 @@ class Demo:
105109 fd=sys.stdout,
106110 line_breaks=False,
107111 is_terminal=True,
108- term_width=64 ,
112+ term_width=112 ,
109113) as bar:
110- for value in (3, 7, 12, 18, 25, 31, 40, 52):
114+ for value in (
115+ 3,
116+ 7,
117+ 12,
118+ 18,
119+ 25,
120+ 31,
121+ 40,
122+ 52,
123+ 67,
124+ 83,
125+ 101,
126+ 124,
127+ ):
111128 bar.update(value, force=True)
112129""" ,
113130 ),
@@ -119,26 +136,19 @@ class Demo:
119136import progressbar
120137
121138with progressbar.ProgressBar(
122- total=4096 ,
139+ total=8192 ,
123140 desc='Items',
124141 unit='B',
125142 unit_scale=True,
126143 postfix={'loss': '1.0'},
127144 fd=sys.stdout,
128145 line_breaks=False,
129146 is_terminal=True,
130- term_width=72 ,
147+ term_width=112 ,
131148) as bar:
132- for value, loss in (
133- (256, '0.9'),
134- (512, '0.8'),
135- (768, '0.7'),
136- (1024, '0.6'),
137- (1536, '0.5'),
138- (2048, '0.4'),
139- (3072, '0.2'),
140- (4096, '0.1'),
141- ):
149+ for step in range(24):
150+ value = int(8192 * (step + 1) / 24)
151+ loss = f'{1 - ((step + 1) / 24):.2f}'
142152 bar.update(value, postfix={'loss': loss}, force=True)
143153""" ,
144154 ),
@@ -186,14 +196,26 @@ def frames_from_output(output: str) -> list[list[str]]:
186196 ]
187197 if lines :
188198 frames .append (lines )
189- return frames [ - MAX_ANIMATION_FRAMES :] or [['No output captured' ]]
199+ return limit_animation_frames ( frames ) or [['No output captured' ]]
190200
191201 for raw_frame in output .splitlines ():
192202 for part in raw_frame .split ('\r ' ):
193203 line = part .strip ()
194204 if line :
195205 frames .append ([normalize_terminal_line (line )])
196- return frames [- MAX_ANIMATION_FRAMES :] or [['No output captured' ]]
206+ return limit_animation_frames (frames ) or [['No output captured' ]]
207+
208+
209+ def limit_animation_frames (frames : list [list [str ]]) -> list [list [str ]]:
210+ if len (frames ) <= MAX_ANIMATION_FRAMES :
211+ return frames
212+
213+ last_index = len (frames ) - 1
214+ selected = [
215+ round (index * last_index / (MAX_ANIMATION_FRAMES - 1 ))
216+ for index in range (MAX_ANIMATION_FRAMES )
217+ ]
218+ return [frames [index ] for index in selected ]
197219
198220
199221def tspan (text : str , class_name : str | None = None ) -> str :
@@ -272,7 +294,7 @@ def styled_terminal_line(line: str) -> str:
272294
273295
274296def svg_document (title : str , frames : list [list [str ]]) -> str :
275- width = 760
297+ width = SVG_WIDTH
276298 line_height = 24
277299 max_lines = max (len (frame ) for frame in frames )
278300 height = 72 + max_lines * line_height
0 commit comments