Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/tqdm/std.py: 16%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

701 statements  

1""" 

2Customisable progress bar decorator for iterators. 

3Includes a default `range` iterator printing to `stderr`. 

4 

5Usage: 

6>>> from tqdm import trange, tqdm 

7>>> for i in trange(10): 

8... ... 

9""" 

10import sys 

11from collections import OrderedDict, defaultdict 

12from contextlib import contextmanager 

13from datetime import datetime, timedelta, timezone 

14from numbers import Number 

15from time import time 

16from warnings import warn 

17from weakref import WeakSet 

18 

19from ._monitor import TMonitor 

20from .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 

32class TqdmTypeError(TypeError): 

33 pass 

34 

35 

36class TqdmKeyError(KeyError): 

37 pass 

38 

39 

40class 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): # noqa: B042 

46 if fp_write is not None: 

47 fp_write("\n" + self.__class__.__name__ + ": " + str(msg).rstrip() + '\n') 

48 else: 

49 super().__init__(msg) 

50 

51 

52class TqdmExperimentalWarning(TqdmWarning, FutureWarning): 

53 """beta feature, unstable API and behaviour""" 

54 

55 

56class TqdmDeprecationWarning(TqdmWarning, DeprecationWarning): 

57 """may be removed in a future release""" 

58 # not suppressed if raised 

59 

60 

61class TqdmMonitorWarning(TqdmWarning, RuntimeWarning): 

62 """tqdm monitor errors which do not affect external functionality""" 

63 

64 

65def TRLock(*args, **kwargs): 

66 """threading RLock""" 

67 try: 

68 from threading import RLock 

69 return RLock(*args, **kwargs) 

70 except (ImportError, OSError): # pragma: no cover 

71 pass 

72 

73 

74class TqdmDefaultWriteLock: 

75 """ 

76 Provide a default write lock for thread and multiprocessing safety. 

77 Works only on platforms supporting `fork` (so Windows is excluded). 

78 You must initialise a `tqdm` or `TqdmDefaultWriteLock` instance 

79 before forking in order for the write lock to work. 

80 On Windows, you need to supply the lock from the parent to the children as 

81 an argument to joblib or the parallelism lib you use. 

82 """ 

83 # global thread lock so no setup required for multithreading. 

84 # NB: Do not create multiprocessing lock as it sets the multiprocessing 

85 # context, disallowing `spawn()`/`forkserver()` 

86 th_lock = TRLock() 

87 

88 def __init__(self): 

89 # Create global parallelism locks to avoid racing issues with parallel 

90 # bars works only if fork available (Linux/MacOSX, but not Windows) 

91 cls = type(self) 

92 root_lock = cls.th_lock 

93 if root_lock is not None: 

94 root_lock.acquire() 

95 cls.create_mp_lock() 

96 self.locks = [lk for lk in [cls.mp_lock, cls.th_lock] if lk is not None] 

97 if root_lock is not None: 

98 root_lock.release() 

99 

100 def acquire(self, *a, **k): 

101 for lock in self.locks: 

102 lock.acquire(*a, **k) 

103 

104 def release(self): 

105 for lock in self.locks[::-1]: # Release in inverse order of acquisition 

106 lock.release() 

107 

108 def __enter__(self): 

109 self.acquire() 

110 

111 def __exit__(self, *exc): 

112 self.release() 

113 

114 @classmethod 

115 def create_mp_lock(cls): 

116 if not hasattr(cls, 'mp_lock'): 

117 try: 

118 from multiprocessing import RLock 

119 cls.mp_lock = RLock() 

120 except (ImportError, OSError): # pragma: no cover 

121 cls.mp_lock = None 

122 

123 @classmethod 

124 def create_th_lock(cls): 

125 assert hasattr(cls, 'th_lock') 

126 warn("create_th_lock not needed anymore", TqdmDeprecationWarning, stacklevel=2) 

127 

128 

129class Bar: 

130 """ 

131 `str.format`-able bar with format specifiers: `[width][type]` 

132 

133 - `width` 

134 + unspecified (default): use `self.default_len` 

135 + `int >= 0`: overrides `self.default_len` 

136 + `int < 0`: subtract from `self.default_len` 

137 - `type` 

138 + `a`: ascii (`charset=self.ASCII` override) 

139 + `u`: unicode (`charset=self.UTF` override) 

140 + `b`: blank (`charset=" "` override) 

141 """ 

142 ASCII = " 123456789#" 

143 UTF = " " + ''.join(map(chr, range(0x258F, 0x2587, -1))) 

144 BLANK = " " 

145 COLOUR_RESET = '\x1b[0m' 

146 COLOUR_RGB = '\x1b[38;2;%d;%d;%dm' 

147 COLOURS = {'BLACK': '\x1b[30m', 'RED': '\x1b[31m', 'GREEN': '\x1b[32m', 

148 'YELLOW': '\x1b[33m', 'BLUE': '\x1b[34m', 'MAGENTA': '\x1b[35m', 

149 'CYAN': '\x1b[36m', 'WHITE': '\x1b[37m'} 

150 

151 def __init__(self, frac, default_len=10, charset=UTF, colour=None): 

152 if not 0 <= frac <= 1: 

153 warn("clamping frac to range [0, 1]", TqdmWarning, stacklevel=2) 

154 frac = max(0, min(1, frac)) 

155 assert default_len > 0 

156 self.frac = frac 

157 self.default_len = default_len 

158 self.charset = charset 

159 self.colour = colour 

160 

161 @property 

162 def colour(self): 

163 return self._colour 

164 

165 @colour.setter 

166 def colour(self, value): 

167 if not value: 

168 self._colour = None 

169 return 

170 try: 

171 if value.upper() in self.COLOURS: 

172 self._colour = self.COLOURS[value.upper()] 

173 elif value[0] == '#' and len(value) == 7: 

174 self._colour = self.COLOUR_RGB % tuple( 

175 int(i, 16) for i in (value[1:3], value[3:5], value[5:7])) 

176 else: 

177 raise KeyError 

178 except (KeyError, AttributeError): 

179 warn(f"Unknown colour ({value}); valid choices:" 

180 f" [hex (#00ff00), {', '.join(self.COLOURS)}]", TqdmWarning, stacklevel=2) 

181 self._colour = None 

182 

183 def __format__(self, format_spec): 

184 if format_spec: 

185 _type = format_spec[-1].lower() 

186 try: 

187 charset = {'a': self.ASCII, 'u': self.UTF, 'b': self.BLANK}[_type] 

188 except KeyError: 

189 charset = self.charset 

190 else: 

191 format_spec = format_spec[:-1] 

192 if format_spec: 

193 N_BARS = int(format_spec) 

194 if N_BARS < 0: 

195 N_BARS += self.default_len 

196 else: 

197 N_BARS = self.default_len 

198 else: 

199 charset = self.charset 

200 N_BARS = self.default_len 

201 

202 nsyms = len(charset) - 1 

203 bar_length, frac_bar_length = divmod(int(self.frac * N_BARS * nsyms), nsyms) 

204 

205 res = charset[-1] * bar_length 

206 if bar_length < N_BARS: # whitespace padding 

