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

702 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) or total == float("inf")): 

534 # allow float imprecision (#849) or inf (#651) 

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) # no `{bar}` 

632 if not full_bar.format_called: 

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

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 disp_trim(nobar, ncols) if ncols else 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 bar & ETA, just progress stats 

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

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

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

663 

664 def __new__(cls, *_, **__): 

665 instance = object.__new__(cls) 

666 with cls.get_lock(): # also constructs lock if non-existent 

667 cls._instances.add(instance) 

668 # create monitoring thread 

669 if cls.monitor_interval and (cls.monitor is None 

670 or not cls.monitor.report()): 

671 try: 

672 cls.monitor = TMonitor(cls, cls.monitor_interval) 

673 except Exception as e: # pragma: nocover 

674 warn("tqdm:disabling monitor support" 

675 " (monitor_interval = 0) due to:\n" + str(e), 

676 TqdmMonitorWarning, stacklevel=2) 

677 cls.monitor_interval = 0 

678 return instance 

679 

680 @classmethod 

681 def _get_free_pos(cls, instance=None): 

682 """Skips specified instance.""" 

683 positions = {abs(inst.pos) for inst in cls._instances 

684 if inst is not instance and hasattr(inst, "pos")} 

685 return min(set(range(len(positions) + 1)).difference(positions)) 

686 

687 @classmethod 

688 def _decr_instances(cls, instance): 

689 """ 

690 Remove from list and reposition another unfixed bar 

691 to fill the new gap. 

692 

693 This means that by default (where all nested bars are unfixed), 

694 order is not maintained but screen flicker/blank space is minimised. 

695 (tqdm<=4.44.1 moved ALL subsequent unfixed bars up.) 

696 """ 

697 with cls._lock: 

698 try: 

699 cls._instances.remove(instance) 

700 except KeyError: 

701 # if not instance.gui: # pragma: no cover 

702 # raise 

703 pass # py2: maybe magically removed already 

704 # else: 

705 if not instance.gui: 

706 last = (instance.nrows or 20) - 1 

707 # find unfixed (`pos >= 0`) overflow (`pos >= nrows - 1`) 

708 instances = list(filter( 

709 lambda i: hasattr(i, "pos") and last <= i.pos, 

710 cls._instances)) 

711 # set first found to current `pos` 

712 if instances: 

713 inst = min(instances, key=lambda i: i.pos) 

714 inst.clear(nolock=True) 

715 inst.pos = abs(instance.pos) 

716 

717 @classmethod 

718 def write(cls, s, file=None, end="\n", nolock=False): 

719 """Print a message via tqdm (without overlap with bars).""" 

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

721 if fp is None: 

722 return 

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

724 # Write the message 

725 fp.write(s) 

726 fp.write(end) 

727 

728 @classmethod 

729 @contextmanager 

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

731 """ 

732 Disable tqdm within context and refresh tqdm when exits. 

733 Useful when writing to standard output stream 

734 """ 

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

736 if fp is None: 

737 yield 

738 return 

739 

740 try: 

741 if not nolock: 

742 cls.get_lock().acquire() 

743 # Clear all bars 

744 inst_cleared = [] 

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

746 # Clear instance if in the target output file 

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

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

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

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

751 inst.clear(nolock=True) 

752 inst_cleared.append(inst) 

753 yield 

754 # Force refresh display of bars we cleared 

755 for inst in inst_cleared: 

756 inst.refresh(nolock=True) 

757 finally: 

758 if not nolock: 

759 cls._lock.release() 

760 

761 @classmethod 

762 def set_lock(cls, lock): 

763 """Set the global lock.""" 

764 cls._lock = lock 

765 

766 @classmethod 

767 def get_lock(cls): 

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

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

770 cls._lock = TqdmDefaultWriteLock() 

771 return cls._lock 

772 

773 @classmethod 

774 def pandas(cls, **tqdm_kwargs): 

775 """ 

776 Registers the current `tqdm` class with 

777 pandas.core. 

778 ( frame.DataFrame 

779 | series.Series 

780 | groupby.(generic.)DataFrameGroupBy 

781 | groupby.(generic.)SeriesGroupBy 

782 ).progress_apply 

783 

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

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

786 

787 Parameters 

788 ---------- 

789 tqdm_kwargs : arguments for the tqdm instance 

790 

791 Examples 

792 -------- 

793 >>> import pandas as pd 

794 >>> import numpy as np 

795 >>> from tqdm import tqdm 

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

797 >>> 

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

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

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

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

802 

803 References 

804 ---------- 

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

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

807 """ 

808 from warnings import catch_warnings, simplefilter 

809 

