Skip to content

Commit e358782

Browse files
authored
Merge pull request #3867 from boegel/robust_update_progress_bar
make update_progress_bar a bit more robust by just doing nothing if the corresponding progress bar was not started (and making stopping of a non-started progress bar fatal)
2 parents 4cde629 + a7a970a commit e358782

File tree

2 files changed

+72
-22
lines changed

2 files changed

+72
-22
lines changed

easybuild/tools/output.py

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -250,22 +250,15 @@ def extensions_progress_bar():
250250
return progress_bar
251251

252252

253-
def get_progress_bar(bar_type, size=None):
253+
def get_progress_bar(bar_type, ignore_cache=False, size=None):
254254
"""
255255
Get progress bar of given type.
256256
"""
257-
progress_bar_types = {
258-
PROGRESS_BAR_DOWNLOAD_ALL: download_all_progress_bar,
259-
PROGRESS_BAR_DOWNLOAD_ONE: download_one_progress_bar,
260-
PROGRESS_BAR_EXTENSIONS: extensions_progress_bar,
261-
PROGRESS_BAR_EASYCONFIG: easyconfig_progress_bar,
262-
STATUS_BAR: status_bar,
263-
}
264257

265258
if bar_type == PROGRESS_BAR_DOWNLOAD_ONE and not size:
266-
pbar = download_one_progress_bar_unknown_size()
267-
elif bar_type in progress_bar_types:
268-
pbar = progress_bar_types[bar_type]()
259+
pbar = download_one_progress_bar_unknown_size(ignore_cache=ignore_cache)
260+
elif bar_type in PROGRESS_BAR_TYPES:
261+
pbar = PROGRESS_BAR_TYPES[bar_type](ignore_cache=ignore_cache)
269262
else:
270263
raise EasyBuildError("Unknown progress bar type: %s", bar_type)
271264

@@ -295,27 +288,31 @@ def start_progress_bar(bar_type, size, label=None):
295288

296289
def update_progress_bar(bar_type, label=None, progress_size=1):
297290
"""
298-
Update progress bar of given type, add progress of given size.
291+
Update progress bar of given type (if it was started), add progress of given size.
299292
300293
:param bar_type: type of progress bar
301294
:param label: label for progress bar
302295
:param progress_size: amount of progress made
303296
"""
304-
(pbar, task_id) = _progress_bar_cache[bar_type]
305-
if label:
306-
pbar.update(task_id, description=label)
307-
if progress_size:
308-
pbar.update(task_id, advance=progress_size)
297+
if bar_type in _progress_bar_cache:
298+
(pbar, task_id) = _progress_bar_cache[bar_type]
299+
if label:
300+
pbar.update(task_id, description=label)
301+
if progress_size:
302+
pbar.update(task_id, advance=progress_size)
309303

310304

311305
def stop_progress_bar(bar_type, visible=False):
312306
"""
313307
Stop progress bar of given type.
314308
"""
315-
(pbar, task_id) = _progress_bar_cache[bar_type]
316-
pbar.stop_task(task_id)
317-
if not visible:
318-
pbar.update(task_id, visible=False)
309+
if bar_type in _progress_bar_cache:
310+
(pbar, task_id) = _progress_bar_cache[bar_type]
311+
pbar.stop_task(task_id)
312+
if not visible:
313+
pbar.update(task_id, visible=False)
314+
else:
315+
raise EasyBuildError("Failed to stop %s progress bar, since it was never started?!", bar_type)
319316

320317

321318
def print_checks(checks_data):
@@ -384,3 +381,13 @@ def print_checks(checks_data):
384381
console_print(table)
385382
else:
386383
print('\n'.join(lines))
384+
385+
386+
# this constant must be defined at the end, since functions used as values need to be defined
387+
PROGRESS_BAR_TYPES = {
388+
PROGRESS_BAR_DOWNLOAD_ALL: download_all_progress_bar,
389+
PROGRESS_BAR_DOWNLOAD_ONE: download_one_progress_bar,
390+
PROGRESS_BAR_EXTENSIONS: extensions_progress_bar,
391+
PROGRESS_BAR_EASYCONFIG: easyconfig_progress_bar,
392+
STATUS_BAR: status_bar,
393+
}

test/framework/output.py

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,12 @@
3131
from unittest import TextTestRunner
3232
from test.framework.utilities import EnhancedTestCase, TestLoaderFiltered
3333

34+
import easybuild.tools.output
3435
from easybuild.tools.build_log import EasyBuildError
3536
from easybuild.tools.config import build_option, get_output_style, update_build_option
36-
from easybuild.tools.output import DummyRich, colorize, show_progress_bars, status_bar, use_rich
37+
from easybuild.tools.output import PROGRESS_BAR_EXTENSIONS, PROGRESS_BAR_TYPES
38+
from easybuild.tools.output import DummyRich, colorize, get_progress_bar, show_progress_bars
39+
from easybuild.tools.output import start_progress_bar, status_bar, stop_progress_bar, update_progress_bar, use_rich
3740

3841
try:
3942
import rich.progress
@@ -138,6 +141,46 @@ def test_colorize(self):
138141

139142
self.assertErrorRegex(EasyBuildError, "Unknown color: nosuchcolor", colorize, 'test', 'nosuchcolor')
140143

144+
def test_get_progress_bar(self):
145+
"""
146+
Test get_progress_bar.
147+
"""
148+
# restore default configuration to show progress bars (disabled to avoid mangled test output),
149+
# to ensure we'll get actual Progress instances when Rich is available
150+
update_build_option('show_progress_bar', True)
151+
152+
for pbar_type in PROGRESS_BAR_TYPES:
153+
pbar = get_progress_bar(pbar_type, ignore_cache=True)
154+
if HAVE_RICH:
155+
self.assertTrue(isinstance(pbar, rich.progress.Progress))
156+
else:
157+
self.assertTrue(isinstance(pbar, DummyRich))
158+
159+
def test_get_start_update_stop_progress_bar(self):
160+
"""
161+
Test starting/updating/stopping of progress bars.
162+
"""
163+
# clear progress bar cache first, this test assumes we start with a clean slate
164+
easybuild.tools.output._progress_bar_cache.clear()
165+
166+
# restore default configuration to show progress bars (disabled to avoid mangled test output)
167+
update_build_option('show_progress_bar', True)
168+
169+
# stopping a progress bar that never was started results in an error
170+
error_pattern = "Failed to stop extensions progress bar, since it was never started"
171+
self.assertErrorRegex(EasyBuildError, error_pattern, stop_progress_bar, PROGRESS_BAR_EXTENSIONS)
172+
173+
# updating a progress bar that never was started is silently ignored on purpose
174+
update_progress_bar(PROGRESS_BAR_EXTENSIONS)
175+
update_progress_bar(PROGRESS_BAR_EXTENSIONS, label="foo")
176+
update_progress_bar(PROGRESS_BAR_EXTENSIONS, progress_size=100)
177+
178+
# also test normal cycle: start, update, stop
179+
start_progress_bar(PROGRESS_BAR_EXTENSIONS, 100)
180+
update_progress_bar(PROGRESS_BAR_EXTENSIONS) # single step progress
181+
update_progress_bar(PROGRESS_BAR_EXTENSIONS, label="test123", progress_size=5)
182+
stop_progress_bar(PROGRESS_BAR_EXTENSIONS)
183+
141184

142185
def suite():
143186
""" returns all the testcases in this module """

0 commit comments

Comments
 (0)