207 res = res + charset[frac_bar_length] + charset[0] * (N_BARS - bar_length - 1) 

208 return self.colour + res + self.COLOUR_RESET if self.colour else res 

209 

210 

211class EMA: 

212 """ 

213 Exponential moving average: smoothing to give progressively lower 

214 weights to older values. 

215 

216 Parameters 

217 ---------- 

218 smoothing : float, optional 

219 Smoothing factor in range [0, 1], [default: 0.3]. 

220 Increase to give more weight to recent values. 

221 Ranges from 0 (yields old value) to 1 (yields new value). 

222 """ 

223 def __init__(self, smoothing=0.3): 

224 self.alpha = smoothing 

225 self.last = 0 

226 self.calls = 0 

227 

228 def __call__(self, x=None): 

229 """ 

230 Parameters 

231 ---------- 

232 x : float 

233 New value to include in EMA. 

234 """ 

235 beta = 1 - self.alpha 

236 if x is not None: 

237 self.last = self.alpha * x + beta * self.last 

238 self.calls += 1 

239 return self.last / (1 - beta ** self.calls) if self.calls else self.last 

240 

241 

242class tqdm(Comparable): 

243 """ 

244 Decorate an iterable object, returning an iterator which acts exactly 

245 like the original iterable, but prints a dynamically updating 

246 progress bar every time a value is requested. 

247 

248 Parameters 

249 ---------- 

250 iterable : iterable, optional 

251 Iterable to decorate with a progress bar. 

252 Leave blank to manually manage the updates. 

253 desc : str, optional 

254 Prefix for the progress bar. 

255 total : int or float, optional 

256 The number of expected iterations. If unspecified, 

257 len(iterable) is used if possible. If float("inf") or as a last 

258 resort, only basic progress statistics are displayed 

259 (no ETA, no progress bar). 

260 If `gui` is True and this parameter needs subsequent updating, 

261 specify an initial arbitrary large positive number, 

262 e.g. 9e9. 

263 leave : bool, optional 

264 If [default: True], keeps all traces of the progress bar 

265 upon termination of iteration. 

266 If `None`, will leave only if `position` is `0`. 

267 file : `io.TextIOWrapper` or `io.StringIO`, optional 

268 Specifies where to output the progress messages 

269 (default: sys.stderr). Uses `file.write(str)` and `file.flush()` 

270 methods. For encoding, see `write_bytes`. 

271 ncols : int, optional 

272 The width of the entire output message. If specified, 

273 dynamically resizes the progress bar to stay within this bound. 

274 If unspecified, attempts to use environment width. The 

275 fallback is a meter width of 10 and no limit for the counter and 

276 statistics. If 0, will not print any meter (only stats). 

277 mininterval : float, optional 

278 Minimum progress display update interval [default: 0.1] seconds. 

279 maxinterval : float, optional 

280 Maximum progress display update interval [default: 10] seconds. 

281 Automatically adjusts `miniters` to correspond to `mininterval` 

282 after long display update lag. Only works if `dynamic_miniters` 

283 or monitor thread is enabled. 

284 miniters : int or float, optional 

285 Minimum progress display update interval, in iterations. 

286 If 0 and `dynamic_miniters`, will automatically adjust to equal 

287 `mininterval` (more CPU efficient, good for tight loops). 

288 If > 0, will skip display of specified number of iterations. 

289 Tweak this and `mininterval` to get very efficient loops. 

290 If your progress is erratic with both fast and slow iterations 

291 (network, skipping items, etc) you should set miniters=1. 

292 ascii : bool or str, optional 

293 If unspecified or False, use unicode (smooth blocks) to fill 

294 the meter. The fallback is to use ASCII characters " 123456789#". 

295 disable : bool, optional 

296 Whether to disable the entire progress bar wrapper 

297 [default: False]. If set to None, disable on non-TTY. 

298 unit : str, optional 

299 String that will be used to define the unit of each iteration 

300 [default: it]. 

301 unit_scale : bool or int or float, optional 

302 If 1 or True, the number of iterations will be reduced/scaled 

303 automatically and a metric prefix following the 

304 International System of Units standard will be added 

305 (kilo, mega, etc.) [default: False]. If any other non-zero 

306 number, will scale `total` and `n`. 

307 dynamic_ncols : bool, optional 

308 If set, constantly alters `ncols` and `nrows` to the 

309 environment (allowing for window resizes) [default: False]. 

310 smoothing : float, optional 

311 Exponential moving average smoothing factor for speed estimates 

312 (ignored in GUI mode). Ranges from 0 (average speed) to 1 

313 (current/instantaneous speed) [default: 0.3]. 

314 bar_format : str, optional 

315 Specify a custom bar string formatting. May impact performance. 

316 [default: '{l_bar}{bar}{r_bar}'], where 

317 l_bar='{desc}: {percentage:3.0f}%|' and 

318 r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ' 

319 '{rate_fmt}{postfix}]' 

320 Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, 

321 percentage, elapsed, elapsed_s, ncols, nrows, desc, unit, 

322 rate, rate_fmt, rate_noinv, rate_noinv_fmt, 

323 rate_inv, rate_inv_fmt, postfix, unit_divisor, 

324 remaining, remaining_s, eta. 

325 Note that a trailing ": " is automatically removed after {desc} 

326 if the latter is empty. 

327 initial : int or float, optional 

328 The initial counter value. Useful when restarting a progress 

329 bar [default: 0]. If using float, consider specifying `{n:.3f}` 

330 or similar in `bar_format`, or specifying `unit_scale`. 

331 position : int, optional 

332 Specify the line offset to print this bar (starting from 0) 

333 Automatic if unspecified. 

334 Useful to manage multiple bars at once (eg, from threads). 

335 postfix : dict or *, optional 

336 Specify additional stats to display at the end of the bar. 

337 Calls `set_postfix(**postfix)` if possible (dict). 

338 unit_divisor : float, optional 

339 [default: 1000], ignored unless `unit_scale` is True. 

340 write_bytes : bool, optional 

341 Whether to write bytes. If (default: False) will write unicode. 

342 lock_args : tuple, optional 

343 Passed to `refresh` for intermediate output 

344 (initialisation, iterating, and updating). 

345 nrows : int, optional 

346 The screen height. If specified, hides nested bars outside this 

347 bound. If unspecified, attempts to use environment height. 

348 The fallback is 20. 

349 colour : str, optional 

350 Bar colour (e.g. 'green', '#00ff00'). 

351 delay : float, optional 

352 Don't display until [default: 0] seconds have elapsed. 

353 gui : bool, optional 

354 WARNING: internal parameter - do not use. 

355 Use tqdm.gui.tqdm(...) instead. If set, will attempt to use 

356 matplotlib animations for a graphical output [default: False]. 

357 

358 Returns 

359 ------- 

360 out : decorated iterator. 

361 """ 

362 

363 monitor_interval = 10 # set to 0 to disable the thread 

364 monitor = None 

365 _instances = WeakSet() 

366 

367 @staticmethod 

368 def format_sizeof(num, suffix='', divisor=1000): 