810 from pandas.core.frame import DataFrame 

811 from pandas.core.series import Series 

812 try: 

813 with catch_warnings(): 

814 simplefilter("ignore", category=FutureWarning) 

815 from pandas import Panel 

816 except ImportError: # pandas>=1.2.0 

817 Panel = None 

818 Rolling, Expanding = None, None 

819 try: # pandas>=1.0.0 

820 from pandas.core.window.rolling import _Rolling_and_Expanding 

821 except ImportError: 

822 try: # pandas>=0.18.0 

823 from pandas.core.window import _Rolling_and_Expanding 

824 except ImportError: # pandas>=1.2.0 

825 try: # pandas>=1.2.0 

826 from pandas.core.window.expanding import Expanding 

827 from pandas.core.window.rolling import Rolling 

828 _Rolling_and_Expanding = Rolling, Expanding 

829 except ImportError: # pragma: no cover 

830 _Rolling_and_Expanding = None 

831 try: # pandas>=0.25.0 

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

833 from pandas.core.groupby.generic import DataFrameGroupBy 

834 except ImportError: # pragma: no cover 

835 try: # pandas>=0.23.0 

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

837 except ImportError: 

838 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy 

839 try: # pandas>=0.23.0 

840 from pandas.core.groupby.groupby import GroupBy 

841 except ImportError: # pragma: no cover 

842 from pandas.core.groupby import GroupBy 

843 

844 try: # pandas>=0.23.0 

845 from pandas.core.groupby.groupby import PanelGroupBy 

846 except ImportError: 

847 try: 

848 from pandas.core.groupby import PanelGroupBy 

849 except ImportError: # pandas>=0.25.0 

850 PanelGroupBy = None 

851 

852 tqdm_kwargs = tqdm_kwargs.copy() 

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

854 

855 def inner_generator(df_function='apply'): 

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

857 """ 

858 Parameters 

859 ---------- 

860 df : (DataFrame|Series)[GroupBy] 

861 Data (may be grouped). 

862 func : function 

863 To be applied on the (grouped) data. 

864 **kwargs : optional 

865 Transmitted to `df.apply()`. 

866 """ 

867 

868 # Precompute total iterations 

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

870 if total is None: # not grouped 

871 if df_function == 'applymap': 

872 total = df.size 

873 elif isinstance(df, Series): 

874 total = len(df) 

875 elif (_Rolling_and_Expanding is None or 

876 not isinstance(df, _Rolling_and_Expanding)): 

877 # DataFrame or Panel 

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

879 if axis == 'index': 

880 axis = 0 

881 elif axis == 'columns': 

882 axis = 1 

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

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

885 

886 # Init bar 

887 if deprecated_t[0] is not None: 

888 t = deprecated_t[0] 

889 deprecated_t[0] = None 

890 else: 

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

892 

893 if len(args) > 0: 

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

895 TqdmDeprecationWarning( 

896 "Except func, normal arguments are intentionally" + 

897 " not supported by" + 

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

899 " Use keyword arguments instead.", 

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

901 

902 try: # pandas>=1.3.0,<3.0 

903 from pandas.core.common import is_builtin_func 

904 except ImportError: # pandas<1.3.0 

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

906 try: 

907 func = is_builtin_func(func) 

908 except TypeError: 

909 pass 

910 

911 # Define bar updating wrapper 

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

913 # update tbar correctly 

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

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

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

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

918 return func(*args, **kwargs) 

919 

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

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

922 try: 

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

924 finally: 

925 t.close() 

926 

927 return inner 

928 

929 # Monkeypatch pandas to provide easy methods 

930 # Enable custom tqdm progress in pandas! 

931 Series.progress_apply = inner_generator() 

932 SeriesGroupBy.progress_apply = inner_generator() 

933 Series.progress_map = inner_generator('map') 

934 SeriesGroupBy.progress_map = inner_generator('map') 

935 

936 DataFrame.progress_apply = inner_generator() 

937 DataFrameGroupBy.progress_apply = inner_generator() 

938 DataFrame.progress_applymap = inner_generator('applymap') 

939 DataFrame.progress_map = inner_generator('map') 

940 DataFrameGroupBy.progress_map = inner_generator('map') 

941 

942 if Panel is not None: 

943 Panel.progress_apply = inner_generator() 

944 if PanelGroupBy is not None: 

945 PanelGroupBy.progress_apply = inner_generator() 

946 

947 GroupBy.progress_apply = inner_generator() 

948 GroupBy.progress_aggregate = inner_generator('aggregate') 

949 GroupBy.progress_transform = inner_generator('transform') 

950 

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

952 Rolling.progress_apply = inner_generator() 

953 Expanding.progress_apply = inner_generator() 

954 elif _Rolling_and_Expanding is not None: 

955 _Rolling_and_Expanding.progress_apply = inner_generator() 

956 

957 # override defaults via env vars 

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

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

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

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

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

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

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

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

966 **kwargs): 

