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

696 statements  

« prev     ^ index     » next       coverage.py v7.3.1, created at 2023-09-30 06:35 +0000

1""" 

2Customisable progressbar 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 

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, *a, **k): 

46 if fp_write is not None: 

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

48 else: 

49 super(TqdmWarning, self).__init__(msg, *a, **k) 

50 

51 

52class TqdmExperimentalWarning(TqdmWarning, FutureWarning): 

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

54 pass 

55 

56 

57class TqdmDeprecationWarning(TqdmWarning, DeprecationWarning): 

58 # not suppressed if raised 

59 pass 

60 

61 

62class TqdmMonitorWarning(TqdmWarning, RuntimeWarning): 

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

64 pass 

65 

66 

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

68 """threading RLock""" 

69 try: 

70 from threading import RLock 

71 return RLock(*args, **kwargs) 

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

73 pass 

74 

75 

76class TqdmDefaultWriteLock(object): 

77 """ 

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

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

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

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

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

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

84 """ 

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

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

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

88 th_lock = TRLock() 

89 

90 def __init__(self): 

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

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

93 cls = type(self) 

94 root_lock = cls.th_lock 

95 if root_lock is not None: 

96 root_lock.acquire() 

97 cls.create_mp_lock() 

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

99 if root_lock is not None: 

100 root_lock.release() 

101 

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

103 for lock in self.locks: 

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

105 

106 def release(self): 

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

108 lock.release() 

109 

110 def __enter__(self): 

111 self.acquire() 

112 

113 def __exit__(self, *exc): 

114 self.release() 

115 

116 @classmethod 

117 def create_mp_lock(cls): 

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

119 try: 

120 from multiprocessing import RLock 

121 cls.mp_lock = RLock() 

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

123 cls.mp_lock = None 

124 

125 @classmethod 

126 def create_th_lock(cls): 

127 assert hasattr(cls, 'th_lock') 

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

129 

130 

131class Bar(object): 

132 """ 

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

134 

135 - `width` 

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

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

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

139 - `type` 

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

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

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

143 """ 

144 ASCII = " 123456789#" 

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

146 BLANK = " " 

147 COLOUR_RESET = '\x1b[0m' 

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

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

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

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

152 

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

154 if not 0 <= frac <= 1: 

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

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

157 assert default_len > 0 

158 self.frac = frac 

159 self.default_len = default_len 

160 self.charset = charset 

161 self.colour = colour 

162 

163 @property 

164 def colour(self): 

165 return self._colour 

166 

167 @colour.setter 

168 def colour(self, value): 

169 if not value: 

170 self._colour = None 

171 return 

172 try: 

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

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

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

176 self._colour = self.COLOUR_RGB % tuple( 

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

178 else: 

179 raise KeyError 

180 except (KeyError, AttributeError): 

181 warn("Unknown colour (%s); valid choices: [hex (#00ff00), %s]" % ( 

182 value, ", ".join(self.COLOURS)), 

183 TqdmWarning, stacklevel=2) 

184 self._colour = None 

185 

186 def __format__(self, format_spec): 

187 if format_spec: 

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

189 try: 

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

191 except KeyError: 

192 charset = self.charset 

193 else: 

194 format_spec = format_spec[:-1] 

195 if format_spec: 

196 N_BARS = int(format_spec) 

197 if N_BARS < 0: 

198 N_BARS += self.default_len 

199 else: 

200 N_BARS = self.default_len 

201 else: 

202 charset = self.charset 

203 N_BARS = self.default_len 

204 

205 nsyms = len(charset) - 1 

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

207 

208 res = charset[-1] * bar_length 

209 if bar_length < N_BARS: # whitespace padding 

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

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

212 

213 

214class EMA(object): 

215 """ 

216 Exponential moving average: smoothing to give progressively lower 

217 weights to older values. 

218 

219 Parameters 

220 ---------- 

221 smoothing : float, optional 

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

223 Increase to give more weight to recent values. 

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

225 """ 

226 def __init__(self, smoothing=0.3): 

227 self.alpha = smoothing 

228 self.last = 0 

229 self.calls = 0 

230 

231 def __call__(self, x=None): 

232 """ 

233 Parameters 

234 ---------- 

235 x : float 

236 New value to include in EMA. 

237 """ 

238 beta = 1 - self.alpha 

239 if x is not None: 

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

241 self.calls += 1 

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

243 

244 

245class tqdm(Comparable): 

246 """ 

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

248 like the original iterable, but prints a dynamically updating 

249 progressbar every time a value is requested. 

250 

251 Parameters 

252 ---------- 