369 """ 

370 Formats a number (greater than unity) with SI Order of Magnitude 

371 prefixes. 

372 

373 Parameters 

374 ---------- 

375 num : float 

376 Number ( >= 1) to format. 

377 suffix : str, optional 

378 Post-postfix [default: '']. 

379 divisor : float, optional 

380 Divisor between prefixes [default: 1000]. 

381 

382 Returns 

383 ------- 

384 out : str 

385 Number with Order of Magnitude SI unit postfix. 

386 """ 

387 for unit in ['', 'k', 'M', 'G', 'T', 'P', 'E', 'Z']: 

388 if abs(num) < 999.5: 

389 if abs(num) < 99.95: 

390 if abs(num) < 9.995: 

391 return f'{num:1.2f}{unit}{suffix}' 

392 return f'{num:2.1f}{unit}{suffix}' 

393 return f'{num:3.0f}{unit}{suffix}' 

394 num /= divisor 

395 return f'{num:3.1f}Y{suffix}' 

396 

397 @staticmethod 

398 def format_interval(t): 

399 """ 

400 Formats a number of seconds as a clock time, [H:]MM:SS 

401 

402 Parameters 

403 ---------- 

404 t : int 

405 Number of seconds. 

406 

407 Returns 

408 ------- 

409 out : str 

410 [H:]MM:SS 

411 """ 

412 sign = '-' if t < 0 else '' 

413 mins, s = divmod(abs(int(t)), 60) 

414 h, m = divmod(mins, 60) 

415 return f'{sign}{h:d}:{m:02d}:{s:02d}' if h else f'{sign}{m:02d}:{s:02d}' 

416 

417 @staticmethod 

418 def format_num(n): 

419 """ 

420 Intelligent scientific notation (.3g). 

421 

422 Parameters 

423 ---------- 

424 n : int or float or Numeric 

425 A Number. 

426 

427 Returns 

428 ------- 

429 out : str 

430 Formatted number. 

431 """ 

432 f = f'{n:.3g}'.replace('e+0', 'e+').replace('e-0', 'e-') 

433 n = str(n) 

434 return f if len(f) < len(n) else n 

435 

436 @staticmethod 

437 def status_printer(file): 

438 """ 

439 Manage the printing and in-place updating of a line of characters. 

440 Note that if the string is longer than a line, then in-place 

441 updating may not work (it will print a new line at each refresh). 

442 """ 

443 fp = file 

444 fp_flush = getattr(fp, 'flush', lambda: None) # pragma: no cover 

445 if fp in (sys.stderr, sys.stdout): 

446 getattr(sys.stderr, 'flush', lambda: None)() 

447 getattr(sys.stdout, 'flush', lambda: None)() 

448 

449 def fp_write(s): 

450 fp.write(str(s)) 

451 fp_flush() 

452 

453 last_len = [0] 

454 

455 def print_status(s): 

456 len_s = disp_len(s) 

457 fp_write('\r' + s + (' ' * max(last_len[0] - len_s, 0))) 

458 last_len[0] = len_s 

459 

460 return print_status 

461 

462 @staticmethod 

463 def format_meter(n, total, elapsed, ncols=None, prefix='', 

464 ascii=False, # pylint: disable=redefined-builtin 

465 unit='it', unit_scale=False, rate=None, bar_format=None, postfix=None, 

466 unit_divisor=1000, initial=0, colour=None, **extra_kwargs): 

467 """ 

468 Return a string-based progress bar given some parameters 

469 

470 Parameters 

471 ---------- 

472 n : int or float 

473 Number of finished iterations. 

474 total : int or float 

475 The expected total number of iterations. If meaningless (None), 

476 only basic progress statistics are displayed (no ETA). 

477 elapsed : float 

478 Number of seconds passed since start. 

479 ncols : int, optional 

480 The width of the entire output message. If specified, 

481 dynamically resizes `{bar}` to stay within this bound 

482 [default: None]. If `0`, will not print any bar (only stats). 

483 The fallback is `{bar:10}`. 

484 prefix : str, optional 

485 Prefix message (included in total width) [default: '']. 

486 Use as {desc} in bar_format string. 

487 ascii : bool, optional or str, optional 

488 If not set, use unicode (smooth blocks) to fill the meter 

489 [default: False]. The fallback is to use ASCII characters 

490 " 123456789#". 

491 unit : str, optional 

492 The iteration unit [default: 'it']. 

493 unit_scale : bool or int or float, optional 

494 If 1 or True, the number of iterations will be printed with an 

495 appropriate SI metric prefix (k = 10^3, M = 10^6, etc.) 

496 [default: False]. If any other non-zero number, will scale 

497 `total` and `n`. 

498 rate : float, optional 

499 Manual override for iteration rate. 

500 If [default: None], uses n/elapsed. 

501 bar_format : str, optional 

502 Specify a custom bar string formatting. May impact performance. 

503 [default: '{l_bar}{bar}{r_bar}'], where 

504 l_bar='{desc}: {percentage:3.0f}%|' and 

505 r_bar='| {n_fmt}/{total_fmt} [{elapsed}<{remaining}, ' 

506 '{rate_fmt}{postfix}]' 

507 Possible vars: l_bar, bar, r_bar, n, n_fmt, total, total_fmt, 

508 percentage, elapsed, elapsed_s, ncols, nrows, desc, unit, 

509 rate, rate_fmt, rate_noinv, rate_noinv_fmt, 

510 rate_inv, rate_inv_fmt, postfix, unit_divisor, 

511 remaining, remaining_s, eta. 

512 Note that a trailing ": " is automatically removed after {desc} 

513 if the latter is empty. 

514 postfix : *, optional 

515 Similar to `prefix`, but placed at the end 

516 (e.g. for additional stats). 

517 Note: postfix is usually a string (not a dict) for this method, 

518 and will if possible be set to postfix = ', ' + postfix. 

519 However other types are supported (#382). 

520 unit_divisor : float, optional 

521 [default: 1000], ignored unless `unit_scale` is True. 

522 initial : int or float, optional 

523 The initial counter value [default: 0]. 

524 colour : str, optional 

525 Bar colour (e.g. 'green', '#00ff00'). 

526 

527 Returns 

528 ------- 

529 out : Formatted meter and stats, ready to display. 

530 """ 

531 

532 # sanity check: total 

533 if total and n >= (total + 0.5): # allow float imprecision (#849) 

534 total = None 

535 

536 # apply custom scale if necessary 

537 if unit_scale and unit_scale not in (True, 1): 

538 if total: 

539 total *= unit_scale 

540 n *= unit_scale 

541 if rate: 

542 rate *= unit_scale # by default rate = self.avg_dn / self.avg_dt 

543 unit_scale = False 

544 

545 elapsed_str = tqdm.format_interval(elapsed) 

546 

547 # if unspecified, attempt to use rate = average speed 

548 # (we allow manual override since predicting time is an arcane art) 

549 if rate is None and elapsed: 

550 rate = (n - initial) / elapsed 

551 inv_rate = 1 / rate if rate else None 

552 format_sizeof = tqdm.format_sizeof 

553 rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else f'{rate:5.2f}') 

554 if rate else '?') + unit + '/s' 

555 rate_inv_fmt = ( 

556 (format_sizeof(inv_rate) if unit_scale else f'{inv_rate:5.2f}') 

557 if inv_rate else '?') + 's/' + unit 