967 """see tqdm.tqdm for arguments""" 

968 if file is None: 

969 file = sys.stderr 

970 

971 if write_bytes: 

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

973 # should have bytes written to them. 

974 file = SimpleTextIOWrapper( 

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

976 

977 file = DisableOnWriteError(file, tqdm_instance=self) 

978 

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

980 disable = True 

981 

982 if total is None and iterable is not None: 

983 try: 

984 total = len(iterable) 

985 except (TypeError, AttributeError): 

986 total = None 

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

988 total = None # same as unknown 

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 yield from iterable 

1176 return 

1177 

1178 mininterval = self.mininterval 

1179 last_print_t = self.last_print_t 

1180 last_print_n = self.last_print_n 

1181 min_start_t = self.start_t + self.delay 

1182 n = self.n 

1183 time = self._time 

1184 

1185 try: 

1186 for obj in iterable: 

1187 yield obj 

1188 # Update and possibly print the progress bar. 

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

1190 n += 1 

1191 

1192 if n - last_print_n >= self.miniters: 

1193 cur_t = time() 

1194 dt = cur_t - last_print_t 

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

1196 self.update(n - last_print_n) 

1197 last_print_n = self.last_print_n 

1198 last_print_t = self.last_print_t 

1199 finally: 

1200 self.n = n 

1201 self.close() 

1202 

1203 def update(self, n=1): 

1204 """ 

1205 Manually update the progress bar, useful for streams 

1206 such as reading files. 

1207 E.g.: 

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

1209 >>> for current_buffer in stream: 

1210 ... ... 

1211 ... t.update(len(current_buffer)) 

1212 >>> t.close() 

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

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

1215 exactly reached and printed. 

1216 

1217 Parameters 

1218 ---------- 

1219 n : int or float, optional 

1220 Increment to add to the internal counter of iterations 

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

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

1223 

1224 Returns 

1225 ------- 

1226 out : bool or None 

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

1228 """ 

1229 if self.disable: 

1230 return 

1231 

1232 if n < 0: 

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

1234 self.n += n 

1235 

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

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

1238 cur_t = self._time() 

1239 dt = cur_t - self.last_print_t 

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

1241 cur_t = self._time() 

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

1243 if self.smoothing and dt and dn: 

1244 # EMA (not just overall average) 

1245 self._ema_dn(dn) 

1246 self._ema_dt(dt) 

1247 self.refresh(lock_args=self.lock_args) 

1248 if self.dynamic_miniters: 

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

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

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

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

1253 # at least 5 more iterations. 

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

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

1256 elif self.smoothing: 

1257 # EMA miniters update 

1258 self.miniters = self._ema_miniters( 

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

1260 else 1)) 

1261 else: 

1262 # max iters between two prints 

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

1264 

1265 # Store old values for next call 

1266 self.last_print_n = self.n 

1267 self.last_print_t = cur_t 

1268 return True 

1269 

1270 def close(self): 

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

1272 if getattr(self, 'disable', True): 

1273 return 

1274 

1275 # Prevent multiple closures 

1276 self.disable = True 

1277 

1278 # decrement instance pos and remove from internal set 

1279 pos = abs(self.pos) 

1280 self._decr_instances(self) 

1281 

1282 if not hasattr(self, 'last_print_t'): 

1283 return 

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

1285 # haven't ever displayed; nothing to clear 

1286 return 

1287 

1288 # GUI mode 

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

1290 return 

1291 

1292 # annoyingly, _supports_unicode isn't good enough 

1293 def fp_write(s): 

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

1295 

1296 try: 

1297 fp_write('') 

1298 except ValueError as e: 

1299 if 'closed' in str(e): 

1300 return 

1301 raise # pragma: no cover 

1302 

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

1304 

1305 with self._lock: 

1306 if leave: 

1307 # stats for overall rate (no weighted average) 

1308 self._ema_dt = lambda: None 

1309 self.display(pos=0) 

1310 fp_write('\n') 

1311 else: 

1312 # clear previous display 

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

1314 fp_write('\r') 

1315 

1316 def clear(self, nolock=False): 

1317 """Clear current bar display.""" 

1318 if self.disable: 

1319 return 

1320 

1321 if not nolock: 

1322 self._lock.acquire() 

1323 pos = abs(self.pos) 

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