253 iterable : iterable, optional 

254 Iterable to decorate with a progressbar. 

255 Leave blank to manually manage the updates. 

256 desc : str, optional 

257 Prefix for the progressbar. 

258 total : int or float, optional 

259 The number of expected iterations. If unspecified, 

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

261 resort, only basic progress statistics are displayed 

262 (no ETA, no progressbar). 

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

264 specify an initial arbitrary large positive number, 

265 e.g. 9e9. 

266 leave : bool, optional 

267 If [default: True], keeps all traces of the progressbar 

268 upon termination of iteration. 

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

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

271 Specifies where to output the progress messages 

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

273 methods. For encoding, see `write_bytes`. 

274 ncols : int, optional 

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

276 dynamically resizes the progressbar to stay within this bound. 

277 If unspecified, attempts to use environment width. The 

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

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

280 mininterval : float, optional 

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

282 maxinterval : float, optional 

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

284 Automatically adjusts `miniters` to correspond to `mininterval` 

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

286 or monitor thread is enabled. 

287 miniters : int or float, optional 

288 Minimum progress display update interval, in iterations. 

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

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

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

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

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

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

295 ascii : bool or str, optional 

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

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

298 disable : bool, optional 

299 Whether to disable the entire progressbar wrapper 

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

301 unit : str, optional 

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

303 [default: it]. 

304 unit_scale : bool or int or float, optional 

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

306 automatically and a metric prefix following the 

307 International System of Units standard will be added 

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

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

310 dynamic_ncols : bool, optional 

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

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

313 smoothing : float, optional 

314 Exponential moving average smoothing factor for speed estimates 

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

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

317 bar_format : str, optional 

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

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

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

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

322 '{rate_fmt}{postfix}]' 

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

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

325 rate, rate_fmt, rate_noinv, rate_noinv_fmt, 

326 rate_inv, rate_inv_fmt, postfix, unit_divisor, 

327 remaining, remaining_s, eta. 

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

329 if the latter is empty. 

330 initial : int or float, optional 

331 The initial counter value. Useful when restarting a progress 

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

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

334 position : int, optional 

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

336 Automatic if unspecified. 

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

338 postfix : dict or *, optional 

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

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

341 unit_divisor : float, optional 

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

343 write_bytes : bool, optional 

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

345 lock_args : tuple, optional 

346 Passed to `refresh` for intermediate output 

347 (initialisation, iterating, and updating). 

348 nrows : int, optional 

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

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

351 The fallback is 20. 

352 colour : str, optional 

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

354 delay : float, optional 

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

356 gui : bool, optional 

357 WARNING: internal parameter - do not use. 

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

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

360 

361 Returns 

362 ------- 

363 out : decorated iterator. 

364 """ 

365 

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

367 monitor = None 

368 _instances = WeakSet() 

369 

370 @staticmethod 

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

372 """ 

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

374 prefixes. 

375 

376 Parameters 

377 ---------- 

378 num : float 

379 Number ( >= 1) to format. 

380 suffix : str, optional 

381 Post-postfix [default: '']. 

382 divisor : float, optional 

383 Divisor between prefixes [default: 1000]. 

384 

385 Returns 

386 ------- 

387 out : str 

388 Number with Order of Magnitude SI unit postfix. 

389 """ 

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

391 if abs(num) < 999.5: 

392 if abs(num) < 99.95: 

393 if abs(num) < 9.995: 

394 return '{0:1.2f}'.format(num) + unit + suffix 

395 return '{0:2.1f}'.format(num) + unit + suffix 

396 return '{0:3.0f}'.format(num) + unit + suffix 

397 num /= divisor 

398 return '{0:3.1f}Y'.format(num) + suffix 

399 

400 @staticmethod 

401 def format_interval(t): 

402 """ 

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

404 

405 Parameters 

406 ---------- 

407 t : int 

408 Number of seconds. 

409 

410 Returns 

411 ------- 

412 out : str 

413 [H:]MM:SS 

414 """ 

415 mins, s = divmod(int(t), 60) 

416 h, m = divmod(mins, 60) 

417 if h: 

418 return '{0:d}:{1:02d}:{2:02d}'.format(h, m, s) 

419 else: 

420 return '{0:02d}:{1:02d}'.format(m, s) 

421 

422 @staticmethod 

423 def format_num(n): 

424 """ 

425 Intelligent scientific notation (.3g). 

426 

427 Parameters 

428 ---------- 

429 n : int or float or Numeric 

430 A Number. 

431 

432 Returns 

433 ------- 

434 out : str 

435 Formatted number. 