558 rate_fmt = rate_inv_fmt if inv_rate and inv_rate > 1 else rate_noinv_fmt 

559 

560 if unit_scale: 

561 n_fmt = format_sizeof(n, divisor=unit_divisor) 

562 total_fmt = format_sizeof(total, divisor=unit_divisor) if total is not None else '?' 

563 else: 

564 n_fmt = str(n) 

565 total_fmt = str(total) if total is not None else '?' 

566 

567 try: 

568 postfix = ', ' + postfix if postfix else '' 

569 except TypeError: 

570 pass 

571 

572 remaining = (total - n) / rate if rate and total else 0 

573 remaining_str = tqdm.format_interval(remaining) if rate else '?' 

574 try: 

575 eta_dt = (datetime.now() + timedelta(seconds=remaining) 

576 if rate and total else datetime.fromtimestamp(0, timezone.utc)) 

577 except OverflowError: 

578 eta_dt = datetime.max 

579 

580 # format the stats displayed to the left and right sides of the bar 

581 if prefix: 

582 # old prefix setup work around 

583 bool_prefix_colon_already = (prefix[-2:] == ": ") 

584 l_bar = prefix if bool_prefix_colon_already else prefix + ": " 

585 else: 

586 l_bar = '' 

587 

588 r_bar = f'| {n_fmt}/{total_fmt} [{elapsed_str}<{remaining_str}, {rate_fmt}{postfix}]' 

589 

590 # Custom bar formatting 

591 # Populate a dict with all available progress indicators 

592 format_dict = { 

593 # slight extension of self.format_dict 

594 'n': n, 'n_fmt': n_fmt, 'total': total, 'total_fmt': total_fmt, 

595 'elapsed': elapsed_str, 'elapsed_s': elapsed, 

596 'ncols': ncols, 'desc': prefix or '', 'unit': unit, 

597 'rate': inv_rate if inv_rate and inv_rate > 1 else rate, 

598 'rate_fmt': rate_fmt, 'rate_noinv': rate, 

599 'rate_noinv_fmt': rate_noinv_fmt, 'rate_inv': inv_rate, 

600 'rate_inv_fmt': rate_inv_fmt, 

601 'postfix': postfix, 'unit_divisor': unit_divisor, 

602 'colour': colour, 

603 # plus more useful definitions 

604 'remaining': remaining_str, 'remaining_s': remaining, 

605 'l_bar': l_bar, 'r_bar': r_bar, 'eta': eta_dt, 

606 **extra_kwargs} 

607 

608 # total is known: we can predict some stats 

609 if total: 

610 # fractional and percentage progress 

611 frac = n / total 

612 percentage = frac * 100 

613 

614 l_bar += f'{percentage:3.0f}%|' 

615 

616 if ncols == 0: 

617 return l_bar[:-1] + r_bar[1:] 

618 

619 format_dict.update(l_bar=l_bar) 

620 if bar_format: 

621 format_dict.update(percentage=percentage) 

622 

623 # auto-remove colon for empty `{desc}` 

624 if not prefix: 

625 bar_format = bar_format.replace("{desc}: ", '') 

626 else: 

627 bar_format = "{l_bar}{bar}{r_bar}" 

628 

629 full_bar = FormatReplace() 

630 nobar = bar_format.format(bar=full_bar, **format_dict) # no `{bar}` 

631 if not full_bar.format_called: 

632 return disp_trim(nobar, ncols) if ncols else nobar 

633 

634 # Formatting progress bar space available for bar's display 

635 full_bar = Bar(frac, 

636 max(1, ncols - disp_len(nobar)) if ncols else 10, 

637 charset=Bar.ASCII if ascii is True else ascii or Bar.UTF, 

638 colour=colour) 

639 if not _is_ascii(full_bar.charset) and _is_ascii(bar_format): 

640 bar_format = str(bar_format) 

641 res = bar_format.format(bar=full_bar, **format_dict) 

642 return disp_trim(res, ncols) if ncols else res 

643 

644 elif bar_format: 

645 # user-specified bar_format but no total 

646 l_bar += '|' 

647 format_dict.update(l_bar=l_bar, percentage=0) 

648 full_bar = FormatReplace() 

649 nobar = bar_format.format(bar=full_bar, **format_dict) 

650 if not full_bar.format_called: 

651 return disp_trim(nobar, ncols) if ncols else nobar 

652 full_bar = Bar(0, 

653 max(1, ncols - disp_len(nobar)) if ncols else 10, 

654 charset=Bar.BLANK, colour=colour) 

655 res = bar_format.format(bar=full_bar, **format_dict) 

656 return disp_trim(res, ncols) if ncols else res 

657 else: 

658 # no total: no bar & ETA, just progress stats 

659 res = (f'{(prefix + ": ") if prefix else ""}' 

660 f'{n_fmt}{unit} [{elapsed_str}, {rate_fmt}{postfix}]') 

661 return disp_trim(res, ncols) if ncols else res 

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 if fp is None: 

721 return 

722 with cls.external_write_mode(file=file, nolock=nolock): 

723 # Write the message 

724 fp.write(s) 

725 fp.write(end) 

726 

727 @classmethod 

728 @contextmanager 

729 def external_write_mode(cls, file=None, nolock=False): 

730 """ 

731 Disable tqdm within context and refresh tqdm when exits. 

732 Useful when writing to standard output stream 

733 """ 

734 fp = file if file is not None else sys.stdout 

735 if fp is None: 

736 yield 

737 return 

738 

739 try: 

740 if not nolock: 

741 cls.get_lock().acquire() 

742 # Clear all bars 

743 inst_cleared = [] 

744 for inst in getattr(cls, '_instances', []): 

745 # Clear instance if in the target output file 

746 # or if write output + tqdm output are both either 

747 # sys.stdout or sys.stderr (because both are mixed in terminal) 

748 if hasattr(inst, "start_t") and (inst.fp == fp or all( 

749 f in (sys.stdout, sys.stderr) for f in (fp, inst.fp))): 

750 inst.clear(nolock=True) 

751 inst_cleared.append(inst) 

752 yield 

753 # Force refresh display of bars we cleared 

754 for inst in inst_cleared: 

755 inst.refresh(nolock=True) 

756 finally: 

757 if not nolock: 

758 cls._lock.release() 

759 

760 @classmethod 

761 def set_lock(cls, lock): 

762 """Set the global lock.""" 

763 cls._lock = lock 

764 

765 @classmethod 

766 def get_lock(cls): 

767 """Get the global lock. Construct it if it does not exist.""" 

768 if not hasattr(cls, '_lock'): 

769 cls._lock = TqdmDefaultWriteLock() 

770 return cls._lock 

771 

772 @classmethod 

773 def pandas(cls, **tqdm_kwargs): 