1325 self.moveto(pos) 

1326 self.sp('') 

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

1328 self.moveto(-pos) 

1329 if not nolock: 

1330 self._lock.release() 

1331 

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

1333 """ 

1334 Force refresh the display of this bar. 

1335 

1336 Parameters 

1337 ---------- 

1338 nolock : bool, optional 

1339 If `True`, does not lock. 

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

1341 lock_args : tuple, optional 

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

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

1344 """ 

1345 if self.disable: 

1346 return 

1347 

1348 if not nolock: 

1349 if lock_args: 

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

1351 return False 

1352 else: 

1353 self._lock.acquire() 

1354 self.display() 

1355 if not nolock: 

1356 self._lock.release() 

1357 return True 

1358 

1359 def unpause(self): 

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

1361 if self.disable: 

1362 return 

1363 cur_t = self._time() 

1364 self.start_t += cur_t - self.last_print_t 

1365 self.last_print_t = cur_t 

1366 

1367 def reset(self, total=None): 

1368 """ 

1369 Resets to 0 iterations for repeated use. 

1370 

1371 Consider combining with `leave=True`. 

1372 

1373 Parameters 

1374 ---------- 

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

1376 """ 

1377 self.n = 0 

1378 if total is not None: 

1379 self.total = None if total == float("inf") else total 

1380 if self.disable: 

1381 return 

1382 self.last_print_n = 0 

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

1384 self._ema_dn = EMA(self.smoothing) 

1385 self._ema_dt = EMA(self.smoothing) 

1386 self._ema_miniters = EMA(self.smoothing) 

1387 self.refresh() 

1388 

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

1390 """ 

1391 Set/modify description of the progress bar. 

1392 

1393 Parameters 

1394 ---------- 

1395 desc : str, optional 

1396 refresh : bool, optional 

1397 Forces refresh [default: True]. 

1398 """ 

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

1400 if refresh: 

1401 self.refresh() 

1402 

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

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

1405 self.desc = desc or '' 

1406 if refresh: 

1407 self.refresh() 

1408 

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

1410 """ 

1411 Set/modify postfix (additional stats) 

1412 with automatic formatting based on datatype. 

1413 

1414 Parameters 

1415 ---------- 

1416 ordered_dict : dict or OrderedDict, optional 

1417 refresh : bool, optional 

1418 Forces refresh [default: True]. 

1419 kwargs : dict, optional 

1420 """ 

1421 # Sort in alphabetical order to be more deterministic 

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

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

1424 postfix[key] = kwargs[key] 

1425 # Preprocess stats according to datatype 

1426 for key in postfix.keys(): 

1427 # Number: limit the length of the string 

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

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

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

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

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

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

1434 # Stitch together to get the final postfix 

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

1436 for key in postfix.keys()) 

1437 if refresh: 

1438 self.refresh() 

1439 

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

1441 """ 

1442 Postfix without dictionary expansion, similar to prefix handling. 

1443 """ 

1444 self.postfix = str(s) 

1445 if refresh: 

1446 self.refresh() 

1447 

1448 def moveto(self, n): 

1449 # TODO: private method 

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

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

1452 

1453 @property 

1454 def format_dict(self): 

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

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

1457 return defaultdict(lambda: None, { 

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

1459 if self.dynamic_ncols: 

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

1461 return { 

1462 'n': self.n, 'total': self.total, 

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

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

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

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

1467 'bar_format': self.bar_format, 'postfix': self.postfix, 

1468 'unit_divisor': self.unit_divisor, 'initial': self.initial, 

1469 'colour': self.colour} 

1470 

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

1472 """ 

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

1474 

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

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

1477 

1478 Parameters 

1479 ---------- 

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

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

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

1483 """ 

1484 if pos is None: 

1485 pos = abs(self.pos) 

1486 

1487 nrows = self.nrows or 20 

1488 if pos >= nrows - 1: 

1489 if pos >= nrows: 

1490 return False 

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

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

1493 

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

1495 raise TqdmDeprecationWarning( 

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

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

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

1499 

1500 if pos: 

1501 self.moveto(pos) 

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

1503 if pos: 

1504 self.moveto(-pos) 

1505 return True 

1506 

1507 @classmethod 

1508 @contextmanager 

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

1510 **tqdm_kwargs): 

1511 """ 

1512 stream : file-like object. 

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

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

1515 

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

1517 ... while True: 

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

1519 ... if not chunk: 

1520 ... break 

1521 """ 

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

1523 if bytes: 

1524 t.unit = "B" 

1525 t.unit_scale = True 

1526 t.unit_divisor = 1024 

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

1528 

1529 

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

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

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