436 """ 

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

438 n = str(n) 

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

440 

441 @staticmethod 

442 def status_printer(file): 

443 """ 

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

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

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

447 """ 

448 fp = file 

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

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

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

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

453 

454 def fp_write(s): 

455 fp.write(str(s)) 

456 fp_flush() 

457 

458 last_len = [0] 

459 

460 def print_status(s): 

461 len_s = disp_len(s) 

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

463 last_len[0] = len_s 

464 

465 return print_status 

466 

467 @staticmethod 

468 def format_meter(n, total, elapsed, ncols=None, prefix='', ascii=False, unit='it', 

469 unit_scale=False, rate=None, bar_format=None, postfix=None, 

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

471 """ 

472 Return a string-based progress bar given some parameters 

473 

474 Parameters 

475 ---------- 

476 n : int or float 

477 Number of finished iterations. 

478 total : int or float 

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

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

481 elapsed : float 

482 Number of seconds passed since start. 

483 ncols : int, optional 

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

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

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

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

488 prefix : str, optional 

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

490 Use as {desc} in bar_format string. 

491 ascii : bool, optional or str, optional 

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

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

494 " 123456789#". 

495 unit : str, optional 

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

497 unit_scale : bool or int or float, optional 

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

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

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

501 `total` and `n`. 

502 rate : float, optional 

503 Manual override for iteration rate. 

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

505 bar_format : str, optional 

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

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

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

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

510 '{rate_fmt}{postfix}]' 

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

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

513 rate, rate_fmt, rate_noinv, rate_noinv_fmt, 

514 rate_inv, rate_inv_fmt, postfix, unit_divisor, 

515 remaining, remaining_s, eta. 

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

517 if the latter is empty. 

518 postfix : *, optional 

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

520 (e.g. for additional stats). 

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

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