774 """ 

775 Registers the current `tqdm` class with 

776 pandas.core. 

777 ( frame.DataFrame 

778 | series.Series 

779 | groupby.(generic.)DataFrameGroupBy 

780 | groupby.(generic.)SeriesGroupBy 

781 ).progress_apply 

782 

783 A new instance will be created every time `progress_apply` is called, 

784 and each instance will automatically `close()` upon completion. 

785 

786 Parameters 

787 ---------- 

788 tqdm_kwargs : arguments for the tqdm instance 

789 

790 Examples 

791 -------- 

792 >>> import pandas as pd 

793 >>> import numpy as np 

794 >>> from tqdm import tqdm 

795 >>> from tqdm.gui import tqdm as tqdm_gui 

796 >>> 

797 >>> df = pd.DataFrame(np.random.randint(0, 100, (100000, 6))) 

798 >>> tqdm.pandas(ncols=50) # can use tqdm_gui, optional kwargs, etc 

799 >>> # Now you can use `progress_apply` instead of `apply` 

800 >>> df.groupby(0).progress_apply(lambda x: x**2) 

801 

802 References 

803 ---------- 

804 <https://stackoverflow.com/questions/18603270/\ 

805 progress-indicator-during-pandas-operations-python> 

806 """ 

807 from warnings import catch_warnings, simplefilter 

808 

809 from pandas.core.frame import DataFrame 

810 from pandas.core.series import Series 

811 try: 

812 with catch_warnings(): 

813 simplefilter("ignore", category=FutureWarning) 

814 from pandas import Panel 

815 except ImportError: # pandas>=1.2.0 

816 Panel = None 

817 Rolling, Expanding = None, None 

818 try: # pandas>=1.0.0 

819 from pandas.core.window.rolling import _Rolling_and_Expanding 

820 except ImportError: 

821 try: # pandas>=0.18.0 

822 from pandas.core.window import _Rolling_and_Expanding 

823 except ImportError: # pandas>=1.2.0 

824 try: # pandas>=1.2.0 

825 from pandas.core.window.expanding import Expanding 

826 from pandas.core.window.rolling import Rolling 

827 _Rolling_and_Expanding = Rolling, Expanding 

828 except ImportError: # pragma: no cover 

829 _Rolling_and_Expanding = None 

830 try: # pandas>=0.25.0 

831 from pandas.core.groupby.generic import SeriesGroupBy # , NDFrameGroupBy 

832 from pandas.core.groupby.generic import DataFrameGroupBy 

833 except ImportError: # pragma: no cover 

834 try: # pandas>=0.23.0 

835 from pandas.core.groupby.groupby import DataFrameGroupBy, SeriesGroupBy 

836 except ImportError: 

837 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy 

838 try: # pandas>=0.23.0 

839 from pandas.core.groupby.groupby import GroupBy 

840 except ImportError: # pragma: no cover 

841 from pandas.core.groupby import GroupBy 

842 

843 try: # pandas>=0.23.0 

844 from pandas.core.groupby.groupby import PanelGroupBy 

845 except ImportError: 

846 try: 

847 from pandas.core.groupby import PanelGroupBy 

848 except ImportError: # pandas>=0.25.0 

849 PanelGroupBy = None 

850 

851 tqdm_kwargs = tqdm_kwargs.copy() 

852 deprecated_t = [tqdm_kwargs.pop('deprecated_t', None)] 

853 

854 def inner_generator(df_function='apply'): 

855 def inner(df, func, *args, **kwargs): 

856 """ 

857 Parameters 

858 ---------- 

859 df : (DataFrame|Series)[GroupBy] 

860 Data (may be grouped). 

861 func : function 

862 To be applied on the (grouped) data. 

863 **kwargs : optional 

864 Transmitted to `df.apply()`. 

865 """ 

866 

867 # Precompute total iterations 

868 total = tqdm_kwargs.pop("total", getattr(df, 'ngroups', None)) 

869 if total is None: # not grouped 

870 if df_function == 'applymap': 

871 total = df.size 

872 elif isinstance(df, Series): 

873 total = len(df) 

874 elif (_Rolling_and_Expanding is None or 

875 not isinstance(df, _Rolling_and_Expanding)): 

876 # DataFrame or Panel 

877 axis = kwargs.get('axis', 0) 

878 if axis == 'index': 

879 axis = 0 

880 elif axis == 'columns': 

881 axis = 1 

882 # when axis=0, total is shape[axis1] 

883 total = df.size // df.shape[axis] 

884 

885 # Init bar 

886 if deprecated_t[0] is not None: 

887 t = deprecated_t[0] 

888 deprecated_t[0] = None 

889 else: 

890 t = cls(total=total, **tqdm_kwargs) 

891 

892 if len(args) > 0: 

893 # *args intentionally not supported (see #244, #299) 

894 TqdmDeprecationWarning( 

895 "Except func, normal arguments are intentionally" + 

896 " not supported by" + 

897 " `(DataFrame|Series|GroupBy).progress_apply`." + 

898 " Use keyword arguments instead.", 

899 fp_write=getattr(t.fp, 'write', sys.stderr.write)) 

900 

901 try: # pandas>=1.3.0,<3.0 

902 from pandas.core.common import is_builtin_func 

903 except ImportError: # pandas<1.3.0 

904 is_builtin_func = getattr(df, '_is_builtin_func', lambda f: f) 

905 try: 

906 func = is_builtin_func(func) 

907 except TypeError: 

908 pass 

909 

910 # Define bar updating wrapper 

911 def wrapper(*args, **kwargs): 

912 # update tbar correctly 

913 # it seems `pandas apply` calls `func` twice 

914 # on the first column/row to decide whether it can 

915 # take a fast or slow code path; so stop when t.total==t.n 

916 t.update(n=1 if not t.total or t.n < t.total else 0) 

917 return func(*args, **kwargs) 

918 

919 # Apply the provided function (in **kwargs) 

920 # on the df using our wrapper (which provides bar updating) 

921 try: 

922 return getattr(df, df_function)(wrapper, **kwargs) 

923 finally: 

924 t.close() 

925 

926 return inner 

927 

928 # Monkeypatch pandas to provide easy methods 

929 # Enable custom tqdm progress in pandas! 

930 Series.progress_apply = inner_generator() 

931 SeriesGroupBy.progress_apply = inner_generator() 

932 Series.progress_map = inner_generator('map') 

933 SeriesGroupBy.progress_map = inner_generator('map') 

934 

935 DataFrame.progress_apply = inner_generator() 

936 DataFrameGroupBy.progress_apply = inner_generator() 

937 DataFrame.progress_applymap = inner_generator('applymap') 

938 DataFrame.progress_map = inner_generator('map') 

939 DataFrameGroupBy.progress_map = inner_generator('map') 

940 

941 if Panel is not None: 

942 Panel.progress_apply = inner_generator() 

943 if PanelGroupBy is not None: 

944 PanelGroupBy.progress_apply = inner_generator() 

945 

946 GroupBy.progress_apply = inner_generator() 

947 GroupBy.progress_aggregate = inner_generator('aggregate') 

948 GroupBy.progress_transform = inner_generator('transform') 

949 

950 if Rolling is not None and Expanding is not None: 

951 Rolling.progress_apply = inner_generator() 

952 Expanding.progress_apply = inner_generator() 

953 elif _Rolling_and_Expanding is not None: 

954 _Rolling_and_Expanding.progress_apply = inner_generator() 

955 

956 # override defaults via env vars 

