comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/lib/python3.8/site-packages/tqdm/std.py @ 68:5028fdace37b

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 16:23:26 -0400
parents
children
comparison
equal deleted inserted replaced
67:0e9998148a16 68:5028fdace37b
1 """
2 Customisable progressbar decorator for iterators.
3 Includes a default `range` iterator printing to `stderr`.
4
5 Usage:
6 >>> from tqdm import trange, tqdm
7 >>> for i in trange(10):
8 ... ...
9 """
10 import sys
11 from collections import OrderedDict, defaultdict
12 from contextlib import contextmanager
13 from datetime import datetime, timedelta, timezone
14 from numbers import Number
15 from time import time
16 from warnings import warn
17 from weakref import WeakSet
18
19 from ._monitor import TMonitor
20 from .utils import (
21 CallbackIOWrapper, Comparable, DisableOnWriteError, FormatReplace, SimpleTextIOWrapper,
22 _is_ascii, _screen_shape_wrapper, _supports_unicode, _term_move_up, disp_len, disp_trim,
23 envwrap)
24
25 __author__ = "https://github.com/tqdm/tqdm#contributions"
26 __all__ = ['tqdm', 'trange',
27 'TqdmTypeError', 'TqdmKeyError', 'TqdmWarning',
28 'TqdmExperimentalWarning', 'TqdmDeprecationWarning',
29 'TqdmMonitorWarning']
30
31
32 class TqdmTypeError(TypeError):
33 pass
34
35
36 class TqdmKeyError(KeyError):
37 pass
38
39
40 class TqdmWarning(Warning):
41 """base class for all tqdm warnings.
42
43 Used for non-external-code-breaking errors, such as garbled printing.
44 """
45 def __init__(self, msg, fp_write=None, *a, **k):
46 if fp_write is not None:
47 fp_write("\n" + self.__class__.__name__ + ": " + str(msg).rstrip() + '\n')
48 else:
49 super().__init__(msg, *a, **k)
50
51
52 class TqdmExperimentalWarning(TqdmWarning, FutureWarning):
53 """beta feature, unstable API and behaviour"""
54 pass
55
56
57 class TqdmDeprecationWarning(TqdmWarning, DeprecationWarning):
58 # not suppressed if raised
59 pass
60
61
62 class TqdmMonitorWarning(TqdmWarning, RuntimeWarning):
63 """tqdm monitor errors which do not affect external functionality"""
64 pass
65
66
67 def TRLock(*args, **kwargs):
68 """threading RLock"""
69 try:
70 from threading import RLock
71 return RLock(*args, **kwargs)
72 except (ImportError, OSError): # pragma: no cover
73 pass
74
75
76 class TqdmDefaultWriteLock(object):
77 """
78 Provide a default write lock for thread and multiprocessing safety.
79 Works only on platforms supporting `fork` (so Windows is excluded).
80 You must initialise a `tqdm` or `TqdmDefaultWriteLock` instance
81 before forking in order for the write lock to work.
82 On Windows, you need to supply the lock from the parent to the children as
83 an argument to joblib or the parallelism lib you use.
84 """
85 # global thread lock so no setup required for multithreading.
86 # NB: Do not create multiprocessing lock as it sets the multiprocessing
87 # context, disallowing `spawn()`/`forkserver()`
88 th_lock = TRLock()
89
90 def __init__(self):
91 # Create global parallelism locks to avoid racing issues with parallel
92 # bars works only if fork available (Linux/MacOSX, but not Windows)
93 cls = type(self)
94 root_lock = cls.th_lock
95 if root_lock is not None:
96 root_lock.acquire()
97 cls.create_mp_lock()
98 self.locks = [lk for lk in [cls.mp_lock, cls.th_lock] if lk is not None]
99 if root_lock is not None:
100 root_lock.release()
101
102 def acquire(self, *a, **k):
103 for lock in self.locks:
104 lock.acquire(*a, **k)
105
106 def release(self):
107 for lock in self.locks[::-1]: # Release in inverse order of acquisition
108 lock.release()
109
110 def __enter__(self):
111 self.acquire()
112
113 def __exit__(self, *exc):
114 self.release()
115
116 @classmethod
117 def create_mp_lock(cls):
118 if not hasattr(cls, 'mp_lock'):
119 try:
120 from multiprocessing import RLock
121 cls.mp_lock = RLock()
122 except (ImportError, OSError): # pragma: no cover
123 cls.mp_lock = None
124
125 @classmethod
126 def create_th_lock(cls):
127 assert hasattr(cls, 'th_lock')
128 warn("create_th_lock not needed anymore", TqdmDeprecationWarning, stacklevel=2)
129
130
131 class Bar(object):
132 """
133 `str.format`-able bar with format specifiers: `[width][type]`
134
135 - `width`
136 + unspecified (default): use `self.default_len`
137 + `int >= 0`: overrides `self.default_len`
138 + `int < 0`: subtract from `self.default_len`
139 - `type`
140 + `a`: ascii (`charset=self.ASCII` override)
141 + `u`: unicode (`charset=self.UTF` override)
142 + `b`: blank (`charset=" "` override)
143 """
144 ASCII = " 123456789#"
145 UTF = u" " + u''.join(map(chr, range(0x258F, 0x2587, -1)))
146 BLANK = " "
147 COLOUR_RESET = '\x1b[0m'
148 COLOUR_RGB = '\x1b[38;2;%d;%d;%dm'
149 COLOURS = {'BLACK': '\x1b[30m', 'RED': '\x1b[31m', 'GREEN': '\x1b[32m',
150 'YELLOW': '\x1b[33m', 'BLUE': '\x1b[34m', 'MAGENTA': '\x1b[35m',
151 'CYAN': '\x1b[36m', 'WHITE': '\x1b[37m'}
152
153 def __init__(self, frac, default_len=10, charset=UTF, colour=None):
154 if not 0 <= frac <= 1:
155 warn("clamping frac to range [0, 1]", TqdmWarning, stacklevel=2)
156 frac = max(0, min(1, frac))
157 assert default_len > 0
158 self.frac = frac
159 self.default_len = default_len
160 self.charset = charset
161 self.colour = colour
162
163 @property
164 def colour(self):
165 return self._colour
166
167 @colour.setter
168 def colour(self, value):
169 if not value:
170 self._colour = None
171 return
172 try:
173 if value.upper() in self.COLOURS:
174 self._colour = self.COLOURS[value.upper()]
175 elif value[0] == '#' and len(value) == 7:
176 self._colour = self.COLOUR_RGB % tuple(
177 int(i, 16) for i in (value[1:3], value[3:5], value[5:7]))
178 else:
179 raise KeyError
180 except (KeyError, AttributeError):
181 warn("Unknown colour (%s); valid choices: [hex (#00ff00), %s]" % (
182 value, ", ".join(self.COLOURS)),
183 TqdmWarning, stacklevel=2)
184 self._colour = None
185
186 def __format__(self, format_spec):
187 if format_spec:
188 _type = format_spec[-1].lower()
189 try:
190 charset = {'a': self.ASCII, 'u': self.UTF, 'b': self.BLANK}[_type]
191 except KeyError:
192 charset = self.charset
193 else:
194 format_spec = format_spec[:-1]
195 if format_spec:
196 N_BARS = int(format_spec)
197 if N_BARS < 0:
198 N_BARS += self.default_len
199 else:
200 N_BARS = self.default_len
201 else:
202 charset = self.charset
203 N_BARS = self.default_len
204
205 nsyms = len(charset) - 1
206 bar_length, frac_bar_length = divmod(int(self.frac * N_BARS * nsyms), nsyms)
207
208 res = charset[-1] * bar_length
209 if bar_length < N_BARS: # whitespace padding
210 res = res + charset[frac_bar_length] + charset[0] * (N_BARS - bar_length - 1)
211 return self.colour + res + self.COLOUR_RESET if self.colour else res
212
213
214 class EMA(object):
215 """
216 Exponential moving average: smoothing to give progressively lower
217 weights to older values.
218
219 Parameters
220 ----------
221 smoothing : float, optional
222 Smoothing factor in range [0, 1], [default: 0.3].
223 Increase to give more weight to recent values.
224 Ranges from 0 (yields old value) to 1 (yields new value).
225 """
226 def __init__(self, smoothing=0.3):
227 self.alpha = smoothing
228 self.last = 0
229 self.calls = 0
230
231 def __call__(self, x=None):
232 """
233 Parameters
234 ----------
235 x : float
236 New value to include in EMA.
237 """
238 beta = 1 - self.alpha
239 if x is not None:
240 self.last = self.alpha * x + beta * self.last
241 self.calls += 1
242 return self.last / (1 - beta ** self.calls) if self.calls else self.last
243
244
245 class tqdm(Comparable):
246 """
247 Decorate an iterable object, returning an iterator which acts exactly
248 like the original iterable, but prints a dynamically updating
249 progressbar every time a value is requested.
250
251 Parameters
252 ----------
253 iterable : iterable, optional
254 Iterable to decorate with a progressbar.
255 Leave blank to manually manage the updates.
256 desc : str, optional
257 Prefix for the progressbar.
258 total : int or float, optional
259 The number of expected iterations. If unspecified,
260 len(iterable) is used if possible. If float("inf") or as a last
261 resort, only basic progress statistics are displayed
262 (no ETA, no progressbar).
263 If `gui` is True and this parameter needs subsequent updating,
264 specify an initial arbitrary large positive number,
265 e.g. 9e9.
266 leave : bool, optional
267 If [default: True], keeps all traces of the progressbar
268 upon termination of iteration.
269 If `None`, will leave only if `position` is `0`.
270 file : `io.TextIOWrapper` or `io.StringIO`, optional
271 Specifies where to output the progress messages
272 (default: sys.stderr). Uses `file.write(str)` and `file.flush()`
273 methods. For encoding, see `write_bytes`.
274 ncols : int, optional
275 The width of the entire output message. If specified,
276 dynamically resizes the progressbar to stay within this bound.
277 If unspecified, attempts to use environment width. The
278 fallback is a meter width of 10 and no limit for the counter and
279 statistics. If 0, will not print any meter (only stats).
280 mininterval : float, optional
281 Minimum progress display update interval [default: 0.1] seconds.
282 maxinterval : float, optional
283 Maximum progress display update interval [default: 10] seconds.
284 Automatically adjusts `miniters` to correspond to `mininterval`
285 after long display update lag. Only works if `dynamic_miniters`
286 or monitor thread is enabled.
287 miniters : int or float, optional
288 Minimum progress display update interval, in iterations.
289 If 0 and `dynamic_miniters`, will automatically adjust to equal
290 `mininterval` (more CPU efficient, good for tight loops).
291 If > 0, will skip display of specified number of iterations.
292 Tweak this and `mininterval` to get very efficient loops.
293 If your progress is erratic with both fast and slow iterations
294 (network, skipping items, etc) you should set miniters=1.
295 ascii : bool or str, optional
296 If unspecified or False, use unicode (smooth blocks) to fill
297 the meter. The fallback is to use ASCII characters " 123456789#".
298 disable : bool, optional
299 Whether to disable the entire progressbar wrapper
300 [default: False]. If set to None, disable on non-TTY.
301 unit : str, optional
302 String that will be used to define the unit of each iteration
303 [default: it].
304 unit_scale : bool or int or float, optional
305 If 1 or True, the number of iterations will be reduced/scaled
306 automatically and a metric prefix following the
307 International System of Units standard will be added
308 (kilo, mega, etc.) [default: False]. If any other non-zero
309 number, will scale `total` and `n`.
310 dynamic_ncols : bool, optional
311 If set, constantly alters `ncols` and `nrows` to the
312 environment (allowing for window resizes) [default: False].
313 smoothing : float, optional
314 Exponential moving average smoothing factor for speed estimates
315 (ignored in GUI mode). Ranges from 0 (average speed) to 1
316 (current/instantaneous speed) [default: 0.3].
317 bar_format : str, optional
318 Specify a custom bar string formatting. May impact performance.
319 [default: '{l_bar}{bar}{r_bar}'], where
320 l_bar='{desc}: {percentage:3.0f}%|' and
321 r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
322 '{rate_fmt}{postfix}]'
323 Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
324 percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
325 rate, rate_fmt, rate_noinv, rate_noinv_fmt,
326 rate_inv, rate_inv_fmt, postfix, unit_divisor,
327 remaining, remaining_s, eta.
328 Note that a trailing ": " is automatically removed after {desc}
329 if the latter is empty.
330 initial : int or float, optional
331 The initial counter value. Useful when restarting a progress
332 bar [default: 0]. If using float, consider specifying `{n:.3f}`
333 or similar in `bar_format`, or specifying `unit_scale`.
334 position : int, optional
335 Specify the line offset to print this bar (starting from 0)
336 Automatic if unspecified.
337 Useful to manage multiple bars at once (eg, from threads).
338 postfix : dict or *, optional
339 Specify additional stats to display at the end of the bar.
340 Calls `set_postfix(**postfix)` if possible (dict).
341 unit_divisor : float, optional
342 [default: 1000], ignored unless `unit_scale` is True.
343 write_bytes : bool, optional
344 Whether to write bytes. If (default: False) will write unicode.
345 lock_args : tuple, optional
346 Passed to `refresh` for intermediate output
347 (initialisation, iterating, and updating).
348 nrows : int, optional
349 The screen height. If specified, hides nested bars outside this
350 bound. If unspecified, attempts to use environment height.
351 The fallback is 20.
352 colour : str, optional
353 Bar colour (e.g. 'green', '#00ff00').
354 delay : float, optional
355 Don't display until [default: 0] seconds have elapsed.
356 gui : bool, optional
357 WARNING: internal parameter - do not use.
358 Use tqdm.gui.tqdm(...) instead. If set, will attempt to use
359 matplotlib animations for a graphical output [default: False].
360
361 Returns
362 -------
363 out : decorated iterator.
364 """
365
366 monitor_interval = 10 # set to 0 to disable the thread
367 monitor = None
368 _instances = WeakSet()
369
370 @staticmethod
371 def format_sizeof(num, suffix='', divisor=1000):
372 """
373 Formats a number (greater than unity) with SI Order of Magnitude
374 prefixes.
375
376 Parameters
377 ----------
378 num : float
379 Number ( >= 1) to format.
380 suffix : str, optional
381 Post-postfix [default: ''].
382 divisor : float, optional
383 Divisor between prefixes [default: 1000].
384
385 Returns
386 -------
387 out : str
388 Number with Order of Magnitude SI unit postfix.
389 """
390 for unit in ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z']:
391 if abs(num) < 999.5:
392 if abs(num) < 99.95:
393 if abs(num) < 9.995:
394 return f'{num:1.2f}{unit}{suffix}'
395 return f'{num:2.1f}{unit}{suffix}'
396 return f'{num:3.0f}{unit}{suffix}'
397 num /= divisor
398 return f'{num:3.1f}Y{suffix}'
399
400 @staticmethod
401 def format_interval(t):
402 """
403 Formats a number of seconds as a clock time, [H:]MM:SS
404
405 Parameters
406 ----------
407 t : int
408 Number of seconds.
409
410 Returns
411 -------
412 out : str
413 [H:]MM:SS
414 """
415 mins, s = divmod(int(t), 60)
416 h, m = divmod(mins, 60)
417 return f'{h:d}:{m:02d}:{s:02d}' if h else f'{m:02d}:{s:02d}'
418
419 @staticmethod
420 def format_num(n):
421 """
422 Intelligent scientific notation (.3g).
423
424 Parameters
425 ----------
426 n : int or float or Numeric
427 A Number.
428
429 Returns
430 -------
431 out : str
432 Formatted number.
433 """
434 f = f'{n:.3g}'.replace('e+0', 'e+').replace('e-0', 'e-')
435 n = str(n)
436 return f if len(f) < len(n) else n
437
438 @staticmethod
439 def status_printer(file):
440 """
441 Manage the printing and in-place updating of a line of characters.
442 Note that if the string is longer than a line, then in-place
443 updating may not work (it will print a new line at each refresh).
444 """
445 fp = file
446 fp_flush = getattr(fp, 'flush', lambda: None) # pragma: no cover
447 if fp in (sys.stderr, sys.stdout):
448 getattr(sys.stderr, 'flush', lambda: None)()
449 getattr(sys.stdout, 'flush', lambda: None)()
450
451 def fp_write(s):
452 fp.write(str(s))
453 fp_flush()
454
455 last_len = [0]
456
457 def print_status(s):
458 len_s = disp_len(s)
459 fp_write('\r' + s + (' ' * max(last_len[0] - len_s, 0)))
460 last_len[0] = len_s
461
462 return print_status
463
464 @staticmethod
465 def format_meter(n, total, elapsed, ncols=None, prefix='', ascii=False, unit='it',
466 unit_scale=False, rate=None, bar_format=None, postfix=None,
467 unit_divisor=1000, initial=0, colour=None, **extra_kwargs):
468 """
469 Return a string-based progress bar given some parameters
470
471 Parameters
472 ----------
473 n : int or float
474 Number of finished iterations.
475 total : int or float
476 The expected total number of iterations. If meaningless (None),
477 only basic progress statistics are displayed (no ETA).
478 elapsed : float
479 Number of seconds passed since start.
480 ncols : int, optional
481 The width of the entire output message. If specified,
482 dynamically resizes `{bar}` to stay within this bound
483 [default: None]. If `0`, will not print any bar (only stats).
484 The fallback is `{bar:10}`.
485 prefix : str, optional
486 Prefix message (included in total width) [default: ''].
487 Use as {desc} in bar_format string.
488 ascii : bool, optional or str, optional
489 If not set, use unicode (smooth blocks) to fill the meter
490 [default: False]. The fallback is to use ASCII characters
491 " 123456789#".
492 unit : str, optional
493 The iteration unit [default: 'it'].
494 unit_scale : bool or int or float, optional
495 If 1 or True, the number of iterations will be printed with an
496 appropriate SI metric prefix (k = 10^3, M = 10^6, etc.)
497 [default: False]. If any other non-zero number, will scale
498 `total` and `n`.
499 rate : float, optional
500 Manual override for iteration rate.
501 If [default: None], uses n/elapsed.
502 bar_format : str, optional
503 Specify a custom bar string formatting. May impact performance.
504 [default: '{l_bar}{bar}{r_bar}'], where
505 l_bar='{desc}: {percentage:3.0f}%|' and
506 r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, '
507 '{rate_fmt}{postfix}]'
508 Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt,
509 percentage, elapsed, elapsed_s, ncols, nrows, desc, unit,
510 rate, rate_fmt, rate_noinv, rate_noinv_fmt,
511 rate_inv, rate_inv_fmt, postfix, unit_divisor,
512 remaining, remaining_s, eta.
513 Note that a trailing ": " is automatically removed after {desc}
514 if the latter is empty.
515 postfix : *, optional
516 Similar to `prefix`, but placed at the end
517 (e.g. for additional stats).
518 Note: postfix is usually a string (not a dict) for this method,
519 and will if possible be set to postfix = ', ' + postfix.
520 However other types are supported (#382).
521 unit_divisor : float, optional
522 [default: 1000], ignored unless `unit_scale` is True.
523 initial : int or float, optional
524 The initial counter value [default: 0].
525 colour : str, optional
526 Bar colour (e.g. 'green', '#00ff00').
527
528 Returns
529 -------
530 out : Formatted meter and stats, ready to display.
531 """
532
533 # sanity check: total
534 if total and n >= (total + 0.5): # allow float imprecision (#849)
535 total = None
536
537 # apply custom scale if necessary
538 if unit_scale and unit_scale not in (True, 1):
539 if total:
540 total *= unit_scale
541 n *= unit_scale
542 if rate:
543 rate *= unit_scale # by default rate = self.avg_dn / self.avg_dt
544 unit_scale = False
545
546 elapsed_str = tqdm.format_interval(elapsed)
547
548 # if unspecified, attempt to use rate = average speed
549 # (we allow manual override since predicting time is an arcane art)
550 if rate is None and elapsed:
551 rate = (n - initial) / elapsed
552 inv_rate = 1 / rate if rate else None
553 format_sizeof = tqdm.format_sizeof
554 rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else f'{rate:5.2f}')
555 if rate else '?') + unit + '/s'
556 rate_inv_fmt = (
557 (format_sizeof(inv_rate) if unit_scale else f'{inv_rate:5.2f}')
558 if inv_rate else '?') + 's/' + unit
559 rate_fmt = rate_inv_fmt if inv_rate and inv_rate > 1 else rate_noinv_fmt
560
561 if unit_scale:
562 n_fmt = format_sizeof(n, divisor=unit_divisor)
563 total_fmt = format_sizeof(total, divisor=unit_divisor) if total is not None else '?'
564 else:
565 n_fmt = str(n)
566 total_fmt = str(total) if total is not None else '?'
567
568 try:
569 postfix = ', ' + postfix if postfix else ''
570 except TypeError:
571 pass
572
573 remaining = (total - n) / rate if rate and total else 0
574 remaining_str = tqdm.format_interval(remaining) if rate else '?'
575 try:
576 eta_dt = (datetime.now() + timedelta(seconds=remaining)
577 if rate and total else datetime.fromtimestamp(0, timezone.utc))
578 except OverflowError:
579 eta_dt = datetime.max
580
581 # format the stats displayed to the left and right sides of the bar
582 if prefix:
583 # old prefix setup work around
584 bool_prefix_colon_already = (prefix[-2:] == ": ")
585 l_bar = prefix if bool_prefix_colon_already else prefix + ": "
586 else:
587 l_bar = ''
588
589 r_bar = f'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}{postfix}]'
590
591 # Custom bar formatting
592 # Populate a dict with all available progress indicators
593 format_dict = {
594 # slight extension of self.format_dict
595 'n': n, 'n_fmt': n_fmt, 'total': total, 'total_fmt': total_fmt,
596 'elapsed': elapsed_str, 'elapsed_s': elapsed,
597 'ncols': ncols, 'desc': prefix or '', 'unit': unit,
598 'rate': inv_rate if inv_rate and inv_rate > 1 else rate,
599 'rate_fmt': rate_fmt, 'rate_noinv': rate,
600 'rate_noinv_fmt': rate_noinv_fmt, 'rate_inv': inv_rate,
601 'rate_inv_fmt': rate_inv_fmt,
602 'postfix': postfix, 'unit_divisor': unit_divisor,
603 'colour': colour,
604 # plus more useful definitions
605 'remaining': remaining_str, 'remaining_s': remaining,
606 'l_bar': l_bar, 'r_bar': r_bar, 'eta': eta_dt,
607 **extra_kwargs}
608
609 # total is known: we can predict some stats
610 if total:
611 # fractional and percentage progress
612 frac = n / total
613 percentage = frac * 100
614
615 l_bar += f'{percentage:3.0f}%|'
616
617 if ncols == 0:
618 return l_bar[:-1] + r_bar[1:]
619
620 format_dict.update(l_bar=l_bar)
621 if bar_format:
622 format_dict.update(percentage=percentage)
623
624 # auto-remove colon for empty `{desc}`
625 if not prefix:
626 bar_format = bar_format.replace("{desc}: ", '')
627 else:
628 bar_format = "{l_bar}{bar}{r_bar}"
629
630 full_bar = FormatReplace()
631 nobar = bar_format.format(bar=full_bar, **format_dict)
632 if not full_bar.format_called:
633 return nobar # no `{bar}`; nothing else to do
634
635 # Formatting progress bar space available for bar's display
636 full_bar = Bar(frac,
637 max(1, ncols - disp_len(nobar)) if ncols else 10,
638 charset=Bar.ASCII if ascii is True else ascii or Bar.UTF,
639 colour=colour)
640 if not _is_ascii(full_bar.charset) and _is_ascii(bar_format):
641 bar_format = str(bar_format)
642 res = bar_format.format(bar=full_bar, **format_dict)
643 return disp_trim(res, ncols) if ncols else res
644
645 elif bar_format:
646 # user-specified bar_format but no total
647 l_bar += '|'
648 format_dict.update(l_bar=l_bar, percentage=0)
649 full_bar = FormatReplace()
650 nobar = bar_format.format(bar=full_bar, **format_dict)
651 if not full_bar.format_called:
652 return nobar
653 full_bar = Bar(0,
654 max(1, ncols - disp_len(nobar)) if ncols else 10,
655 charset=Bar.BLANK, colour=colour)
656 res = bar_format.format(bar=full_bar, **format_dict)
657 return disp_trim(res, ncols) if ncols else res
658 else:
659 # no total: no progressbar, ETA, just progress stats
660 return (f'{(prefix + ": ") if prefix else ""}'
661 f'{n_fmt}{unit} [{elapsed_str}, {rate_fmt}{postfix}]')
662
663 def __new__(cls, *_, **__):
664 instance = object.__new__(cls)
665 with cls.get_lock(): # also constructs lock if non-existent
666 cls._instances.add(instance)
667 # create monitoring thread
668 if cls.monitor_interval and (cls.monitor is None
669 or not cls.monitor.report()):
670 try:
671 cls.monitor = TMonitor(cls, cls.monitor_interval)
672 except Exception as e: # pragma: nocover
673 warn("tqdm:disabling monitor support"
674 " (monitor_interval = 0) due to:\n" + str(e),
675 TqdmMonitorWarning, stacklevel=2)
676 cls.monitor_interval = 0
677 return instance
678
679 @classmethod
680 def _get_free_pos(cls, instance=None):
681 """Skips specified instance."""
682 positions = {abs(inst.pos) for inst in cls._instances
683 if inst is not instance and hasattr(inst, "pos")}
684 return min(set(range(len(positions) + 1)).difference(positions))
685
686 @classmethod
687 def _decr_instances(cls, instance):
688 """
689 Remove from list and reposition another unfixed bar
690 to fill the new gap.
691
692 This means that by default (where all nested bars are unfixed),
693 order is not maintained but screen flicker/blank space is minimised.
694 (tqdm<=4.44.1 moved ALL subsequent unfixed bars up.)
695 """
696 with cls._lock:
697 try:
698 cls._instances.remove(instance)
699 except KeyError:
700 # if not instance.gui: # pragma: no cover
701 # raise
702 pass # py2: maybe magically removed already
703 # else:
704 if not instance.gui:
705 last = (instance.nrows or 20) - 1
706 # find unfixed (`pos >= 0`) overflow (`pos >= nrows - 1`)
707 instances = list(filter(
708 lambda i: hasattr(i, "pos") and last <= i.pos,
709 cls._instances))
710 # set first found to current `pos`
711 if instances:
712 inst = min(instances, key=lambda i: i.pos)
713 inst.clear(nolock=True)
714 inst.pos = abs(instance.pos)
715
716 @classmethod
717 def write(cls, s, file=None, end="\n", nolock=False):
718 """Print a message via tqdm (without overlap with bars)."""
719 fp = file if file is not None else sys.stdout
720 with cls.external_write_mode(file=file, nolock=nolock):
721 # Write the message
722 fp.write(s)
723 fp.write(end)
724
725 @classmethod
726 @contextmanager
727 def external_write_mode(cls, file=None, nolock=False):
728 """
729 Disable tqdm within context and refresh tqdm when exits.
730 Useful when writing to standard output stream
731 """
732 fp = file if file is not None else sys.stdout
733
734 try:
735 if not nolock:
736 cls.get_lock().acquire()
737 # Clear all bars
738 inst_cleared = []
739 for inst in getattr(cls, '_instances', []):
740 # Clear instance if in the target output file
741 # or if write output + tqdm output are both either
742 # sys.stdout or sys.stderr (because both are mixed in terminal)
743 if hasattr(inst, "start_t") and (inst.fp == fp or all(
744 f in (sys.stdout, sys.stderr) for f in (fp, inst.fp))):
745 inst.clear(nolock=True)
746 inst_cleared.append(inst)
747 yield
748 # Force refresh display of bars we cleared
749 for inst in inst_cleared:
750 inst.refresh(nolock=True)
751 finally:
752 if not nolock:
753 cls._lock.release()
754
755 @classmethod
756 def set_lock(cls, lock):
757 """Set the global lock."""
758 cls._lock = lock
759
760 @classmethod
761 def get_lock(cls):
762 """Get the global lock. Construct it if it does not exist."""
763 if not hasattr(cls, '_lock'):
764 cls._lock = TqdmDefaultWriteLock()
765 return cls._lock
766
767 @classmethod
768 def pandas(cls, **tqdm_kwargs):
769 """
770 Registers the current `tqdm` class with
771 pandas.core.
772 ( frame.DataFrame
773 | series.Series
774 | groupby.(generic.)DataFrameGroupBy
775 | groupby.(generic.)SeriesGroupBy
776 ).progress_apply
777
778 A new instance will be created every time `progress_apply` is called,
779 and each instance will automatically `close()` upon completion.
780
781 Parameters
782 ----------
783 tqdm_kwargs : arguments for the tqdm instance
784
785 Examples
786 --------
787 >>> import pandas as pd
788 >>> import numpy as np
789 >>> from tqdm import tqdm
790 >>> from tqdm.gui import tqdm as tqdm_gui
791 >>>
792 >>> df = pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
793 >>> tqdm.pandas(ncols=50) # can use tqdm_gui, optional kwargs, etc
794 >>> # Now you can use `progress_apply` instead of `apply`
795 >>> df.groupby(0).progress_apply(lambda x: x**2)
796
797 References
798 ----------
799 <https://stackoverflow.com/questions/18603270/\
800 progress-indicator-during-pandas-operations-python>
801 """
802 from warnings import catch_warnings, simplefilter
803
804 from pandas.core.frame import DataFrame
805 from pandas.core.series import Series
806 try:
807 with catch_warnings():
808 simplefilter("ignore", category=FutureWarning)
809 from pandas import Panel
810 except ImportError: # pandas>=1.2.0
811 Panel = None
812 Rolling, Expanding = None, None
813 try: # pandas>=1.0.0
814 from pandas.core.window.rolling import _Rolling_and_Expanding
815 except ImportError:
816 try: # pandas>=0.18.0
817 from pandas.core.window import _Rolling_and_Expanding
818 except ImportError: # pandas>=1.2.0
819 try: # pandas>=1.2.0
820 from pandas.core.window.expanding import Expanding
821 from pandas.core.window.rolling import Rolling
822 _Rolling_and_Expanding = Rolling, Expanding
823 except ImportError: # pragma: no cover
824 _Rolling_and_Expanding = None
825 try: # pandas>=0.25.0
826 from pandas.core.groupby.generic import SeriesGroupBy # , NDFrameGroupBy
827 from pandas.core.groupby.generic import DataFrameGroupBy
828 except ImportError: # pragma: no cover
829 try: # pandas>=0.23.0
830 from pandas.core.groupby.groupby import DataFrameGroupBy, SeriesGroupBy
831 except ImportError:
832 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy
833 try: # pandas>=0.23.0
834 from pandas.core.groupby.groupby import GroupBy
835 except ImportError: # pragma: no cover
836 from pandas.core.groupby import GroupBy
837
838 try: # pandas>=0.23.0
839 from pandas.core.groupby.groupby import PanelGroupBy
840 except ImportError:
841 try:
842 from pandas.core.groupby import PanelGroupBy
843 except ImportError: # pandas>=0.25.0
844 PanelGroupBy = None
845
846 tqdm_kwargs = tqdm_kwargs.copy()
847 deprecated_t = [tqdm_kwargs.pop('deprecated_t', None)]
848
849 def inner_generator(df_function='apply'):
850 def inner(df, func, *args, **kwargs):
851 """
852 Parameters
853 ----------
854 df : (DataFrame|Series)[GroupBy]
855 Data (may be grouped).
856 func : function
857 To be applied on the (grouped) data.
858 **kwargs : optional
859 Transmitted to `df.apply()`.
860 """
861
862 # Precompute total iterations
863 total = tqdm_kwargs.pop("total", getattr(df, 'ngroups', None))
864 if total is None: # not grouped
865 if df_function == 'applymap':
866 total = df.size
867 elif isinstance(df, Series):
868 total = len(df)
869 elif (_Rolling_and_Expanding is None or
870 not isinstance(df, _Rolling_and_Expanding)):
871 # DataFrame or Panel
872 axis = kwargs.get('axis', 0)
873 if axis == 'index':
874 axis = 0
875 elif axis == 'columns':
876 axis = 1
877 # when axis=0, total is shape[axis1]
878 total = df.size // df.shape[axis]
879
880 # Init bar
881 if deprecated_t[0] is not None:
882 t = deprecated_t[0]
883 deprecated_t[0] = None
884 else:
885 t = cls(total=total, **tqdm_kwargs)
886
887 if len(args) > 0:
888 # *args intentionally not supported (see #244, #299)
889 TqdmDeprecationWarning(
890 "Except func, normal arguments are intentionally" +
891 " not supported by" +
892 " `(DataFrame|Series|GroupBy).progress_apply`." +
893 " Use keyword arguments instead.",
894 fp_write=getattr(t.fp, 'write', sys.stderr.write))
895
896 try: # pandas>=1.3.0
897 from pandas.core.common import is_builtin_func
898 except ImportError:
899 is_builtin_func = df._is_builtin_func
900 try:
901 func = is_builtin_func(func)
902 except TypeError:
903 pass
904
905 # Define bar updating wrapper
906 def wrapper(*args, **kwargs):
907 # update tbar correctly
908 # it seems `pandas apply` calls `func` twice
909 # on the first column/row to decide whether it can
910 # take a fast or slow code path; so stop when t.total==t.n
911 t.update(n=1 if not t.total or t.n < t.total else 0)
912 return func(*args, **kwargs)
913
914 # Apply the provided function (in **kwargs)
915 # on the df using our wrapper (which provides bar updating)
916 try:
917 return getattr(df, df_function)(wrapper, **kwargs)
918 finally:
919 t.close()
920
921 return inner
922
923 # Monkeypatch pandas to provide easy methods
924 # Enable custom tqdm progress in pandas!
925 Series.progress_apply = inner_generator()
926 SeriesGroupBy.progress_apply = inner_generator()
927 Series.progress_map = inner_generator('map')
928 SeriesGroupBy.progress_map = inner_generator('map')
929
930 DataFrame.progress_apply = inner_generator()
931 DataFrameGroupBy.progress_apply = inner_generator()
932 DataFrame.progress_applymap = inner_generator('applymap')
933 DataFrame.progress_map = inner_generator('map')
934 DataFrameGroupBy.progress_map = inner_generator('map')
935
936 if Panel is not None:
937 Panel.progress_apply = inner_generator()
938 if PanelGroupBy is not None:
939 PanelGroupBy.progress_apply = inner_generator()
940
941 GroupBy.progress_apply = inner_generator()
942 GroupBy.progress_aggregate = inner_generator('aggregate')
943 GroupBy.progress_transform = inner_generator('transform')
944
945 if Rolling is not None and Expanding is not None:
946 Rolling.progress_apply = inner_generator()
947 Expanding.progress_apply = inner_generator()
948 elif _Rolling_and_Expanding is not None:
949 _Rolling_and_Expanding.progress_apply = inner_generator()
950
951 # override defaults via env vars
952 @envwrap("TQDM_", is_method=True, types={'total': float, 'ncols': int, 'miniters': float,
953 'position': int, 'nrows': int})
954 def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None,
955 ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None,
956 ascii=None, disable=False, unit='it', unit_scale=False,
957 dynamic_ncols=False, smoothing=0.3, bar_format=None, initial=0,
958 position=None, postfix=None, unit_divisor=1000, write_bytes=False,
959 lock_args=None, nrows=None, colour=None, delay=0.0, gui=False,
960 **kwargs):
961 """see tqdm.tqdm for arguments"""
962 if file is None:
963 file = sys.stderr
964
965 if write_bytes:
966 # Despite coercing unicode into bytes, py2 sys.std* streams
967 # should have bytes written to them.
968 file = SimpleTextIOWrapper(
969 file, encoding=getattr(file, 'encoding', None) or 'utf-8')
970
971 file = DisableOnWriteError(file, tqdm_instance=self)
972
973 if disable is None and hasattr(file, "isatty") and not file.isatty():
974 disable = True
975
976 if total is None and iterable is not None:
977 try:
978 total = len(iterable)
979 except (TypeError, AttributeError):
980 total = None
981 if total == float("inf"):
982 # Infinite iterations, behave same as unknown
983 total = None
984
985 if disable:
986 self.iterable = iterable
987 self.disable = disable
988 with self._lock:
989 self.pos = self._get_free_pos(self)
990 self._instances.remove(self)
991 self.n = initial
992 self.total = total
993 self.leave = leave
994 return
995
996 if kwargs:
997 self.disable = True
998 with self._lock:
999 self.pos = self._get_free_pos(self)
1000 self._instances.remove(self)
1001 raise (
1002 TqdmDeprecationWarning(
1003 "`nested` is deprecated and automated.\n"
1004 "Use `position` instead for manual control.\n",
1005 fp_write=getattr(file, 'write', sys.stderr.write))
1006 if "nested" in kwargs else
1007 TqdmKeyError("Unknown argument(s): " + str(kwargs)))
1008
1009 # Preprocess the arguments
1010 if (
1011 (ncols is None or nrows is None) and (file in (sys.stderr, sys.stdout))
1012 ) or dynamic_ncols: # pragma: no cover
1013 if dynamic_ncols:
1014 dynamic_ncols = _screen_shape_wrapper()
1015 if dynamic_ncols:
1016 ncols, nrows = dynamic_ncols(file)
1017 else:
1018 _dynamic_ncols = _screen_shape_wrapper()
1019 if _dynamic_ncols:
1020 _ncols, _nrows = _dynamic_ncols(file)
1021 if ncols is None:
1022 ncols = _ncols
1023 if nrows is None:
1024 nrows = _nrows
1025
1026 if miniters is None:
1027 miniters = 0
1028 dynamic_miniters = True
1029 else:
1030 dynamic_miniters = False
1031
1032 if mininterval is None:
1033 mininterval = 0
1034
1035 if maxinterval is None:
1036 maxinterval = 0
1037
1038 if ascii is None:
1039 ascii = not _supports_unicode(file)
1040
1041 if bar_format and ascii is not True and not _is_ascii(ascii):
1042 # Convert bar format into unicode since terminal uses unicode
1043 bar_format = str(bar_format)
1044
1045 if smoothing is None:
1046 smoothing = 0
1047
1048 # Store the arguments
1049 self.iterable = iterable
1050 self.desc = desc or ''
1051 self.total = total
1052 self.leave = leave
1053 self.fp = file
1054 self.ncols = ncols
1055 self.nrows = nrows
1056 self.mininterval = mininterval
1057 self.maxinterval = maxinterval
1058 self.miniters = miniters
1059 self.dynamic_miniters = dynamic_miniters
1060 self.ascii = ascii
1061 self.disable = disable
1062 self.unit = unit
1063 self.unit_scale = unit_scale
1064 self.unit_divisor = unit_divisor
1065 self.initial = initial
1066 self.lock_args = lock_args
1067 self.delay = delay
1068 self.gui = gui
1069 self.dynamic_ncols = dynamic_ncols
1070 self.smoothing = smoothing
1071 self._ema_dn = EMA(smoothing)
1072 self._ema_dt = EMA(smoothing)
1073 self._ema_miniters = EMA(smoothing)
1074 self.bar_format = bar_format
1075 self.postfix = None
1076 self.colour = colour
1077 self._time = time
1078 if postfix:
1079 try:
1080 self.set_postfix(refresh=False, **postfix)
1081 except TypeError:
1082 self.postfix = postfix
1083
1084 # Init the iterations counters
1085 self.last_print_n = initial
1086 self.n = initial
1087
1088 # if nested, at initial sp() call we replace '\r' by '\n' to
1089 # not overwrite the outer progress bar
1090 with self._lock:
1091 # mark fixed positions as negative
1092 self.pos = self._get_free_pos(self) if position is None else -position
1093
1094 if not gui:
1095 # Initialize the screen printer
1096 self.sp = self.status_printer(self.fp)
1097 if delay <= 0:
1098 self.refresh(lock_args=self.lock_args)
1099
1100 # Init the time counter
1101 self.last_print_t = self._time()
1102 # NB: Avoid race conditions by setting start_t at the very end of init
1103 self.start_t = self.last_print_t
1104
1105 def __bool__(self):
1106 if self.total is not None:
1107 return self.total > 0
1108 if self.iterable is None:
1109 raise TypeError('bool() undefined when iterable == total == None')
1110 return bool(self.iterable)
1111
1112 def __len__(self):
1113 return (
1114 self.total if self.iterable is None
1115 else self.iterable.shape[0] if hasattr(self.iterable, "shape")
1116 else len(self.iterable) if hasattr(self.iterable, "__len__")
1117 else self.iterable.__length_hint__() if hasattr(self.iterable, "__length_hint__")
1118 else getattr(self, "total", None))
1119
1120 def __reversed__(self):
1121 try:
1122 orig = self.iterable
1123 except AttributeError:
1124 raise TypeError("'tqdm' object is not reversible")
1125 else:
1126 self.iterable = reversed(self.iterable)
1127 return self.__iter__()
1128 finally:
1129 self.iterable = orig
1130
1131 def __contains__(self, item):
1132 contains = getattr(self.iterable, '__contains__', None)
1133 return contains(item) if contains is not None else item in self.__iter__()
1134
1135 def __enter__(self):
1136 return self
1137
1138 def __exit__(self, exc_type, exc_value, traceback):
1139 try:
1140 self.close()
1141 except AttributeError:
1142 # maybe eager thread cleanup upon external error
1143 if (exc_type, exc_value, traceback) == (None, None, None):
1144 raise
1145 warn("AttributeError ignored", TqdmWarning, stacklevel=2)
1146
1147 def __del__(self):
1148 self.close()
1149
1150 def __str__(self):
1151 return self.format_meter(**self.format_dict)
1152
1153 @property
1154 def _comparable(self):
1155 return abs(getattr(self, "pos", 1 << 31))
1156
1157 def __hash__(self):
1158 return id(self)
1159
1160 def __iter__(self):
1161 """Backward-compatibility to use: for x in tqdm(iterable)"""
1162
1163 # Inlining instance variables as locals (speed optimisation)
1164 iterable = self.iterable
1165
1166 # If the bar is disabled, then just walk the iterable
1167 # (note: keep this check outside the loop for performance)
1168 if self.disable:
1169 for obj in iterable:
1170 yield obj
1171 return
1172
1173 mininterval = self.mininterval
1174 last_print_t = self.last_print_t
1175 last_print_n = self.last_print_n
1176 min_start_t = self.start_t + self.delay
1177 n = self.n
1178 time = self._time
1179
1180 try:
1181 for obj in iterable:
1182 yield obj
1183 # Update and possibly print the progressbar.
1184 # Note: does not call self.update(1) for speed optimisation.
1185 n += 1
1186
1187 if n - last_print_n >= self.miniters:
1188 cur_t = time()
1189 dt = cur_t - last_print_t
1190 if dt >= mininterval and cur_t >= min_start_t:
1191 self.update(n - last_print_n)
1192 last_print_n = self.last_print_n
1193 last_print_t = self.last_print_t
1194 finally:
1195 self.n = n
1196 self.close()
1197
1198 def update(self, n=1):
1199 """
1200 Manually update the progress bar, useful for streams
1201 such as reading files.
1202 E.g.:
1203 >>> t = tqdm(total=filesize) # Initialise
1204 >>> for current_buffer in stream:
1205 ... ...
1206 ... t.update(len(current_buffer))
1207 >>> t.close()
1208 The last line is highly recommended, but possibly not necessary if
1209 `t.update()` will be called in such a way that `filesize` will be
1210 exactly reached and printed.
1211
1212 Parameters
1213 ----------
1214 n : int or float, optional
1215 Increment to add to the internal counter of iterations
1216 [default: 1]. If using float, consider specifying `{n:.3f}`
1217 or similar in `bar_format`, or specifying `unit_scale`.
1218
1219 Returns
1220 -------
1221 out : bool or None
1222 True if a `display()` was triggered.
1223 """
1224 if self.disable:
1225 return
1226
1227 if n < 0:
1228 self.last_print_n += n # for auto-refresh logic to work
1229 self.n += n
1230
1231 # check counter first to reduce calls to time()
1232 if self.n - self.last_print_n >= self.miniters:
1233 cur_t = self._time()
1234 dt = cur_t - self.last_print_t
1235 if dt >= self.mininterval and cur_t >= self.start_t + self.delay:
1236 cur_t = self._time()
1237 dn = self.n - self.last_print_n # >= n
1238 if self.smoothing and dt and dn:
1239 # EMA (not just overall average)
1240 self._ema_dn(dn)
1241 self._ema_dt(dt)
1242 self.refresh(lock_args=self.lock_args)
1243 if self.dynamic_miniters:
1244 # If no `miniters` was specified, adjust automatically to the
1245 # maximum iteration rate seen so far between two prints.
1246 # e.g.: After running `tqdm.update(5)`, subsequent
1247 # calls to `tqdm.update()` will only cause an update after
1248 # at least 5 more iterations.
1249 if self.maxinterval and dt >= self.maxinterval:
1250 self.miniters = dn * (self.mininterval or self.maxinterval) / dt
1251 elif self.smoothing:
1252 # EMA miniters update
1253 self.miniters = self._ema_miniters(
1254 dn * (self.mininterval / dt if self.mininterval and dt
1255 else 1))
1256 else:
1257 # max iters between two prints
1258 self.miniters = max(self.miniters, dn)
1259
1260 # Store old values for next call
1261 self.last_print_n = self.n
1262 self.last_print_t = cur_t
1263 return True
1264
1265 def close(self):
1266 """Cleanup and (if leave=False) close the progressbar."""
1267 if self.disable:
1268 return
1269
1270 # Prevent multiple closures
1271 self.disable = True
1272
1273 # decrement instance pos and remove from internal set
1274 pos = abs(self.pos)
1275 self._decr_instances(self)
1276
1277 if self.last_print_t < self.start_t + self.delay:
1278 # haven't ever displayed; nothing to clear
1279 return
1280
1281 # GUI mode
1282 if getattr(self, 'sp', None) is None:
1283 return
1284
1285 # annoyingly, _supports_unicode isn't good enough
1286 def fp_write(s):
1287 self.fp.write(str(s))
1288
1289 try:
1290 fp_write('')
1291 except ValueError as e:
1292 if 'closed' in str(e):
1293 return
1294 raise # pragma: no cover
1295
1296 leave = pos == 0 if self.leave is None else self.leave
1297
1298 with self._lock:
1299 if leave:
1300 # stats for overall rate (no weighted average)
1301 self._ema_dt = lambda: None
1302 self.display(pos=0)
1303 fp_write('\n')
1304 else:
1305 # clear previous display
1306 if self.display(msg='', pos=pos) and not pos:
1307 fp_write('\r')
1308
1309 def clear(self, nolock=False):
1310 """Clear current bar display."""
1311 if self.disable:
1312 return
1313
1314 if not nolock:
1315 self._lock.acquire()
1316 pos = abs(self.pos)
1317 if pos < (self.nrows or 20):
1318 self.moveto(pos)
1319 self.sp('')
1320 self.fp.write('\r') # place cursor back at the beginning of line
1321 self.moveto(-pos)
1322 if not nolock:
1323 self._lock.release()
1324
1325 def refresh(self, nolock=False, lock_args=None):
1326 """
1327 Force refresh the display of this bar.
1328
1329 Parameters
1330 ----------
1331 nolock : bool, optional
1332 If `True`, does not lock.
1333 If [default: `False`]: calls `acquire()` on internal lock.
1334 lock_args : tuple, optional
1335 Passed to internal lock's `acquire()`.
1336 If specified, will only `display()` if `acquire()` returns `True`.
1337 """
1338 if self.disable:
1339 return
1340
1341 if not nolock:
1342 if lock_args:
1343 if not self._lock.acquire(*lock_args):
1344 return False
1345 else:
1346 self._lock.acquire()
1347 self.display()
1348 if not nolock:
1349 self._lock.release()
1350 return True
1351
1352 def unpause(self):
1353 """Restart tqdm timer from last print time."""
1354 if self.disable:
1355 return
1356 cur_t = self._time()
1357 self.start_t += cur_t - self.last_print_t
1358 self.last_print_t = cur_t
1359
1360 def reset(self, total=None):
1361 """
1362 Resets to 0 iterations for repeated use.
1363
1364 Consider combining with `leave=True`.
1365
1366 Parameters
1367 ----------
1368 total : int or float, optional. Total to use for the new bar.
1369 """
1370 self.n = 0
1371 if total is not None:
1372 self.total = total
1373 if self.disable:
1374 return
1375 self.last_print_n = 0
1376 self.last_print_t = self.start_t = self._time()
1377 self._ema_dn = EMA(self.smoothing)
1378 self._ema_dt = EMA(self.smoothing)
1379 self._ema_miniters = EMA(self.smoothing)
1380 self.refresh()
1381
1382 def set_description(self, desc=None, refresh=True):
1383 """
1384 Set/modify description of the progress bar.
1385
1386 Parameters
1387 ----------
1388 desc : str, optional
1389 refresh : bool, optional
1390 Forces refresh [default: True].
1391 """
1392 self.desc = desc + ': ' if desc else ''
1393 if refresh:
1394 self.refresh()
1395
1396 def set_description_str(self, desc=None, refresh=True):
1397 """Set/modify description without ': ' appended."""
1398 self.desc = desc or ''
1399 if refresh:
1400 self.refresh()
1401
1402 def set_postfix(self, ordered_dict=None, refresh=True, **kwargs):
1403 """
1404 Set/modify postfix (additional stats)
1405 with automatic formatting based on datatype.
1406
1407 Parameters
1408 ----------
1409 ordered_dict : dict or OrderedDict, optional
1410 refresh : bool, optional
1411 Forces refresh [default: True].
1412 kwargs : dict, optional
1413 """
1414 # Sort in alphabetical order to be more deterministic
1415 postfix = OrderedDict([] if ordered_dict is None else ordered_dict)
1416 for key in sorted(kwargs.keys()):
1417 postfix[key] = kwargs[key]
1418 # Preprocess stats according to datatype
1419 for key in postfix.keys():
1420 # Number: limit the length of the string
1421 if isinstance(postfix[key], Number):
1422 postfix[key] = self.format_num(postfix[key])
1423 # Else for any other type, try to get the string conversion
1424 elif not isinstance(postfix[key], str):
1425 postfix[key] = str(postfix[key])
1426 # Else if it's a string, don't need to preprocess anything
1427 # Stitch together to get the final postfix
1428 self.postfix = ', '.join(key + '=' + postfix[key].strip()
1429 for key in postfix.keys())
1430 if refresh:
1431 self.refresh()
1432
1433 def set_postfix_str(self, s='', refresh=True):
1434 """
1435 Postfix without dictionary expansion, similar to prefix handling.
1436 """
1437 self.postfix = str(s)
1438 if refresh:
1439 self.refresh()
1440
1441 def moveto(self, n):
1442 # TODO: private method
1443 self.fp.write('\n' * n + _term_move_up() * -n)
1444 getattr(self.fp, 'flush', lambda: None)()
1445
1446 @property
1447 def format_dict(self):
1448 """Public API for read-only member access."""
1449 if self.disable and not hasattr(self, 'unit'):
1450 return defaultdict(lambda: None, {
1451 'n': self.n, 'total': self.total, 'elapsed': 0, 'unit': 'it'})
1452 if self.dynamic_ncols:
1453 self.ncols, self.nrows = self.dynamic_ncols(self.fp)
1454 return {
1455 'n': self.n, 'total': self.total,
1456 'elapsed': self._time() - self.start_t if hasattr(self, 'start_t') else 0,
1457 'ncols': self.ncols, 'nrows': self.nrows, 'prefix': self.desc,
1458 'ascii': self.ascii, 'unit': self.unit, 'unit_scale': self.unit_scale,
1459 'rate': self._ema_dn() / self._ema_dt() if self._ema_dt() else None,
1460 'bar_format': self.bar_format, 'postfix': self.postfix,
1461 'unit_divisor': self.unit_divisor, 'initial': self.initial,
1462 'colour': self.colour}
1463
1464 def display(self, msg=None, pos=None):
1465 """
1466 Use `self.sp` to display `msg` in the specified `pos`.
1467
1468 Consider overloading this function when inheriting to use e.g.:
1469 `self.some_frontend(**self.format_dict)` instead of `self.sp`.
1470
1471 Parameters
1472 ----------
1473 msg : str, optional. What to display (default: `repr(self)`).
1474 pos : int, optional. Position to `moveto`
1475 (default: `abs(self.pos)`).
1476 """
1477 if pos is None:
1478 pos = abs(self.pos)
1479
1480 nrows = self.nrows or 20
1481 if pos >= nrows - 1:
1482 if pos >= nrows:
1483 return False
1484 if msg or msg is None: # override at `nrows - 1`
1485 msg = " ... (more hidden) ..."
1486
1487 if not hasattr(self, "sp"):
1488 raise TqdmDeprecationWarning(
1489 "Please use `tqdm.gui.tqdm(...)`"
1490 " instead of `tqdm(..., gui=True)`\n",
1491 fp_write=getattr(self.fp, 'write', sys.stderr.write))
1492
1493 if pos:
1494 self.moveto(pos)
1495 self.sp(self.__str__() if msg is None else msg)
1496 if pos:
1497 self.moveto(-pos)
1498 return True
1499
1500 @classmethod
1501 @contextmanager
1502 def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs):
1503 """
1504 stream : file-like object.
1505 method : str, "read" or "write". The result of `read()` and
1506 the first argument of `write()` should have a `len()`.
1507
1508 >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj:
1509 ... while True:
1510 ... chunk = fobj.read(chunk_size)
1511 ... if not chunk:
1512 ... break
1513 """
1514 with cls(total=total, **tqdm_kwargs) as t:
1515 if bytes:
1516 t.unit = "B"
1517 t.unit_scale = True
1518 t.unit_divisor = 1024
1519 yield CallbackIOWrapper(t.update, stream, method)
1520
1521
1522 def trange(*args, **kwargs):
1523 """Shortcut for tqdm(range(*args), **kwargs)."""
1524 return tqdm(range(*args), **kwargs)