523 However other types are supported (#382). 

524 unit_divisor : float, optional 

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

526 initial : int or float, optional 

527 The initial counter value [default: 0]. 

528 colour : str, optional 

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

530 

531 Returns 

532 ------- 

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

534 """ 

535 

536 # sanity check: total 

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

538 total = None 

539 

540 # apply custom scale if necessary 

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

542 if total: 

543 total *= unit_scale 

544 n *= unit_scale 

545 if rate: 

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

547 unit_scale = False 

548 

549 elapsed_str = tqdm.format_interval(elapsed) 

550 

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

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

553 if rate is None and elapsed: 

554 rate = (n - initial) / elapsed 

555 inv_rate = 1 / rate if rate else None 

556 format_sizeof = tqdm.format_sizeof 

557 rate_noinv_fmt = ((format_sizeof(rate) if unit_scale else 

558 '{0:5.2f}'.format(rate)) if rate else '?') + unit + '/s' 

559 rate_inv_fmt = ( 

560 (format_sizeof(inv_rate) if unit_scale else '{0:5.2f}'.format(inv_rate)) 

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

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

563 

564 if unit_scale: 

565 n_fmt = format_sizeof(n, divisor=unit_divisor) 

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

567 else: 

568 n_fmt = str(n) 

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

570 

571 try: 

572 postfix = ', ' + postfix if postfix else '' 

573 except TypeError: 

574 pass 

575 

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

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

578 try: 

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

580 if rate and total else datetime.utcfromtimestamp(0)) 

581 except OverflowError: 

582 eta_dt = datetime.max 

583 

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

585 if prefix: 

586 # old prefix setup work around 

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

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

589 else: 

590 l_bar = '' 

591 

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

593 

594 # Custom bar formatting 

595 # Populate a dict with all available progress indicators 

596 format_dict = { 

597 # slight extension of self.format_dict 

598 'n': n, 'n_fmt': n_fmt, 'total': total, 'total_fmt': total_fmt, 

599 'elapsed': elapsed_str, 'elapsed_s': elapsed, 

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

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

602 'rate_fmt': rate_fmt, 'rate_noinv': rate, 

603 'rate_noinv_fmt': rate_noinv_fmt, 'rate_inv': inv_rate, 

604 'rate_inv_fmt': rate_inv_fmt, 

605 'postfix': postfix, 'unit_divisor': unit_divisor, 

606 'colour': colour, 

607 # plus more useful definitions 

608 'remaining': remaining_str, 'remaining_s': remaining, 

609 'l_bar': l_bar, 'r_bar': r_bar, 'eta': eta_dt, 

610 **extra_kwargs} 

611 

612 # total is known: we can predict some stats 

613 if total: 

614 # fractional and percentage progress 

615 frac = n / total 

616 percentage = frac * 100 

617 

618 l_bar += '{0:3.0f}%|'.format(percentage) 

619 

620 if ncols == 0: 

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

622 

623 format_dict.update(l_bar=l_bar) 

624 if bar_format: 

625 format_dict.update(percentage=percentage) 

626 

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

628 if not prefix: 

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

630 else: 

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

632 

633 full_bar = FormatReplace() 

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

635 if not full_bar.format_called: 

636 return nobar # no `{bar}`; nothing else to do 

637 

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

639 full_bar = Bar(frac, 

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

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

642 colour=colour) 

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

644 bar_format = str(bar_format) 

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

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

647 

648 elif bar_format: 

649 # user-specified bar_format but no total 

650 l_bar += '|' 

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

652 full_bar = FormatReplace() 

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

654 if not full_bar.format_called: 

655 return nobar 

656 full_bar = Bar(0, 

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

658 charset=Bar.BLANK, colour=colour) 

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

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

661 else: 

662 # no total: no progressbar, ETA, just progress stats 

663 return (f'{(prefix + ": ") if prefix else ""}' 

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

665 

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

667 instance = object.__new__(cls) 

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

669 cls._instances.add(instance) 

670 # create monitoring thread 

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

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

673 try: 

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

675 except Exception as e: # pragma: nocover 

676 warn("tqdm:disabling monitor support" 

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

678 TqdmMonitorWarning, stacklevel=2) 

679 cls.monitor_interval = 0 

680 return instance 

681 

682 @classmethod 

683 def _get_free_pos(cls, instance=None): 

684 """Skips specified instance.""" 

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

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

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

688 

689 @classmethod 

690 def _decr_instances(cls, instance): 

691 """ 

692 Remove from list and reposition another unfixed bar 

693 to fill the new gap. 

694 

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

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

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

698 """ 

699 with cls._lock: 

700 try: 

701 cls._instances.remove(instance) 

702 except KeyError: 

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

704 # raise 

705 pass # py2: maybe magically removed already 

706 # else: 

707 if not instance.gui: 

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

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

710 instances = list(filter( 

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

712 cls._instances)) 

713 # set first found to current `pos` 

714 if instances: 

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

716 inst.clear(nolock=True) 

717 inst.pos = abs(instance.pos) 

718 

719 @classmethod 

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

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

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

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 

737 try: 

738 if not nolock: 

739 cls.get_lock().acquire() 

740 # Clear all bars 

741 inst_cleared = [] 

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

743 # Clear instance if in the target output file 

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

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

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

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

748 inst.clear(nolock=True) 

749 inst_cleared.append(inst) 

750 yield 

751 # Force refresh display of bars we cleared 

752 for inst in inst_cleared: 

753 inst.refresh(nolock=True) 

754 finally: 

755 if not nolock: 

756 cls._lock.release() 

757 

758 @classmethod 

759 def set_lock(cls, lock): 

760 """Set the global lock.""" 

761 cls._lock = lock 

762 

763 @classmethod 

764 def get_lock(cls): 

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

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

767 cls._lock = TqdmDefaultWriteLock() 

768 return cls._lock 

769 

770 @classmethod 

771 def pandas(cls, **tqdm_kwargs): 

772 """ 

773 Registers the current `tqdm` class with 

774 pandas.core. 

775 ( frame.DataFrame 

776 | series.Series 

777 | groupby.(generic.)DataFrameGroupBy 

778 | groupby.(generic.)SeriesGroupBy 

779 ).progress_apply 

780 

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

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

783 

784 Parameters 

785 ---------- 

786 tqdm_kwargs : arguments for the tqdm instance 

787 

788 Examples 

789 -------- 

790 >>> import pandas as pd 

791 >>> import numpy as np 

792 >>> from tqdm import tqdm 

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

794 >>> 

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

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

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

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

799 

800 References 

801 ---------- 

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

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

804 """ 

805 from warnings import catch_warnings, simplefilter 

806 

807 from pandas.core.frame import DataFrame 

808 from pandas.core.series import Series 

809 try: 

810 with catch_warnings(): 

811 simplefilter("ignore", category=FutureWarning) 

812 from pandas import Panel 

813 except ImportError: # pandas>=1.2.0 

814 Panel = None 

815 Rolling, Expanding = None, None 

816 try: # pandas>=1.0.0 

817 from pandas.core.window.rolling import _Rolling_and_Expanding 

818 except ImportError: 

819 try: # pandas>=0.18.0 

820 from pandas.core.window import _Rolling_and_Expanding 

821 except ImportError: # pandas>=1.2.0 

822 try: # pandas>=1.2.0 

823 from pandas.core.window.expanding import Expanding 

824 from pandas.core.window.rolling import Rolling 

825 _Rolling_and_Expanding = Rolling, Expanding 

826 except ImportError: # pragma: no cover 

827 _Rolling_and_Expanding = None 

828 try: # pandas>=0.25.0 

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

830 from pandas.core.groupby.generic import DataFrameGroupBy 

831 except ImportError: # pragma: no cover 

832 try: # pandas>=0.23.0 

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

834 except ImportError: 

835 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy 

836 try: # pandas>=0.23.0 

837 from pandas.core.groupby.groupby import GroupBy 

838 except ImportError: # pragma: no cover 

839 from pandas.core.groupby import GroupBy 

840 

841 try: # pandas>=0.23.0 

842 from pandas.core.groupby.groupby import PanelGroupBy 

843 except ImportError: 

844 try: 

845 from pandas.core.groupby import PanelGroupBy 

846 except ImportError: # pandas>=0.25.0 

847 PanelGroupBy = None 

848 

849 tqdm_kwargs = tqdm_kwargs.copy() 

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

851 

852 def inner_generator(df_function='apply'): 

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

854 """ 

855 Parameters 

856 ---------- 

857 df : (DataFrame|Series)[GroupBy] 

858 Data (may be grouped). 

859 func : function 

860 To be applied on the (grouped) data. 

861 **kwargs : optional 

862 Transmitted to `df.apply()`. 

863 """ 

864 

865 # Precompute total iterations 

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

867 if total is None: # not grouped 

868 if df_function == 'applymap': 

869 total = df.size 

870 elif isinstance(df, Series): 

871 total = len(df) 

872 elif (_Rolling_and_Expanding is None or 

873 not isinstance(df, _Rolling_and_Expanding)): 

874 # DataFrame or Panel 

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

876 if axis == 'index': 

877 axis = 0 

878 elif axis == 'columns': 

879 axis = 1 

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

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

882 

883 # Init bar 

884 if deprecated_t[0] is not None: 

885 t = deprecated_t[0] 

886 deprecated_t[0] = None 

887 else: 

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

889 

890 if len(args) > 0: 

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

892 TqdmDeprecationWarning( 

893 "Except func, normal arguments are intentionally" + 

894 " not supported by" + 

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

896 " Use keyword arguments instead.", 

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

898 

899 try: # pandas>=1.3.0 

900 from pandas.core.common import is_builtin_func 

901 except ImportError: 

902 is_builtin_func = df._is_builtin_func 

903 try: 

904 func = is_builtin_func(func) 

905 except TypeError: 

906 pass 

907 

908 # Define bar updating wrapper 

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

910 # update tbar correctly 

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

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

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

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

915 return func(*args, **kwargs) 

916 

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

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

919 try: 

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

921 finally: 

922 t.close() 

923 

924 return inner 

925 

926 # Monkeypatch pandas to provide easy methods 

927 # Enable custom tqdm progress in pandas! 

928 Series.progress_apply = inner_generator() 

929 SeriesGroupBy.progress_apply = inner_generator() 

930 Series.progress_map = inner_generator('map') 

931 SeriesGroupBy.progress_map = inner_generator('map') 

932 

933 DataFrame.progress_apply = inner_generator() 

934 DataFrameGroupBy.progress_apply = inner_generator() 

935 DataFrame.progress_applymap = inner_generator('applymap') 

936 

937 if Panel is not None: 

938 Panel.progress_apply = inner_generator() 

939 if PanelGroupBy is not None: 

940 PanelGroupBy.progress_apply = inner_generator() 

941 

942 GroupBy.progress_apply = inner_generator() 

943 GroupBy.progress_aggregate = inner_generator('aggregate') 

944 GroupBy.progress_transform = inner_generator('transform') 

945 

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

947 Rolling.progress_apply = inner_generator() 

948 Expanding.progress_apply = inner_generator() 

949 elif _Rolling_and_Expanding is not None: 

950 _Rolling_and_Expanding.progress_apply = inner_generator() 

951 

952 # override defaults via env vars 

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

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

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

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

957 ascii=None, disable=False, unit='it', unit_scale=False, 

958 dynamic_ncols=False, smoothing=0.3, bar_format=None, initial=0, 

959 position=None, postfix=None, unit_divisor=1000, write_bytes=False, 

960 lock_args=None, nrows=None, colour=None, delay=0.0, gui=False, 

961 **kwargs): 

962 """see tqdm.tqdm for arguments""" 

963 if file is None: 

964 file = sys.stderr 

965 

966 if write_bytes: 

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

968 # should have bytes written to them. 

969 file = SimpleTextIOWrapper( 

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

971 

972 file = DisableOnWriteError(file, tqdm_instance=self) 

973 

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

975 disable = True 

976 

977 if total is None and iterable is not None: 

978 try: 

979 total = len(iterable) 

980 except (TypeError, AttributeError): 

981 total = None 

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

983 # Infinite iterations, behave same as unknown 

984 total = None 

985 

986 if disable: 

987 self.iterable = iterable 

988 self.disable = disable 

989 with self._lock: 

990 self.pos = self._get_free_pos(self) 

991 self._instances.remove(self) 

992 self.n = initial 

993 self.total = total 

994 self.leave = leave 

995 return 

996 

997 if kwargs: 

998 self.disable = True 

999 with self._lock: 

1000 self.pos = self._get_free_pos(self) 

1001 self._instances.remove(self) 

1002 raise ( 

1003 TqdmDeprecationWarning( 

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

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

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

1007 if "nested" in kwargs else 

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

1009 

1010 # Preprocess the arguments 

1011 if ( 

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

1013 ) or dynamic_ncols: # pragma: no cover 

1014 if dynamic_ncols: 

1015 dynamic_ncols = _screen_shape_wrapper() 

1016 if dynamic_ncols: 

1017 ncols, nrows = dynamic_ncols(file) 

1018 else: 

1019 _dynamic_ncols = _screen_shape_wrapper() 

1020 if _dynamic_ncols: 

1021 _ncols, _nrows = _dynamic_ncols(file) 

1022 if ncols is None: 

1023 ncols = _ncols 

1024 if nrows is None: 

1025 nrows = _nrows 

1026 

1027 if miniters is None: 

1028 miniters = 0 

1029 dynamic_miniters = True 

1030 else: 

1031 dynamic_miniters = False 

1032 

1033 if mininterval is None: 

1034 mininterval = 0 

1035 

1036 if maxinterval is None: 

1037 maxinterval = 0 

1038 

1039 if ascii is None: 

1040 ascii = not _supports_unicode(file) 

1041 

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

1043 # Convert bar format into unicode since terminal uses unicode 

1044 bar_format = str(bar_format) 

1045 

1046 if smoothing is None: 

1047 smoothing = 0 

1048 

1049 # Store the arguments 

1050 self.iterable = iterable 

1051 self.desc = desc or '' 

1052 self.total = total 

1053 self.leave = leave 

1054 self.fp = file 

1055 self.ncols = ncols 

1056 self.nrows = nrows 

1057 self.mininterval = mininterval 

1058 self.maxinterval = maxinterval 

1059 self.miniters = miniters 

1060 self.dynamic_miniters = dynamic_miniters 

1061 self.ascii = ascii 

1062 self.disable = disable 

1063 self.unit = unit 

1064 self.unit_scale = unit_scale 

1065 self.unit_divisor = unit_divisor 

1066 self.initial = initial 

1067 self.lock_args = lock_args 

1068 self.delay = delay 

1069 self.gui = gui 

1070 self.dynamic_ncols = dynamic_ncols 

1071 self.smoothing = smoothing 

1072 self._ema_dn = EMA(smoothing) 

1073 self._ema_dt = EMA(smoothing) 

1074 self._ema_miniters = EMA(smoothing) 

1075 self.bar_format = bar_format 

1076 self.postfix = None 

1077 self.colour = colour 

1078 self._time = time 

1079 if postfix: 

1080 try: 

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

1082 except TypeError: 

1083 self.postfix = postfix 

1084 

1085 # Init the iterations counters 

1086 self.last_print_n = initial 

1087 self.n = initial 

1088 

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

1090 # not overwrite the outer progress bar 

1091 with self._lock: 

1092 # mark fixed positions as negative 

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

1094 

1095 if not gui: 

1096 # Initialize the screen printer 

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

1098 if delay <= 0: 

1099 self.refresh(lock_args=self.lock_args) 

1100 

1101 # Init the time counter 

1102 self.last_print_t = self._time() 

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

1104 self.start_t = self.last_print_t 

1105 

1106 def __bool__(self): 

1107 if self.total is not None: 

1108 return self.total > 0 

1109 if self.iterable is None: 

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

1111 return bool(self.iterable) 

1112 

1113 def __len__(self): 

1114 return ( 

1115 self.total if self.iterable is None 

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

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

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

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

1120 

1121 def __reversed__(self): 

1122 try: 

1123 orig = self.iterable 

1124 except AttributeError: 

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

1126 else: 

1127 self.iterable = reversed(self.iterable) 

1128 return self.__iter__() 

1129 finally: 

1130 self.iterable = orig 

1131 

1132 def __contains__(self, item): 

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

1134 return contains(item) if contains is not None else item in self.__iter__() 

1135 

1136 def __enter__(self): 

1137 return self 

1138 

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

1140 try: 

1141 self.close() 

1142 except AttributeError: 

1143 # maybe eager thread cleanup upon external error 

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

1145 raise 

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

1147 

1148 def __del__(self): 

1149 self.close() 

1150 

1151 def __str__(self): 

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

1153 

1154 @property 

1155 def _comparable(self): 

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

1157 

1158 def __hash__(self): 

1159 return id(self) 

1160 

1161 def __iter__(self): 

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

1163 

1164 # Inlining instance variables as locals (speed optimisation) 

1165 iterable = self.iterable 

1166 

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

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

1169 if self.disable: 

1170 for obj in iterable: 

1171 yield obj 

1172 return 

1173 

1174 mininterval = self.mininterval 

1175 last_print_t = self.last_print_t 

1176 last_print_n = self.last_print_n 

1177 min_start_t = self.start_t + self.delay 

1178 n = self.n 

1179 time = self._time 

1180 

1181 try: 

1182 for obj in iterable: 

1183 yield obj 

1184 # Update and possibly print the progressbar. 

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

1186 n += 1 

1187 

1188 if n - last_print_n >= self.miniters: 

1189 cur_t = time() 

1190 dt = cur_t - last_print_t 

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

1192 self.update(n - last_print_n) 

1193 last_print_n = self.last_print_n 

1194 last_print_t = self.last_print_t 

1195 finally: 

1196 self.n = n 

1197 self.close() 

1198 

1199 def update(self, n=1): 

1200 """ 

1201 Manually update the progress bar, useful for streams 

1202 such as reading files. 

1203 E.g.: 

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

1205 >>> for current_buffer in stream: 

1206 ... ... 

1207 ... t.update(len(current_buffer)) 

1208 >>> t.close() 

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

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

1211 exactly reached and printed. 

1212 

1213 Parameters 

1214 ---------- 

1215 n : int or float, optional 

1216 Increment to add to the internal counter of iterations 

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

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

1219 

1220 Returns 

1221 ------- 

1222 out : bool or None 

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

1224 """ 

1225 if self.disable: 

1226 return 

1227 

1228 if n < 0: 

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

1230 self.n += n 

1231 

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

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

1234 cur_t = self._time() 

1235 dt = cur_t - self.last_print_t 

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

1237 cur_t = self._time() 

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

1239 if self.smoothing and dt and dn: 

1240 # EMA (not just overall average) 

1241 self._ema_dn(dn) 

1242 self._ema_dt(dt) 

1243 self.refresh(lock_args=self.lock_args) 

1244 if self.dynamic_miniters: 

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

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

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

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

1249 # at least 5 more iterations. 

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

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

1252 elif self.smoothing: 

1253 # EMA miniters update 

1254 self.miniters = self._ema_miniters( 

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

1256 else 1)) 

1257 else: 

1258 # max iters between two prints 

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

1260 

1261 # Store old values for next call 

1262 self.last_print_n = self.n 

1263 self.last_print_t = cur_t 

1264 return True 

1265 

1266 def close(self): 

1267 """Cleanup and (if leave=False) close the progressbar.""" 

1268 if self.disable: 

1269 return 

1270 

1271 # Prevent multiple closures 

1272 self.disable = True 

1273 

1274 # decrement instance pos and remove from internal set 

1275 pos = abs(self.pos) 

1276 self._decr_instances(self) 

1277 

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

1279 # haven't ever displayed; nothing to clear 

1280 return 

1281 

1282 # GUI mode 

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

1284 return 

1285 

1286 # annoyingly, _supports_unicode isn't good enough 

1287 def fp_write(s): 

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

1289 

1290 try: 

1291 fp_write('') 

1292 except ValueError as e: 

1293 if 'closed' in str(e): 

1294 return 

1295 raise # pragma: no cover 

1296 

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

1298 

1299 with self._lock: 

1300 if leave: 

1301 # stats for overall rate (no weighted average) 

1302 self._ema_dt = lambda: None 

1303 self.display(pos=0) 

1304 fp_write('\n') 

1305 else: 

1306 # clear previous display 

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

1308 fp_write('\r') 

1309 

1310 def clear(self, nolock=False): 

1311 """Clear current bar display.""" 

1312 if self.disable: 

1313 return 

1314 

1315 if not nolock: 

1316 self._lock.acquire() 

1317 pos = abs(self.pos) 

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

1319 self.moveto(pos) 

1320 self.sp('') 

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

1322 self.moveto(-pos) 

1323 if not nolock: 

1324 self._lock.release() 

1325 

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

1327 """ 

1328 Force refresh the display of this bar. 

1329 

1330 Parameters 

1331 ---------- 

1332 nolock : bool, optional 

1333 If `True`, does not lock. 

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

1335 lock_args : tuple, optional 

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

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

1338 """ 

1339 if self.disable: 

1340 return 

1341 

1342 if not nolock: 

1343 if lock_args: 

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

1345 return False 

1346 else: 

1347 self._lock.acquire() 

1348 self.display() 

1349 if not nolock: 

1350 self._lock.release() 

1351 return True 

1352 

1353 def unpause(self): 

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

1355 if self.disable: 

1356 return 

1357 cur_t = self._time() 

1358 self.start_t += cur_t - self.last_print_t 

1359 self.last_print_t = cur_t 

1360 

1361 def reset(self, total=None): 

1362 """ 

1363 Resets to 0 iterations for repeated use. 

1364 

1365 Consider combining with `leave=True`. 

1366 

1367 Parameters 

1368 ---------- 

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

1370 """ 

1371 self.n = 0 

1372 if total is not None: 

1373 self.total = total 

1374 if self.disable: 

1375 return 

1376 self.last_print_n = 0 

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

1378 self._ema_dn = EMA(self.smoothing) 

1379 self._ema_dt = EMA(self.smoothing) 

1380 self._ema_miniters = EMA(self.smoothing) 

1381 self.refresh() 

1382 

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

1384 """ 

1385 Set/modify description of the progress bar. 

1386 

1387 Parameters 

1388 ---------- 

1389 desc : str, optional 

1390 refresh : bool, optional 

1391 Forces refresh [default: True]. 

1392 """ 

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

1394 if refresh: 

1395 self.refresh() 

1396 

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

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

1399 self.desc = desc or '' 

1400 if refresh: 

1401 self.refresh() 

1402 

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

1404 """ 

1405 Set/modify postfix (additional stats) 

1406 with automatic formatting based on datatype. 

1407 

1408 Parameters 

1409 ---------- 

1410 ordered_dict : dict or OrderedDict, optional 

1411 refresh : bool, optional 

1412 Forces refresh [default: True]. 

1413 kwargs : dict, optional 

1414 """ 

1415 # Sort in alphabetical order to be more deterministic 

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

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

1418 postfix[key] = kwargs[key] 

1419 # Preprocess stats according to datatype 

1420 for key in postfix.keys(): 

1421 # Number: limit the length of the string 

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

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

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

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

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

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

1428 # Stitch together to get the final postfix 

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

1430 for key in postfix.keys()) 

1431 if refresh: 

1432 self.refresh() 

1433 

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

1435 """ 

1436 Postfix without dictionary expansion, similar to prefix handling. 

1437 """ 

1438 self.postfix = str(s) 

1439 if refresh: 

1440 self.refresh() 

1441 

1442 def moveto(self, n): 

1443 # TODO: private method 

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

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

1446 

1447 @property 

1448 def format_dict(self): 

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

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

1451 return defaultdict(lambda: None, { 

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

1453 if self.dynamic_ncols: 

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

1455 return { 

1456 'n': self.n, 'total': self.total, 

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

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

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

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

1461 'bar_format': self.bar_format, 'postfix': self.postfix, 

1462 'unit_divisor': self.unit_divisor, 'initial': self.initial, 

1463 'colour': self.colour} 

1464 

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

1466 """ 

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

1468 

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

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

1471 

1472 Parameters 

1473 ---------- 

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

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

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

1477 """ 

1478 if pos is None: 

1479 pos = abs(self.pos) 

1480 

1481 nrows = self.nrows or 20 

1482 if pos >= nrows - 1: 

1483 if pos >= nrows: 

1484 return False 

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

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

1487 

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

1489 raise TqdmDeprecationWarning( 

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

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

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

1493 

1494 if pos: 

1495 self.moveto(pos) 

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

1497 if pos: 

1498 self.moveto(-pos) 

1499 return True 

1500 

1501 @classmethod 

1502 @contextmanager 

1503 def wrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs): 

1504 """ 

1505 stream : file-like object. 

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

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

1508 

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

1510 ... while True: 

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

1512 ... if not chunk: 

1513 ... break 

1514 """ 

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

1516 if bytes: 

1517 t.unit = "B" 

1518 t.unit_scale = True 

1519 t.unit_divisor = 1024 

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

1521 

1522 

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

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

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