diff --git a/README.rst b/README.rst index 187b7af7..00e9cd81 100644 --- a/README.rst +++ b/README.rst @@ -351,10 +351,9 @@ Parameters Specify the line offset to print this bar (starting from 0) Automatic if unspecified. Useful to manage multiple bars at once (eg, from threads). -* postfix : dict, optional +* postfix : dict or ``*``, optional Specify additional stats to display at the end of the bar. - Note: postfix is a dict ({'key': value} pairs) for this method, - not a string. + Calls ``set_postfix(**postfix)`` if possible (dict). * unit_divisor : float, optional [default: 1000], ignored unless `unit_scale` is True. @@ -495,14 +494,22 @@ with the ``desc`` and ``postfix`` arguments: from random import random, randint from time import sleep - t = trange(100) - for i in t: - # Description will be displayed on the left - t.set_description('GEN %i' % i) - # Postfix will be displayed on the right, and will format automatically - # based on argument's datatype - t.set_postfix(loss=random(), gen=randint(1,999), str='h', lst=[1, 2]) - sleep(0.1) + with trange(100) as t: + for i in t: + # Description will be displayed on the left + t.set_description('GEN %i' % i) + # Postfix will be displayed on the right, + # formatted automatically based on argument's datatype + t.set_postfix(loss=random(), gen=randint(1,999), str='h', + lst=[1, 2]) + sleep(0.1) + + with tqdm(total=10, bar_format="{postfix[0]} {postfix[1][value]:>8.2g}", + postfix=["Batch", dict(value=0)]) as t: + for i in range(10): + sleep(0.1) + t.postfix[1]["value"] = i / 2 + t.update() Nested progress bars ~~~~~~~~~~~~~~~~~~~~ diff --git a/tqdm.1 b/tqdm.1 index b8fc7eeb..79beadac 100644 --- a/tqdm.1 +++ b/tqdm.1 @@ -159,11 +159,12 @@ Ranges from 0 (average speed) to 1 (current/instantaneous speed) str, optional. Specify a custom bar string formatting. May impact performance. -If unspecified, will use \[aq]{l_bar}{bar}{r_bar}\[aq], where l_bar is -\[aq]{desc}: {percentage:3.0f}%|\[aq] and r_bar is \[aq]| -{n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}]\[aq] Possible -vars: bar, n, n_fmt, total, total_fmt, percentage, rate, rate_fmt, -elapsed, remaining, l_bar, r_bar, desc. +[default: \[aq]{l_bar}{bar}{r_bar}\[aq]], where l_bar=\[aq]{desc}: +{percentage:3.0f}%|\[aq] and r_bar=\[aq]| {n_fmt}/{total_fmt} +[{elapsed}<{remaining}, \[aq] \[aq]{rate_fmt}{postfix}]\[aq] Possible +vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, percentage, rate, +rate_fmt, rate_noinv, rate_noinv_fmt, rate_inv, rate_inv_fmt, elapsed, +remaining, desc, postfix. Note that a trailing ": " is automatically removed after {desc} if the latter is empty. .RS @@ -185,10 +186,9 @@ Useful to manage multiple bars at once (eg, from threads). .RE .TP .B \-\-postfix=\f[I]postfix\f[] -dict, optional. +dict or *, optional. Specify additional stats to display at the end of the bar. -Note: postfix is a dict ({\[aq]key\[aq]: value} pairs) for this method, -not a string. +Calls \f[C]set_postfix(**postfix)\f[] if possible (dict). .RS .RE .TP diff --git a/tqdm/_tqdm.py b/tqdm/_tqdm.py index 0eafbf0a..04b2961b 100755 --- a/tqdm/_tqdm.py +++ b/tqdm/_tqdm.py @@ -240,10 +240,12 @@ class tqdm(object): rate_inv, rate_inv_fmt, elapsed, remaining, desc, postfix. Note that a trailing ": " is automatically removed after {desc} if the latter is empty. - postfix : str, optional + postfix : *, optional Similar to `prefix`, but placed at the end (e.g. for additional stats). - Note: postfix is a string for this method. Not a dict. + Note: postfix is usually a string (not a dict) for this method, + and will if possible be set to postfix = ', ' + postfix. + However other types are supported (#382). unit_divisor : float, optional [default: 1000], ignored unless `unit_scale` is True. @@ -287,6 +289,11 @@ class tqdm(object): n_fmt = str(n) total_fmt = str(total) + try: + postfix = ', ' + postfix if postfix else '' + except TypeError: + pass + # total is known: we can predict some stats if total: # fractional and percentage progress @@ -305,8 +312,7 @@ class tqdm(object): l_bar = '' l_bar += '{0:3.0f}%|'.format(percentage) r_bar = '| {0}/{1} [{2}<{3}, {4}{5}]'.format( - n_fmt, total_fmt, elapsed_str, remaining_str, rate_fmt, - ', ' + postfix if postfix else '') + n_fmt, total_fmt, elapsed_str, remaining_str, rate_fmt, postfix) if ncols == 0: return l_bar[:-1] + r_bar[1:] @@ -331,7 +337,7 @@ class tqdm(object): 'l_bar': l_bar, 'r_bar': r_bar, 'desc': prefix or '', - 'postfix': ', ' + postfix if postfix else '', + 'postfix': postfix, # 'bar': full_bar # replaced by procedure below } @@ -386,8 +392,7 @@ class tqdm(object): else: return ((prefix + ": ") if prefix else '') + \ '{0}{1} [{2}, {3}{4}]'.format( - n_fmt, unit, elapsed_str, rate_fmt, - ', ' + postfix if postfix else '') + n_fmt, unit, elapsed_str, rate_fmt, postfix) def __new__(cls, *args, **kwargs): # Create a new instance @@ -691,11 +696,13 @@ class tqdm(object): (current/instantaneous speed) [default: 0.3]. bar_format : str, optional Specify a custom bar string formatting. May impact performance. - If unspecified, will use '{l_bar}{bar}{r_bar}', where l_bar is - '{desc}: {percentage:3.0f}%|' and r_bar is - '| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, {rate_fmt}]' - Possible vars: bar, n, n_fmt, total, total_fmt, percentage, - rate, rate_fmt, elapsed, remaining, l_bar, r_bar, desc. + [default: '{l_bar}{bar}{r_bar}'], where + l_bar='{desc}: {percentage:3.0f}%|' and + r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ' + '{rate_fmt}{postfix}]' + Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, + percentage, rate, rate_fmt, rate_noinv, rate_noinv_fmt, + rate_inv, rate_inv_fmt, elapsed, remaining, desc, postfix. Note that a trailing ": " is automatically removed after {desc} if the latter is empty. initial : int, optional @@ -705,10 +712,9 @@ class tqdm(object): Specify the line offset to print this bar (starting from 0) Automatic if unspecified. Useful to manage multiple bars at once (eg, from threads). - postfix : dict, optional + postfix : dict or *, optional Specify additional stats to display at the end of the bar. - Note: postfix is a dict ({'key': value} pairs) for this method, - not a string. + Calls `set_postfix(**postfix)` if possible (dict). unit_divisor : float, optional [default: 1000], ignored unless `unit_scale` is True. gui : bool, optional @@ -812,7 +818,10 @@ class tqdm(object): self.bar_format = bar_format self.postfix = None if postfix: - self.set_postfix(refresh=False, **postfix) + try: + self.set_postfix(refresh=False, **postfix) + except TypeError: + self.postfix = postfix # Init the iterations counters self.last_print_n = initial diff --git a/tqdm/_version.py b/tqdm/_version.py index 45bef8d7..6866bc5b 100644 --- a/tqdm/_version.py +++ b/tqdm/_version.py @@ -5,7 +5,7 @@ from io import open as io_open __all__ = ["__version__"] # major, minor, patch, -extra -version_info = 4, 21, 0 +version_info = 4, 22, 0 # Nice string for the version __version__ = '.'.join(map(str, version_info)) diff --git a/tqdm/tests/tests_tqdm.py b/tqdm/tests/tests_tqdm.py index 89640d7f..f81d2391 100644 --- a/tqdm/tests/tests_tqdm.py +++ b/tqdm/tests/tests_tqdm.py @@ -1463,6 +1463,25 @@ def test_postfix(): assert out5 == ["World"] +def test_postfix_direct(): + """Test directly assigning non-str objects to postfix""" + with closing(StringIO()) as our_file: + with tqdm(total=10, file=our_file, miniters=1, mininterval=0, + bar_format="{postfix[0][name]} {postfix[1]:>5.2f}", + postfix=[dict(name="foo"), 42]) as t: + for i in range(10): + if i % 2: + t.postfix[0]["name"] = "abcdefghij"[i] + else: + t.postfix[1] = i + t.update() + res = our_file.getvalue() + assert "f 6.00" in res + assert "h 6.00" in res + assert "h 8.00" in res + assert "j 8.00" in res + + class DummyTqdmFile(object): """Dummy file-like that will write to tqdm""" file = None