957 @envwrap("tqdm", is_method=True, types={'total': float, 'ncols': int, 'miniters': float, 

958 'position': int, 'nrows': int}) 

959 def __init__(self, iterable=None, desc=None, total=None, leave=True, file=None, 

960 ncols=None, mininterval=0.1, maxinterval=10.0, miniters=None, 

961 ascii=None, # pylint: disable=redefined-builtin 

962 disable=False, unit='it', unit_scale=False, dynamic_ncols=False, smoothing=0.3, 

963 bar_format=None, initial=0, position=None, postfix=None, unit_divisor=1000, 

964 write_bytes=False, lock_args=None, nrows=None, colour=None, delay=0.0, gui=False, 

965 **kwargs): 

966 """see tqdm.tqdm for arguments""" 

967 if file is None: 

968 file = sys.stderr 

969 

970 if write_bytes: 

971 # Despite coercing unicode into bytes, py2 sys.std* streams 

972 # should have bytes written to them. 

973 file = SimpleTextIOWrapper( 

974 file, encoding=getattr(file, 'encoding', None) or 'utf-8') 

975 

976 file = DisableOnWriteError(file, tqdm_instance=self) 

977 

978 if disable is None and hasattr(file, "isatty") and not file.isatty(): 

979 disable = True 

980 

981 if total is None and iterable is not None: 

982 try: 

983 total = len(iterable) 

984 except (TypeError, AttributeError): 

985 total = None 

986 if total == float("inf"): 

987 # Infinite iterations, behave same as unknown 

988 total = None 

989 

990 if disable: 

991 self.iterable = iterable 

992 self.disable = disable 

993 with self._lock: 

994 self.pos = self._get_free_pos(self) 

995 self._instances.remove(self) 

996 self.n = initial 

997 self.total = total 

998 self.leave = leave 

999 return 

1000 

1001 if kwargs: 

1002 self.disable = True 

1003 with self._lock: 

1004 self.pos = self._get_free_pos(self) 

1005 self._instances.remove(self) 

1006 raise ( 

1007 TqdmDeprecationWarning( 

1008 "`nested` is deprecated and automated.\n" 

1009 "Use `position` instead for manual control.\n", 

1010 fp_write=getattr(file, 'write', sys.stderr.write)) 

1011 if "nested" in kwargs else 

1012 TqdmKeyError("Unknown argument(s): " + str(kwargs))) 

1013 

1014 # Preprocess the arguments 

1015 if ( 

1016 (ncols is None or nrows is None) and (file in (sys.stderr, sys.stdout)) 

1017 ) or dynamic_ncols: # pragma: no cover 

1018 if dynamic_ncols: 

1019 dynamic_ncols = _screen_shape_wrapper() 

1020 if dynamic_ncols: 

1021 ncols, nrows = dynamic_ncols(file) 

1022 else: 

1023 _dynamic_ncols = _screen_shape_wrapper() 

1024 if _dynamic_ncols: 

1025 _ncols, _nrows = _dynamic_ncols(file) 

1026 if ncols is None: 

1027 ncols = _ncols 

1028 if nrows is None: 

1029 nrows = _nrows 

1030 

1031 if miniters is None: 

1032 miniters = 0 

1033 dynamic_miniters = True 

1034 else: 

1035 dynamic_miniters = False 

1036 

1037 if mininterval is None: 

1038 mininterval = 0 

1039 

1040 if maxinterval is None: 

1041 maxinterval = 0 

1042 

1043 if ascii is None: 

1044 ascii = not _supports_unicode(file) 

1045 

1046 if bar_format and ascii is not True and not _is_ascii(ascii): 

1047 # Convert bar format into unicode since terminal uses unicode 

1048 bar_format = str(bar_format) 

1049 

1050 if smoothing is None: 

1051 smoothing = 0 

1052 

1053 # Store the arguments 

1054 self.iterable = iterable 

1055 self.desc = desc or '' 

1056 self.total = total 

1057 self.leave = leave 

1058 self.fp = file 

1059 self.ncols = ncols 

1060 self.nrows = nrows 

1061 self.mininterval = mininterval 

1062 self.maxinterval = maxinterval 

1063 self.miniters = miniters 

1064 self.dynamic_miniters = dynamic_miniters 

1065 self.ascii = ascii 

1066 self.disable = disable 

1067 self.unit = unit 

1068 self.unit_scale = unit_scale 

1069 self.unit_divisor = unit_divisor 

1070 self.initial = initial 

1071 self.lock_args = lock_args 

1072 self.delay = delay 

1073 self.gui = gui 

1074 self.dynamic_ncols = dynamic_ncols 

1075 self.smoothing = smoothing 

1076 self._ema_dn = EMA(smoothing) 

1077 self._ema_dt = EMA(smoothing) 

1078 self._ema_miniters = EMA(smoothing) 

1079 self.bar_format = bar_format 

1080 self.postfix = None 

1081 self.colour = colour 

1082 self._time = time 

1083 if postfix: 

1084 try: 

1085 self.set_postfix(refresh=False, **postfix) 

1086 except TypeError: 

1087 self.postfix = postfix 

1088 

1089 # Init the iterations counters 

1090 self.last_print_n = initial 

1091 self.n = initial 

1092 

1093 # if nested, at initial sp() call we replace '\r' by '\n' to 

1094 # not overwrite the outer progress bar 

1095 with self._lock: 

1096 # mark fixed positions as negative 

1097 self.pos = self._get_free_pos(self) if position is None else -position 

1098 

1099 if not gui: 

1100 # Initialize the screen printer 

1101 self.sp = self.status_printer(self.fp) 

1102 if delay <= 0: 

1103 self.refresh(lock_args=self.lock_args) 

1104 

1105 # Init the time counter 

1106 self.last_print_t = self._time() 

1107 # NB: Avoid race conditions by setting start_t at the very end of init 

1108 self.start_t = self.last_print_t 

1109 

1110 def __bool__(self): 

1111 if self.total is not None: 

1112 return self.total > 0 

1113 if self.iterable is None: 

1114 raise TypeError('bool() undefined when iterable == total == None') 

1115 return bool(self.iterable) 

1116 

1117 def __len__(self): 

1118 return ( 

1119 self.total if self.iterable is None 

1120 else self.iterable.shape[0] if hasattr(self.iterable, "shape") 

1121 else len(self.iterable) if hasattr(self.iterable, "__len__") 

1122 else self.iterable.__length_hint__() if hasattr(self.iterable, "__length_hint__") 

1123 else getattr(self, "total", None)) 

1124 

1125 def __reversed__(self): 

1126 try: 

1127 orig = self.iterable 

1128 except AttributeError: 

1129 raise TypeError("'tqdm' object is not reversible") 

1130 else: 

1131 self.iterable = reversed(self.iterable) 

1132 return self.__iter__() 

1133 finally: 

1134 self.iterable = orig 

1135 

1136 def __contains__(self, item): 

1137 contains = getattr(self.iterable, '__contains__', None) 

1138 return (contains(item) if contains is not None # pylint: disable=not-callable 

1139 else item in self.__iter__()) 

1140 

1141 def __enter__(self): 

1142 return self 

1143 

1144 def __exit__(self, exc_type, exc_value, traceback): 

