Skip to content

Commit 8430037

Browse files
committed
fix progress-update throttling logic
1 parent 8ebd272 commit 8430037

File tree

2 files changed

+22
-34
lines changed

2 files changed

+22
-34
lines changed

src/xulbux/console.py

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,7 @@ def __init__(
13201320
self._current_progress_str: str = ""
13211321
self._last_line_len: int = 0
13221322
self._last_update_time: float = 0.0
1323-
self._min_update_interval: float = 0.05 # 50ms = 20 UPDATES/SECOND MAX
1323+
self._min_update_interval: float = 0.02 # 20ms = MAX 50 UPDATES/SECOND
13241324

13251325
def set_width(self, min_width: Optional[int] = None, max_width: Optional[int] = None) -> None:
13261326
"""Set the width of the progress bar.\n
@@ -1396,9 +1396,9 @@ def show_progress(self, current: int, total: int, label: Optional[str] = None) -
13961396
if not isinstance(total, int):
13971397
raise TypeError(f"The 'total' parameter must be an integer, got {type(total)}")
13981398

1399-
# THROTTLE UPDATES (UNLESS IT'S THE FINAL UPDATE)
1399+
# THROTTLE UPDATES (UNLESS IT'S THE FIRST/FINAL UPDATE)
14001400
current_time = _time.time()
1401-
if not (current >= total or current < 0) \
1401+
if not (self._last_update_time == 0.0 or current >= total or current < 0) \
14021402
and (current_time - self._last_update_time) < self._min_update_interval:
14031403
return
14041404
self._last_update_time = current_time
@@ -1466,49 +1466,37 @@ def progress_context(self, total: int, label: Optional[str] = None) -> Generator
14661466
try:
14671467

14681468
def update_progress(*args, **kwargs) -> None: # TYPE HINTS DEFINED IN 'ProgressUpdater' PROTOCOL
1469-
"""Update the progress bar's current value and/or label."""
1469+
"""Update the progress bar's current value and/or label.\n
1470+
-----------------------------------------------------------
1471+
`current` -⠀the current progress value
1472+
`label` -⠀the progress label
1473+
`type_checking` -⠀whether to check the parameters' types:
1474+
Is false per default to save performance, but can be set
1475+
to true for debugging purposes."""
14701476
nonlocal current_progress, current_label
1471-
current = label = None
1477+
current, label = None, None
14721478

1473-
# PARSE ARGUMENTS FIRST
1474-
if len(args) > 2:
1475-
raise TypeError(f"update_progress() takes at most 2 positional arguments, got {len(args)}")
1476-
elif len(args) >= 1:
1479+
if (num_args := len(args)) == 1:
14771480
current = args[0]
1478-
if len(args) >= 2:
1479-
label = args[1]
1481+
elif num_args == 2:
1482+
current, label = args[0], args[1]
1483+
else:
1484+
raise TypeError(f"update_progress() takes 1 or 2 positional arguments, got {len(args)}")
14801485

1481-
if "current" in kwargs:
1482-
if current is not None:
1483-
raise TypeError("update_progress() got multiple values for argument 'current'.")
1486+
if current is not None and "current" in kwargs:
14841487
current = kwargs["current"]
1485-
if "label" in kwargs:
1486-
if label is not None:
1487-
raise TypeError("update_progress() got multiple values for argument 'label'.")
1488+
if label is None and "label" in kwargs:
14881489
label = kwargs["label"]
14891490

1490-
if unexpected := set(kwargs.keys()) - {"current", "label"}:
1491-
raise TypeError(f"update_progress() got unexpected keyword arguments: {', '.join(unexpected)}")
1492-
14931491
if current is None and label is None:
14941492
raise TypeError("Either the keyword argument 'current' or 'label' must be provided.")
14951493

1496-
# VALIDATE AND UPDATE VALUES
14971494
if current is not None:
1498-
if not isinstance(current, int):
1499-
raise TypeError(f"The 'current' parameter must be an integer, got {type(current)}")
15001495
current_progress = current
15011496
if label is not None:
15021497
current_label = label
15031498

1504-
# THROTTLE UPDATES (UNLESS IT'S THE FINAL UPDATE)
1505-
current_time = _time.time()
1506-
if not (current_progress >= total or current_progress < 0) \
1507-
and (current_time - self._last_update_time) < self._min_update_interval:
1508-
return
1509-
self._last_update_time = current_time
1510-
1511-
self.show_progress(current_progress, total, current_label)
1499+
self.show_progress(current=current_progress, total=total, label=current_label)
15121500

15131501
yield update_progress
15141502
except Exception:

tests/test_console.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from collections import namedtuple
66
import builtins
77
import pytest
8+
import time
89
import sys
910
import io
1011

@@ -1047,9 +1048,8 @@ def test_progressbar_progress_context():
10471048
with patch.object(pb, "show_progress") as mock_show, patch.object(pb, "hide_progress") as mock_hide:
10481049
with pb.progress_context(100, "Testing") as update_progress:
10491050
update_progress(25)
1050-
update_progress(50) # CALL WILL GET BLOCKED BY THROTTLING, SINCE IT'S TOO SOON AFTER PREVIOUS
1051-
assert mock_show.call_count == 1
1052-
mock_show.assert_any_call(25, 100, "Testing")
1051+
update_progress(50)
1052+
assert mock_show.call_count == 2
10531053
mock_hide.assert_called_once()
10541054

10551055

0 commit comments

Comments
 (0)