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

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

695 statements  

1""" 

2Customisable progress bar decorator for iterators. 

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

4 

5Usage: 

6>>> from tqdm import trange, tqdm 

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

8... ... 

9""" 

10import sys 

11from collections import OrderedDict, defaultdict 

12from contextlib import contextmanager 

13from datetime import datetime, timedelta, timezone 

14from numbers import Number 

15from time import time 

16from warnings import warn 

17from weakref import WeakSet 

18 

19from ._monitor import TMonitor 

20from .utils import ( 

21 CallbackIOWrapper, Comparable, DisableOnWriteError, FormatReplace, SimpleTextIOWrapper, 

22 _is_ascii, _screen_shape_wrapper, _supports_unicode, _term_move_up, disp_len, disp_trim, 

23 envwrap) 

24 

25__author__ = "https://github.com/tqdm/tqdm#contributions" 

26__all__ = ['tqdm', 'trange', 

27 'TqdmTypeError', 'TqdmKeyError', 'TqdmWarning', 

28 'TqdmExperimentalWarning', 'TqdmDeprecationWarning', 

29 'TqdmMonitorWarning'] 

30 

31 

32class TqdmTypeError(TypeError): 

33 pass 

34 

35 

36class TqdmKeyError(KeyError): 

37 pass 

38 

39 

40class TqdmWarning(Warning): 

41 """base class for all tqdm warnings. 

42 

43 Used for non-external-code-breaking errors, such as garbled printing. 

44 """ 

45 def __init__(self, msg, fp_write=None): # noqa: B042 

46 if fp_write is not None: 

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

48 else: 

49 super().__init__(msg) 

50 

51 

52class TqdmExperimentalWarning(TqdmWarning, FutureWarning): 

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

54 

55 

56class TqdmDeprecationWarning(TqdmWarning, DeprecationWarning): 

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

58 # not suppressed if raised 

59 

60 

61class TqdmMonitorWarning(TqdmWarning, RuntimeWarning): 

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

63 

64 

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

66 """threading RLock""" 

67 try: 

68 from threading import RLock 

69 return RLock(*args, **kwargs) 

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

71 pass 

72 

73 

74class TqdmDefaultWriteLock: 

75 """ 

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

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

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

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

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

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

82 """ 

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

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

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

86 th_lock = TRLock() 

87 

88 def __init__(self): 

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

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

91 cls = type(self) 

92 root_lock = cls.th_lock 

93 if root_lock is not None: 

94 root_lock.acquire() 

95 cls.create_mp_lock() 

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

97 if root_lock is not None: 

98 root_lock.release() 

99 

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

101 for lock in self.locks: 

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

103 

104 def release(self): 

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

106 lock.release() 

107 

108 def __enter__(self): 

109 self.acquire() 

110 

111 def __exit__(self, *exc): 

112 self.release() 

113 

114 @classmethod 

115 def create_mp_lock(cls): 

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

117 try: 

118 from multiprocessing import RLock 

119 cls.mp_lock = RLock() 

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

121 cls.mp_lock = None 

122 

123 @classmethod 

124 def create_th_lock(cls): 

125 assert hasattr(cls, 'th_lock') 

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

127 

128 

129class Bar: 

130 """ 

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

132 

133 - `width` 

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

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

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

137 - `type` 

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

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

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

141 """ 

142 ASCII = " 123456789#" 

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

144 BLANK = " " 

145 COLOUR_RESET = '\x1b[0m' 

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

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

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

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

150 

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

152 if not 0 <= frac <= 1: 

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

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

155 assert default_len > 0 

156 self.frac = frac 

157 self.default_len = default_len 

158 self.charset = charset 

159 self.colour = colour 

160 

161 @property 

162 def colour(self): 

163 return self._colour 

164 

165 @colour.setter 

166 def colour(self, value): 

167 if not value: 

168 self._colour = None 

169 return 

170 try: 

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

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

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