1145 try: 

1146 self.close() 

1147 except AttributeError: 

1148 # maybe eager thread cleanup upon external error 

1149 if (exc_type, exc_value, traceback) == (None, None, None): 

1150 raise 

1151 warn("AttributeError ignored", TqdmWarning, stacklevel=2) 

1152 

1153 def __del__(self): 

1154 self.close() 

1155 

1156 def __str__(self): 

1157 return self.format_meter(**self.format_dict) 

1158 

1159 @property 

1160 def _comparable(self): 

1161 return abs(getattr(self, "pos", 1 << 31)) 

1162 

1163 def __hash__(self): 

1164 return id(self) 

1165 

1166 def __iter__(self): 

1167 """Backward-compatibility to use: for x in tqdm(iterable)""" 

1168 

1169 # Inlining instance variables as locals (speed optimisation) 

1170 iterable = self.iterable 

1171 

1172 # If the bar is disabled, then just walk the iterable 

1173 # (note: keep this check outside the loop for performance) 

1174 if self.disable: 

1175 for obj in iterable: 

1176 yield obj 

1177 return 

1178 

1179 mininterval = self.mininterval 

1180 last_print_t = self.last_print_t 

1181 last_print_n = self.last_print_n 

1182 min_start_t = self.start_t + self.delay 

1183 n = self.n 

1184 time = self._time 

1185 

1186 try: 

1187 for obj in iterable: 

1188 yield obj 

1189 # Update and possibly print the progress bar. 

1190 # Note: does not call self.update(1) for speed optimisation. 

1191 n += 1 

1192 

1193 if n - last_print_n >= self.miniters: 

1194 cur_t = time() 

1195 dt = cur_t - last_print_t 

1196 if dt >= mininterval and cur_t >= min_start_t: 

1197 self.update(n - last_print_n) 

1198 last_print_n = self.last_print_n 

1199 last_print_t = self.last_print_t 

1200 finally: 

1201 self.n = n 

1202 self.close() 

1203 

1204 def update(self, n=1): 

1205 """ 

1206 Manually update the progress bar, useful for streams 

1207 such as reading files. 

1208 E.g.: 

1209 >>> t = tqdm(total=filesize) # Initialise 

1210 >>> for current_buffer in stream: 

1211 ... ... 

1212 ... t.update(len(current_buffer)) 

1213 >>> t.close() 

1214 The last line is highly recommended, but possibly not necessary if 

1215 `t.update()` will be called in such a way that `filesize` will be 

1216 exactly reached and printed. 

1217 

1218 Parameters 

1219 ---------- 

1220 n : int or float, optional 

1221 Increment to add to the internal counter of iterations 

1222 [default: 1]. If using float, consider specifying `{n:.3f}` 

1223 or similar in `bar_format`, or specifying `unit_scale`. 

1224 

1225 Returns 

1226 ------- 

1227 out : bool or None 

1228 True if a `display()` was triggered. 

1229 """ 

1230 if self.disable: 

1231 return 

1232 

1233 if n < 0: 

1234 self.last_print_n += n # for auto-refresh logic to work 

1235 self.n += n 

1236 

1237 # check counter first to reduce calls to time() 

1238 if self.n - self.last_print_n >= self.miniters: 

1239 cur_t = self._time() 

1240 dt = cur_t - self.last_print_t 

1241 if dt >= self.mininterval and cur_t >= self.start_t + self.delay: 

1242 cur_t = self._time() 

1243 dn = self.n - self.last_print_n # >= n 

1244 if self.smoothing and dt and dn: 

1245 # EMA (not just overall average) 

1246 self._ema_dn(dn) 

1247 self._ema_dt(dt) 

1248 self.refresh(lock_args=self.lock_args) 

1249 if self.dynamic_miniters: 

1250 # If no `miniters` was specified, adjust automatically to the 

1251 # maximum iteration rate seen so far between two prints. 

1252 # e.g.: After running `tqdm.update(5)`, subsequent 

1253 # calls to `tqdm.update()` will only cause an update after 

1254 # at least 5 more iterations. 

1255 if self.maxinterval and dt >= self.maxinterval: 

1256 self.miniters = dn * (self.mininterval or self.maxinterval) / dt 

1257 elif self.smoothing: 

1258 # EMA miniters update 

1259 self.miniters = self._ema_miniters( 

1260 dn * (self.mininterval / dt if self.mininterval and dt 

1261 else 1)) 

1262 else: 

1263 # max iters between two prints 

1264 self.miniters = max(self.miniters, dn) 

1265 

1266 # Store old values for next call 

1267 self.last_print_n = self.n 

1268 self.last_print_t = cur_t 

1269 return True 

1270 

1271 def close(self): 

1272 """Cleanup and (if leave=False) close the progress bar.""" 

1273 if self.disable: 

1274 return 

1275 

1276 # Prevent multiple closures 

1277 self.disable = True 

1278 

1279 # decrement instance pos and remove from internal set 

1280 pos = abs(self.pos) 

1281 self._decr_instances(self) 

1282 

1283 if self.last_print_t < self.start_t + self.delay: 

1284 # haven't ever displayed; nothing to clear 

1285 return 

1286 

1287 # GUI mode 

1288 if getattr(self, 'sp', None) is None: 

1289 return 

1290 

1291 # annoyingly, _supports_unicode isn't good enough 

1292 def fp_write(s): 

1293 self.fp.write(str(s)) 

1294 

1295 try: 

1296 fp_write('') 

1297 except ValueError as e: 

1298 if 'closed' in str(e): 

1299 return 

1300 raise # pragma: no cover 

1301 

1302 leave = pos == 0 if self.leave is None else self.leave 

1303 

1304 with self._lock: 

1305 if leave: 

1306 # stats for overall rate (no weighted average) 

1307 self._ema_dt = lambda: None 

1308 self.display(pos=0) 

1309 fp_write('\n') 

1310 else: 

1311 # clear previous display 

1312 if self.display(msg='', pos=pos) and not pos: 

1313 fp_write('\r') 

1314 

1315 def clear(self, nolock=False): 

1316 """Clear current bar display.""" 

1317 if self.disable: 

1318 return 

1319 

1320 if not nolock: 

1321 self._lock.acquire() 

1322 pos = abs(self.pos) 

1323 if pos < (self.nrows or 20): 

1324 self.moveto(pos) 

1325 self.sp('') 

1326 self.fp.write('\r') # place cursor back at the beginning of line 

1327 self.moveto(-pos) 

1328 if not nolock: 

1329 self._lock.release() 

1330 

1331 def refresh(self, nolock=False, lock_args=None): 

1332 """ 

1333 Force refresh the display of this bar. 

1334 

1335 Parameters 

1336 ---------- 

1337 nolock : bool, optional 

1338 If `True`, does not lock. 

1339 If [default: `False`]: calls `acquire()` on internal lock. 

1340 lock_args : tuple, optional 

1341 Passed to internal lock's `acquire()`. 

1342 If specified, will only `display()` if `acquire()` returns `True`. 

1343 """ 

1344 if self.disable: 

1345 return 

1346 

1347 if not nolock: 

1348 if lock_args: 

1349 if not self._lock.acquire(*lock_args): 