174 self._colour = self.COLOUR_RGB % tuple( 

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

176 else: 

177 raise KeyError 

178 except (KeyError, AttributeError): 

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

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

181 self._colour = None 

182 

183 def __format__(self, format_spec): 

184 if format_spec: 

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

186 try: 

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

188 except KeyError: 

189 charset = self.charset 

190 else: 

191 format_spec = format_spec[:-1] 

192 if format_spec: 

193 N_BARS = int(format_spec) 

194 if N_BARS < 0: 

195 N_BARS += self.default_len 

196 else: 

197 N_BARS = self.default_len 

198 else: 

199 charset = self.charset 

200 N_BARS = self.default_len 

201 

202 nsyms = len(charset) - 1 

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

204 

205 res = charset[-1] * bar_length 

206 if bar_length < N_BARS: # whitespace padding 

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

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

209 

210 

211class EMA: 

212 """ 

213 Exponential moving average: smoothing to give progressively lower 

214 weights to older values. 

215 

216 Parameters 

217 ---------- 

218 smoothing : float, optional 

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

220 Increase to give more weight to recent values. 

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

222 """ 

223 def __init__(self, smoothing=0.3): 

224 self.alpha = smoothing 

225 self.last = 0 

226 self.calls = 0 

227 

228 def __call__(self, x=None): 

229 """ 

230 Parameters 

231 ---------- 

232 x : float 

233 New value to include in EMA. 

234 """ 

235 beta = 1 - self.alpha 

236 if x is not None: 

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

238 self.calls += 1 

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

240 

241 

242class tqdm(Comparable): 

243 """ 

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

245 like the original iterable, but prints a dynamically updating 

246 progress bar every time a value is requested. 

247 

248 Parameters 

249 ---------- 

250 iterable : iterable, optional 

251 Iterable to decorate with a progress bar. 

252 Leave blank to manually manage the updates. 

253 desc : str, optional 

254 Prefix for the progress bar. 

255 total : int or float, optional 

256 The number of expected iterations. If unspecified, 

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

258 resort, only basic progress statistics are displayed 

259 (no ETA, no progress bar). 

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

261 specify an initial arbitrary large positive number, 

262 e.g. 9e9. 

263 leave : bool, optional 

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

265 upon termination of iteration. 

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

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

268 Specifies where to output the progress messages 

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

270 methods. For encoding, see `write_bytes`. 

271 ncols : int, optional 

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

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

274 If unspecified, attempts to use environment width. The 

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

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

277 mininterval : float, optional 

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

279 maxinterval : float, optional 

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

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

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

283 or monitor thread is enabled. 

284 miniters : int or float, optional 

285 Minimum progress display update interval, in iterations. 

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

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

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

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

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

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

292 ascii : bool or str, optional 

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

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

295 disable : bool, optional 

296 Whether to disable the entire progress bar wrapper 

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

298 unit : str, optional 

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

300 [default: it]. 

301 unit_scale : bool or int or float, optional 

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

303 automatically and a metric prefix following the 

304 International System of Units standard will be added 

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

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

307 dynamic_ncols : bool, optional 

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

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

310 smoothing : float, optional 

311 Exponential moving average smoothing factor for speed estimates 

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

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

314 bar_format : str, optional 

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

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

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

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

319 '{rate_fmt}{postfix}]' 

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

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

322 rate, rate_fmt, rate_noinv, rate_noinv_fmt, 

323 rate_inv, rate_inv_fmt, postfix, unit_divisor, 

324 remaining, remaining_s, eta. 

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

326 if the latter is empty. 

327 initial : int or float, optional 

328 The initial counter value. Useful when restarting a progress 

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

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

331 position : int, optional 

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

333 Automatic if unspecified. 

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

335 postfix : dict or *, optional 

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

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

338 unit_divisor : float, optional 

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

340 write_bytes : bool, optional 

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

342 lock_args : tuple, optional 

343 Passed to `refresh` for intermediate output 

344 (initialisation, iterating, and updating). 

345 nrows : int, optional 

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

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

348 The fallback is 20. 

349 colour : str, optional 

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

351 delay : float, optional 

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

353 gui : bool, optional 

354 WARNING: internal parameter - do not use. 

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

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

357 

358 Returns 

359 ------- 

360 out : decorated iterator. 

361 """ 

362 

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

364 monitor = None 

365 _instances = WeakSet() 

366 

367 @staticmethod 

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

369 """ 

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

371 prefixes. 

372 

373 Parameters 

374 ---------- 

375 num : float 

376 Number ( >= 1) to format. 

377 suffix : str, optional 

378 Post-postfix [default: '']. 

379 divisor : float, optional 

380 Divisor between prefixes [default: 1000]. 

381 

382 Returns 

383 ------- 

384 out : str 

385 Number with Order of Magnitude SI unit postfix. 

386 """ 

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

388 if abs(num) < 999.5: 

389 if abs(num) < 99.95: 

390 if abs(num) < 9.995: 

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

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

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

394 num /= divisor 

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

396 

397 @staticmethod 

398 def format_interval(t): 

399 """ 

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

401 

402 Parameters 

403 ---------- 

404 t : int 

405 Number of seconds. 

406 

407 Returns 

408 ------- 

409 out : str 

410 [H:]MM:SS 

411 """ 

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

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

414 h, m = divmod(mins, 60) 

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

416 

417 @staticmethod 

418 def format_num(n): 

419 """ 

420 Intelligent scientific notation (.3g). 

421 

422 Parameters 

423 ---------- 

424 n : int or float or Numeric 

425 A Number. 

426 

427 Returns 

428 ------- 

429 out : str 

430 Formatted number. 

431 """ 

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

433 n = str(n) 

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

435 

436 @staticmethod 

437 def status_printer(file): 

438 """ 

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

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

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

442 """ 

443 fp = file 

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

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

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

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

448 

449 def fp_write(s): 

450 fp.write(str(s)) 

451 fp_flush() 

452 

453 last_len = [0] 

454 

455 def print_status(s): 

456 len_s = disp_len(s) 

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

458 last_len[0] = len_s 

459 

460 return print_status 

461 

462 @staticmethod 

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

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

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

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

467 """ 

468 Return a string-based progress bar given some parameters 

469 

470 Parameters 

471 ---------- 

472 n : int or float 

473 Number of finished iterations. 

474 total : int or float 

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

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

477 elapsed : float 

478 Number of seconds passed since start. 

479 ncols : int, optional 

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

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

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

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

484 prefix : str, optional 

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

486 Use as {desc} in bar_format string. 

487 ascii : bool, optional or str, optional 

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

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

490 " 123456789#". 

491 unit : str, optional 

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

493 unit_scale : bool or int or float, optional 

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

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

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

497 `total` and `n`. 

498 rate : float, optional 

499 Manual override for iteration rate. 

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

501 bar_format : str, optional 

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

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

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

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

506 '{rate_fmt}{postfix}]' 

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

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

509 rate, rate_fmt, rate_noinv, rate_noinv_fmt, 

510 rate_inv, rate_inv_fmt, postfix, unit_divisor, 

511 remaining, remaining_s, eta. 

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

513 if the latter is empty. 

514 postfix : *, optional 

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

516 (e.g. for additional stats). 

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

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

519 However other types are supported (#382). 

520 unit_divisor : float, optional 

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

522 initial : int or float, optional 

523 The initial counter value [default: 0]. 

524 colour : str, optional 

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

526 

527 Returns 

528 ------- 

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

530 """ 

531 

532 # sanity check: total 

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

534 total = None 

535 

536 # apply custom scale if necessary 

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

538 if total: 

539 total *= unit_scale 

540 n *= unit_scale 

541 if rate: 

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

543 unit_scale = False 

544 

545 elapsed_str = tqdm.format_interval(elapsed) 

546 

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

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

549 if rate is None and elapsed: 

550 rate = (n - initial) / elapsed 

551 inv_rate = 1 / rate if rate else None 

552 format_sizeof = tqdm.format_sizeof 

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

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

555 rate_inv_fmt = ( 

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

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

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

559 

560 if unit_scale: 

561 n_fmt = format_sizeof(n, divisor=unit_divisor) 

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

563 else: 

564 n_fmt = str(n) 

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

566 

567 try: 

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

569 except TypeError: 

570 pass 

571 

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

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

574 try: 

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

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

577 except OverflowError: 

578 eta_dt = datetime.max 

579 

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

581 if prefix: 

582 # old prefix setup work around 

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

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

585 else: 

586 l_bar = '' 

587 

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

589 

590 # Custom bar formatting 

591 # Populate a dict with all available progress indicators 

592 format_dict = { 

593 # slight extension of self.format_dict 

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

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

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

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

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

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

600 'rate_inv_fmt': rate_inv_fmt, 

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

602 'colour': colour, 

603 # plus more useful definitions 

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

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

606 **extra_kwargs} 

607 

608 # total is known: we can predict some stats 

609 if total: 

610 # fractional and percentage progress 

611 frac = n / total 

612 percentage = frac * 100 

613 

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

615 

616 if ncols == 0: 

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

618 

619 format_dict.update(l_bar=l_bar) 

620 if bar_format: 

621 format_dict.update(percentage=percentage) 

622 

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

624 if not prefix: 

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

626 else: 

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

628 

629 full_bar = FormatReplace() 

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

631 if not full_bar.format_called: 

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

633 

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

635 full_bar = Bar(frac, 

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

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

638 colour=colour) 

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

640 bar_format = str(bar_format) 

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

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

643 

644 elif bar_format: 

645 # user-specified bar_format but no total 

646 l_bar += '|' 

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

648 full_bar = FormatReplace() 

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

650 if not full_bar.format_called: 

651 return nobar 

652 full_bar = Bar(0, 

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

654 charset=Bar.BLANK, colour=colour) 

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

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

657 else: 

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

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

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

661 

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

663 instance = object.__new__(cls) 

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

665 cls._instances.add(instance) 

666 # create monitoring thread 

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

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

669 try: 

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

671 except Exception as e: # pragma: nocover 

672 warn("tqdm:disabling monitor support" 

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

674 TqdmMonitorWarning, stacklevel=2) 

675 cls.monitor_interval = 0 

676 return instance 

677 

678 @classmethod 

679 def _get_free_pos(cls, instance=None): 

680 """Skips specified instance.""" 

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

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

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

684 

685 @classmethod 

686 def _decr_instances(cls, instance): 

687 """ 

688 Remove from list and reposition another unfixed bar 

689 to fill the new gap. 

690 

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

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

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

694 """ 

695 with cls._lock: 

696 try: 

697 cls._instances.remove(instance) 

698 except KeyError: 

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

700 # raise 

701 pass # py2: maybe magically removed already 

702 # else: 

703 if not instance.gui: 

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

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

706 instances = list(filter( 

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

708 cls._instances)) 

709 # set first found to current `pos` 

710 if instances: 

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

712 inst.clear(nolock=True) 

713 inst.pos = abs(instance.pos) 

714 

715 @classmethod 

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

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

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

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

720 # Write the message 

721 fp.write(s) 

722 fp.write(end) 

723 

724 @classmethod 

725 @contextmanager 

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

727 """ 

728 Disable tqdm within context and refresh tqdm when exits. 

729 Useful when writing to standard output stream 

730 """ 

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

732 

733 try: 

734 if not nolock: 

735 cls.get_lock().acquire() 

736 # Clear all bars 

737 inst_cleared = [] 

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

739 # Clear instance if in the target output file 

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

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

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

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

744 inst.clear(nolock=True) 

745 inst_cleared.append(inst) 

746 yield 

747 # Force refresh display of bars we cleared 

748 for inst in inst_cleared: 

749 inst.refresh(nolock=True) 

750 finally: 

751 if not nolock: 

752 cls._lock.release() 

753 

754 @classmethod 

755 def set_lock(cls, lock): 

756 """Set the global lock.""" 

757 cls._lock = lock 

758 

759 @classmethod 

760 def get_lock(cls): 

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

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

763 cls._lock = TqdmDefaultWriteLock() 

764 return cls._lock 

765 

766 @classmethod 

767 def pandas(cls, **tqdm_kwargs): 

768 """ 

769 Registers the current `tqdm` class with 

770 pandas.core. 

771 ( frame.DataFrame 

772 | series.Series 

773 | groupby.(generic.)DataFrameGroupBy 

774 | groupby.(generic.)SeriesGroupBy 

775 ).progress_apply 

776 

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

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

779 

780 Parameters 

781 ---------- 

782 tqdm_kwargs : arguments for the tqdm instance 

783 

784 Examples 

785 -------- 

786 >>> import pandas as pd 

787 >>> import numpy as np 

788 >>> from tqdm import tqdm 

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

790 >>> 

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

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

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

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

795 

796 References 

797 ---------- 

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

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

800 """ 

801 from warnings import catch_warnings, simplefilter 

802 

803 from pandas.core.frame import DataFrame 

804 from pandas.core.series import Series 

805 try: 

806 with catch_warnings(): 

807 simplefilter("ignore", category=FutureWarning) 

808 from pandas import Panel 

809 except ImportError: # pandas>=1.2.0 

810 Panel = None 

811 Rolling, Expanding = None, None 

812 try: # pandas>=1.0.0 

813 from pandas.core.window.rolling import _Rolling_and_Expanding 

814 except ImportError: 

815 try: # pandas>=0.18.0 

816 from pandas.core.window import _Rolling_and_Expanding 

817 except ImportError: # pandas>=1.2.0 

818 try: # pandas>=1.2.0 

819 from pandas.core.window.expanding import Expanding 

820 from pandas.core.window.rolling import Rolling 

821 _Rolling_and_Expanding = Rolling, Expanding 

822 except ImportError: # pragma: no cover 

823 _Rolling_and_Expanding = None 

824 try: # pandas>=0.25.0 

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

826 from pandas.core.groupby.generic import DataFrameGroupBy 

827 except ImportError: # pragma: no cover 

828 try: # pandas>=0.23.0 

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

830 except ImportError: 

831 from pandas.core.groupby import DataFrameGroupBy, SeriesGroupBy 

832 try: # pandas>=0.23.0 

833 from pandas.core.groupby.groupby import GroupBy 

834 except ImportError: # pragma: no cover 

835 from pandas.core.groupby import GroupBy 

836 

837 try: # pandas>=0.23.0 

838 from pandas.core.groupby.groupby import PanelGroupBy 

839 except ImportError: 

840 try: 

841 from pandas.core.groupby import PanelGroupBy 

842 except ImportError: # pandas>=0.25.0 

843 PanelGroupBy = None 

844 

845 tqdm_kwargs = tqdm_kwargs.copy() 

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

847 

848 def inner_generator(df_function='apply'): 

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

850 """ 

851 Parameters 

852 ---------- 

853 df : (DataFrame|Series)[GroupBy] 

854 Data (may be grouped). 

855 func : function 

856 To be applied on the (grouped) data. 

857 **kwargs : optional 

858 Transmitted to `df.apply()`. 

859 """ 

860 

861 # Precompute total iterations 

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

863 if total is None: # not grouped 

864 if df_function == 'applymap': 

865 total = df.size 

866 elif isinstance(df, Series): 

867 total = len(df) 

868 elif (_Rolling_and_Expanding is None or 

869 not isinstance(df, _Rolling_and_Expanding)): 

870 # DataFrame or Panel 

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

872 if axis == 'index': 

873 axis = 0 

874 elif axis == 'columns': 

875 axis = 1 

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

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

878 

879 # Init bar 

880 if deprecated_t[0] is not None: 

881 t = deprecated_t[0] 

882 deprecated_t[0] = None 

883 else: 

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

885 

886 if len(args) > 0: 

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

888 TqdmDeprecationWarning( 

889 "Except func, normal arguments are intentionally" + 

890 " not supported by" + 

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

892 " Use keyword arguments instead.", 

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

894 

895 try: # pandas>=1.3.0,<3.0 

896 from pandas.core.common import is_builtin_func 

897 except ImportError: # pandas<1.3.0 

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

899 try: 

900 func = is_builtin_func(func) 

901 except TypeError: 

902 pass 

903 

904 # Define bar updating wrapper 

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

906 # update tbar correctly 

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

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

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

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

911 return func(*args, **kwargs) 

912 

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

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

915 try: 

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

917 finally: 

918 t.close() 

919 

920 return inner 

921 

922 # Monkeypatch pandas to provide easy methods 

923 # Enable custom tqdm progress in pandas! 

924 Series.progress_apply = inner_generator() 

925 SeriesGroupBy.progress_apply = inner_generator() 

926 Series.progress_map = inner_generator('map') 

927 SeriesGroupBy.progress_map = inner_generator('map') 

928 

929 DataFrame.progress_apply = inner_generator() 

930 DataFrameGroupBy.progress_apply = inner_generator() 

931 DataFrame.progress_applymap = inner_generator('applymap') 

932 DataFrame.progress_map = inner_generator('map') 

933 DataFrameGroupBy.progress_map = inner_generator('map') 

934 

935 if Panel is not None: 

936 Panel.progress_apply = inner_generator() 

937 if PanelGroupBy is not None: 

938 PanelGroupBy.progress_apply = inner_generator() 

939 

940 GroupBy.progress_apply = inner_generator() 

941 GroupBy.progress_aggregate = inner_generator('aggregate') 

942 GroupBy.progress_transform = inner_generator('transform') 

943 

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

945 Rolling.progress_apply = inner_generator() 

946 Expanding.progress_apply = inner_generator() 

947 elif _Rolling_and_Expanding is not None: 

948 _Rolling_and_Expanding.progress_apply = inner_generator() 

949 

950 # override defaults via env vars 

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

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

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

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

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

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

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

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

959 **kwargs): 

960 """see tqdm.tqdm for arguments""" 

961 if file is None: 

962 file = sys.stderr 

963 

964 if write_bytes: 

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

966 # should have bytes written to them. 

967 file = SimpleTextIOWrapper( 

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

969 

970 file = DisableOnWriteError(file, tqdm_instance=self) 

971 

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

973 disable = True 

974 

975 if total is None and iterable is not None: 

976 try: 

977 total = len(iterable) 

978 except (TypeError, AttributeError): 

979 total = None 

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

981 # Infinite iterations, behave same as unknown 

982 total = None 

983 

984 if disable: 

985 self.iterable = iterable 

986 self.disable = disable 

987 with self._lock: 

988 self.pos = self._get_free_pos(self) 

989 self._instances.remove(self) 

990 self.n = initial 

991 self.total = total 

992 self.leave = leave 

993 return 

994 

995 if kwargs: 

996 self.disable = True 

997 with self._lock: 

998 self.pos = self._get_free_pos(self) 

999 self._instances.remove(self) 

1000 raise ( 

1001 TqdmDeprecationWarning( 

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

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

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

1005 if "nested" in kwargs else 

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

1007 

1008 # Preprocess the arguments 

1009 if ( 

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

1011 ) or dynamic_ncols: # pragma: no cover 

1012 if dynamic_ncols: 

1013 dynamic_ncols = _screen_shape_wrapper() 

1014 if dynamic_ncols: 

1015 ncols, nrows = dynamic_ncols(file) 

1016 else: 

1017 _dynamic_ncols = _screen_shape_wrapper() 

1018 if _dynamic_ncols: 

1019 _ncols, _nrows = _dynamic_ncols(file) 

1020 if ncols is None: 

1021 ncols = _ncols 

1022 if nrows is None: 

1023 nrows = _nrows 

1024 

1025 if miniters is None: 

1026 miniters = 0 

1027 dynamic_miniters = True 

1028 else: 

1029 dynamic_miniters = False 

1030 

1031 if mininterval is None: 

1032 mininterval = 0 

1033 

1034 if maxinterval is None: 

1035 maxinterval = 0 

1036 

1037 if ascii is None: 

1038 ascii = not _supports_unicode(file) 

1039 

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

1041 # Convert bar format into unicode since terminal uses unicode 

1042 bar_format = str(bar_format) 

1043 

1044 if smoothing is None: 

1045 smoothing = 0 

1046 

1047 # Store the arguments 

1048 self.iterable = iterable 

1049 self.desc = desc or '' 

1050 self.total = total 

1051 self.leave = leave 

1052 self.fp = file 

1053 self.ncols = ncols 

1054 self.nrows = nrows 

1055 self.mininterval = mininterval 

1056 self.maxinterval = maxinterval 

1057 self.miniters = miniters 

1058 self.dynamic_miniters = dynamic_miniters 

1059 self.ascii = ascii 

1060 self.disable = disable 

1061 self.unit = unit 

1062 self.unit_scale = unit_scale 

1063 self.unit_divisor = unit_divisor 

1064 self.initial = initial 

1065 self.lock_args = lock_args 

1066 self.delay = delay 

1067 self.gui = gui 

1068 self.dynamic_ncols = dynamic_ncols 

1069 self.smoothing = smoothing 

1070 self._ema_dn = EMA(smoothing) 

1071 self._ema_dt = EMA(smoothing) 

1072 self._ema_miniters = EMA(smoothing) 

1073 self.bar_format = bar_format 

1074 self.postfix = None 

1075 self.colour = colour 

1076 self._time = time 

1077 if postfix: 

1078 try: 

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

1080 except TypeError: 

1081 self.postfix = postfix 

1082 

1083 # Init the iterations counters 

1084 self.last_print_n = initial 

1085 self.n = initial 

1086 

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

1088 # not overwrite the outer progress bar 

1089 with self._lock: 

1090 # mark fixed positions as negative 

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

1092 

1093 if not gui: 

1094 # Initialize the screen printer 

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

1096 if delay <= 0: 

1097 self.refresh(lock_args=self.lock_args) 

1098 

1099 # Init the time counter 

1100 self.last_print_t = self._time() 

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

1102 self.start_t = self.last_print_t 

1103 

1104 def __bool__(self): 

1105 if self.total is not None: 

1106 return self.total > 0 

1107 if self.iterable is None: 

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

1109 return bool(self.iterable) 

1110 

1111 def __len__(self): 

1112 return ( 

1113 self.total if self.iterable is None 

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

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

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

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

1118 

1119 def __reversed__(self): 

1120 try: 

1121 orig = self.iterable 

1122 except AttributeError: 

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

1124 else: 

1125 self.iterable = reversed(self.iterable) 

1126 return self.__iter__() 

1127 finally: 

1128 self.iterable = orig 

1129 

1130 def __contains__(self, item): 

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

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

1133 else item in self.__iter__()) 

1134 

1135 def __enter__(self): 

1136 return self 

1137 

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

1139 try: 

1140 self.close() 

1141 except AttributeError: 

1142 # maybe eager thread cleanup upon external error 

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

1144 raise 

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

1146 

1147 def __del__(self): 

1148 self.close() 

1149 

1150 def __str__(self): 

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

1152 

1153 @property 

1154 def _comparable(self): 

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

1156 

1157 def __hash__(self): 

1158 return id(self) 

1159 

1160 def __iter__(self): 

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

1162 

1163 # Inlining instance variables as locals (speed optimisation) 

1164 iterable = self.iterable 

1165 

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

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

1168 if self.disable: 

1169 for obj in iterable: 

1170 yield obj 

1171 return 

1172 

1173 mininterval = self.mininterval 

1174 last_print_t = self.last_print_t 

1175 last_print_n = self.last_print_n 

1176 min_start_t = self.start_t + self.delay 

1177 n = self.n 

1178 time = self._time 

1179 

1180 try: 

1181 for obj in iterable: 

1182 yield obj 

1183 # Update and possibly print the progress bar. 

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

1185 n += 1 

1186 

1187 if n - last_print_n >= self.miniters: 

1188 cur_t = time() 

1189 dt = cur_t - last_print_t 

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

1191 self.update(n - last_print_n) 

1192 last_print_n = self.last_print_n 

1193 last_print_t = self.last_print_t 

1194 finally: 

1195 self.n = n 

1196 self.close() 

1197 

1198 def update(self, n=1): 

1199 """ 

1200 Manually update the progress bar, useful for streams 

1201 such as reading files. 

1202 E.g.: 

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

1204 >>> for current_buffer in stream: 

1205 ... ... 

1206 ... t.update(len(current_buffer)) 

1207 >>> t.close() 

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

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

1210 exactly reached and printed. 

1211 

1212 Parameters 

1213 ---------- 

1214 n : int or float, optional 

1215 Increment to add to the internal counter of iterations 

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

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

1218 

1219 Returns 

1220 ------- 

1221 out : bool or None 

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

1223 """ 

1224 if self.disable: 

1225 return 

1226 

1227 if n < 0: 

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

1229 self.n += n 

1230 

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

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

1233 cur_t = self._time() 

1234 dt = cur_t - self.last_print_t 

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

1236 cur_t = self._time() 

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

1238 if self.smoothing and dt and dn: 

1239 # EMA (not just overall average) 

1240 self._ema_dn(dn) 

1241 self._ema_dt(dt) 

1242 self.refresh(lock_args=self.lock_args) 

1243 if self.dynamic_miniters: 

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

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

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

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

1248 # at least 5 more iterations. 

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

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

1251 elif self.smoothing: 

1252 # EMA miniters update 

1253 self.miniters = self._ema_miniters( 

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

1255 else 1)) 

1256 else: 

1257 # max iters between two prints 

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

1259 

1260 # Store old values for next call 

1261 self.last_print_n = self.n 

1262 self.last_print_t = cur_t 

1263 return True 

1264 

1265 def close(self): 

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

1267 if self.disable: 

1268 return 

1269 

1270 # Prevent multiple closures 

1271 self.disable = True 

1272 

1273 # decrement instance pos and remove from internal set 

1274 pos = abs(self.pos) 

1275 self._decr_instances(self) 

1276 

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

1278 # haven't ever displayed; nothing to clear 

1279 return 

1280 

1281 # GUI mode 

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

1283 return 

1284 

1285 # annoyingly, _supports_unicode isn't good enough 

1286 def fp_write(s): 

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

1288 

1289 try: 

1290 fp_write('') 

1291 except ValueError as e: 

1292 if 'closed' in str(e): 

1293 return 

1294 raise # pragma: no cover 

1295 

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

1297 

1298 with self._lock: 

1299 if leave: 

1300 # stats for overall rate (no weighted average) 

1301 self._ema_dt = lambda: None 

1302 self.display(pos=0) 

1303 fp_write('\n') 

1304 else: 

1305 # clear previous display 

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

1307 fp_write('\r') 

1308 

1309 def clear(self, nolock=False): 

1310 """Clear current bar display.""" 

1311 if self.disable: 

1312 return 

1313 

1314 if not nolock: 

1315 self._lock.acquire() 

1316 pos = abs(self.pos) 

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

1318 self.moveto(pos) 

1319 self.sp('') 

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

1321 self.moveto(-pos) 

1322 if not nolock: 

1323 self._lock.release() 

1324 

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

1326 """ 

1327 Force refresh the display of this bar. 

1328 

1329 Parameters 

1330 ---------- 

1331 nolock : bool, optional 

1332 If `True`, does not lock. 

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

1334 lock_args : tuple, optional 

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

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

1337 """ 

1338 if self.disable: 

1339 return 

1340 

1341 if not nolock: 

1342 if lock_args: 

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

1344 return False 

1345 else: 

1346 self._lock.acquire() 

1347 self.display() 

1348 if not nolock: 

1349 self._lock.release() 

1350 return True 

1351 

1352 def unpause(self): 

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

1354 if self.disable: 

1355 return 

1356 cur_t = self._time() 

1357 self.start_t += cur_t - self.last_print_t 

1358 self.last_print_t = cur_t 

1359 

1360 def reset(self, total=None): 

1361 """ 

1362 Resets to 0 iterations for repeated use. 

1363 

1364 Consider combining with `leave=True`. 

1365 

1366 Parameters 

1367 ---------- 

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

1369 """ 

1370 self.n = 0 

1371 if total is not None: 

1372 self.total = total 

1373 if self.disable: 

1374 return 

1375 self.last_print_n = 0 

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

1377 self._ema_dn = EMA(self.smoothing) 

1378 self._ema_dt = EMA(self.smoothing) 

1379 self._ema_miniters = EMA(self.smoothing) 

1380 self.refresh() 

1381 

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

1383 """ 

1384 Set/modify description of the progress bar. 

1385 

1386 Parameters 

1387 ---------- 

1388 desc : str, optional 

1389 refresh : bool, optional 

1390 Forces refresh [default: True]. 

1391 """ 

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

1393 if refresh: 

1394 self.refresh() 

1395 

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

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

1398 self.desc = desc or '' 

1399 if refresh: 

1400 self.refresh() 

1401 

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

1403 """ 

1404 Set/modify postfix (additional stats) 

1405 with automatic formatting based on datatype. 

1406 

1407 Parameters 

1408 ---------- 

1409 ordered_dict : dict or OrderedDict, optional 

1410 refresh : bool, optional 

1411 Forces refresh [default: True]. 

1412 kwargs : dict, optional 

1413 """ 

1414 # Sort in alphabetical order to be more deterministic 

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

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

1417 postfix[key] = kwargs[key] 

1418 # Preprocess stats according to datatype 

1419 for key in postfix.keys(): 

1420 # Number: limit the length of the string 

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

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

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

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

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

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

1427 # Stitch together to get the final postfix 

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

1429 for key in postfix.keys()) 

1430 if refresh: 

1431 self.refresh() 

1432 

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

1434 """ 

1435 Postfix without dictionary expansion, similar to prefix handling. 

1436 """ 

1437 self.postfix = str(s) 

1438 if refresh: 

1439 self.refresh() 

1440 

1441 def moveto(self, n): 

1442 # TODO: private method 

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

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

1445 

1446 @property 

1447 def format_dict(self): 

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

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

1450 return defaultdict(lambda: None, { 

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

1452 if self.dynamic_ncols: 

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

1454 return { 

1455 'n': self.n, 'total': self.total, 

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

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

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

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

1460 'bar_format': self.bar_format, 'postfix': self.postfix, 

1461 'unit_divisor': self.unit_divisor, 'initial': self.initial, 

1462 'colour': self.colour} 

1463 

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

1465 """ 

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

1467 

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

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

1470 

1471 Parameters 

1472 ---------- 

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

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

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

1476 """ 

1477 if pos is None: 

1478 pos = abs(self.pos) 

1479 

1480 nrows = self.nrows or 20 

1481 if pos >= nrows - 1: 

1482 if pos >= nrows: 

1483 return False 

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

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

1486 

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

1488 raise TqdmDeprecationWarning( 

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

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

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

1492 

1493 if pos: 

1494 self.moveto(pos) 

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

1496 if pos: 

1497 self.moveto(-pos) 

1498 return True 

1499 

1500 @classmethod 

1501 @contextmanager 

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

1503 **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)