1350 return False 

1351 else: 

1352 self._lock.acquire() 

1353 self.display() 

1354 if not nolock: 

1355 self._lock.release() 

1356 return True 

1357 

1358 def unpause(self): 

1359 """Restart tqdm timer from last print time.""" 

1360 if self.disable: 

1361 return 

1362 cur_t = self._time() 

1363 self.start_t += cur_t - self.last_print_t 

1364 self.last_print_t = cur_t 

1365 

1366 def reset(self, total=None): 

1367 """ 

1368 Resets to 0 iterations for repeated use. 

1369 

1370 Consider combining with `leave=True`. 

1371 

1372 Parameters 

1373 ---------- 

1374 total : int or float, optional. Total to use for the new bar. 

1375 """ 

1376 self.n = 0 

1377 if total is not None: 

1378 self.total = total 

1379 if self.disable: 

1380 return 

1381 self.last_print_n = 0 

1382 self.last_print_t = self.start_t = self._time() 

1383 self._ema_dn = EMA(self.smoothing) 

1384 self._ema_dt = EMA(self.smoothing) 

1385 self._ema_miniters = EMA(self.smoothing) 

1386 self.refresh() 

1387 

1388 def set_description(self, desc=None, refresh=True): 

1389 """ 

1390 Set/modify description of the progress bar. 

1391 

1392 Parameters 

1393 ---------- 

1394 desc : str, optional 

1395 refresh : bool, optional 

1396 Forces refresh [default: True]. 

1397 """ 

1398 self.desc = desc + ': ' if desc else '' 

1399 if refresh: 

1400 self.refresh() 

1401 

1402 def set_description_str(self, desc=None, refresh=True): 

1403 """Set/modify description without ': ' appended.""" 

1404 self.desc = desc or '' 

1405 if refresh: 

1406 self.refresh() 

1407 

1408 def set_postfix(self, ordered_dict=None, refresh=True, **kwargs): 

1409 """ 

1410 Set/modify postfix (additional stats) 

1411 with automatic formatting based on datatype. 

1412 

1413 Parameters 

1414 ---------- 

1415 ordered_dict : dict or OrderedDict, optional 

1416 refresh : bool, optional 

1417 Forces refresh [default: True]. 

1418 kwargs : dict, optional 

1419 """ 

1420 # Sort in alphabetical order to be more deterministic 

1421 postfix = OrderedDict([] if ordered_dict is None else ordered_dict) 

1422 for key in sorted(kwargs.keys()): 

1423 postfix[key] = kwargs[key] 

1424 # Preprocess stats according to datatype 

1425 for key in postfix.keys(): 

1426 # Number: limit the length of the string 

1427 if isinstance(postfix[key], Number): 

1428 postfix[key] = self.format_num(postfix[key]) 

1429 # Else for any other type, try to get the string conversion 

1430 elif not isinstance(postfix[key], str): 

1431 postfix[key] = str(postfix[key]) 

1432 # Else if it's a string, don't need to preprocess anything 

1433 # Stitch together to get the final postfix 

1434 self.postfix = ', '.join(key + '=' + postfix[key].strip() 

1435 for key in postfix.keys()) 

1436 if refresh: 

1437 self.refresh() 

1438 

1439 def set_postfix_str(self, s='', refresh=True): 

1440 """ 

1441 Postfix without dictionary expansion, similar to prefix handling. 

1442 """ 

1443 self.postfix = str(s) 

1444 if refresh: 

1445 self.refresh() 

1446 

1447 def moveto(self, n): 

1448 # TODO: private method 

1449 self.fp.write('\n' * n + _term_move_up() * -n) 

1450 getattr(self.fp, 'flush', lambda: None)() 

1451 

1452 @property 

1453 def format_dict(self): 

1454 """Public API for read-only member access.""" 

1455 if self.disable and not hasattr(self, 'unit'): 

1456 return defaultdict(lambda: None, { 

1457 'n': self.n, 'total': self.total, 'elapsed': 0, 'unit': 'it'}) 

1458 if self.dynamic_ncols: 

1459 self.ncols, self.nrows = self.dynamic_ncols(self.fp) 

1460 return { 

1461 'n': self.n, 'total': self.total, 

1462 'elapsed': self._time() - self.start_t if hasattr(self, 'start_t') else 0, 

1463 'ncols': self.ncols, 'nrows': self.nrows, 'prefix': self.desc, 

1464 'ascii': self.ascii, 'unit': self.unit, 'unit_scale': self.unit_scale, 

1465 'rate': self._ema_dn() / self._ema_dt() if self._ema_dt() else None, 

1466 'bar_format': self.bar_format, 'postfix': self.postfix, 

1467 'unit_divisor': self.unit_divisor, 'initial': self.initial, 

1468 'colour': self.colour} 

1469 

1470 def display(self, msg=None, pos=None): 

1471 """ 

1472 Use `self.sp` to display `msg` in the specified `pos`. 

1473 

1474 Consider overloading this function when inheriting to use e.g.: 

1475 `self.some_frontend(**self.format_dict)` instead of `self.sp`. 

1476 

1477 Parameters 

1478 ---------- 

1479 msg : str, optional. What to display (default: `repr(self)`). 

1480 pos : int, optional. Position to `moveto` 

1481 (default: `abs(self.pos)`). 

1482 """ 

1483 if pos is None: 

1484 pos = abs(self.pos) 

1485 

1486 nrows = self.nrows or 20 

1487 if pos >= nrows - 1: 

1488 if pos >= nrows: 

1489 return False 

1490 if msg or msg is None: # override at `nrows - 1` 

1491 msg = " ... (more hidden) ..." 

1492 

1493 if not hasattr(self, "sp"): 

1494 raise TqdmDeprecationWarning( 

1495 "Please use `tqdm.gui.tqdm(...)`" 

1496 " instead of `tqdm(..., gui=True)`\n", 

1497 fp_write=getattr(self.fp, 'write', sys.stderr.write)) 

1498 

1499 if pos: 

1500 self.moveto(pos) 

1501 self.sp(self.__str__() if msg is None else msg) 

1502 if pos: 

1503 self.moveto(-pos) 

1504 return True 

1505 

1506 @classmethod 

1507 @contextmanager 

1508 def wrapattr(cls, stream, method, total=None, bytes=True, # pylint: disable=redefined-builtin 

1509 **tqdm_kwargs): 

1510 """ 

1511 stream : file-like object. 

1512 method : str, "read" or "write". The result of `read()` and 

1513 the first argument of `write()` should have a `len()`. 

1514 

1515 >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj: 

1516 ... while True: 

1517 ... chunk = fobj.read(chunk_size) 

1518 ... if not chunk: 

1519 ... break 

1520 """ 

1521 with cls(total=total, **tqdm_kwargs) as t: 

1522 if bytes: 

1523 t.unit = "B" 

1524 t.unit_scale = True 

1525 t.unit_divisor = 1024 

1526 yield CallbackIOWrapper(t.update, stream, method) 

1527 

1528 

1529def trange(*args, **kwargs): 

1530 """Shortcut for tqdm(range(*args), **kwargs).""" 

1531 return tqdm(range(*args), **kwargs)