Source code for easydev.progressbar

# -*- python -*-
# -*- coding: utf-8 -*-
#
#  This file is part of the easydev software
#
#  Copyright (c) 2011-2024
#
#  File author(s): Thomas Cokelaer <cokelaer@gmail.com>
#
#  Distributed under the BSD3 License.
#
#  Website: https://github.com/cokelaer/easydev
#  Documentation: http://easydev-python.readthedocs.io
#
##############################################################################
"""A progress bar copied and adapted from pyMC code (dec 2014)"""

import sys
import time
import uuid

try:
    from IPython import display
    from IPython.core.display import HTML, Javascript

except ImportError:  # pragma: no cover
    pass


__all__ = ["progress_bar", "TextProgressBar", "Progress"]


class ProgressBar(object):
    def __init__(self, iterations, interval=None):
        self.iterations = iterations
        # if no interval provided, set it to 1%
        if interval is None:
            if iterations <= 100:
                interval = 1  # everything % of the data
            else:
                interval = int(iterations / 100)
        self.interval = interval
        self.start = time.time()
        self.last = 0

    def _percentage(self, i):
        if self.iterations != 0:
            return 100 * i / float(self.iterations)
        else:  # pragma: no cover
            # could be 100 ?
            return 100

    def _get_elapsed(self):
        return time.time() - self.start

    elapsed = property(_get_elapsed)


[docs]class TextProgressBar(ProgressBar): """Use :class:`Progress`""" def __init__(self, iterations, printer, width=40, interval=None): self.fill_char = "-" self.width = width self.printer = printer ProgressBar.__init__(self, iterations, interval=interval)
[docs] def animate(self, i, dummy=None): # dummy=None is for back-compatibility if dummy is not None: # pragma: no cover print("second argument in easydev.progress_bar.animate is deprecated. Update your code") # +1 if i starts at 0 and finishes at N-1 if divmod(i, self.interval)[1] != 0 and i != self.iterations: pass else: self.printer(self.progbar(i))
[docs] def progbar(self, i): # +1 if i starts at 0 and finishes at N-1 bar = self.bar(self._percentage(i)) return "[%s] %i of %i complete in %.1f sec" % ( bar, (i), self.iterations, round(self.elapsed, 1), )
[docs] def bar(self, percent): all_full = self.width - 2 num_hashes = int(percent / 100 * all_full) bar = self.fill_char * num_hashes + " " * (all_full - num_hashes) info = "%d%%" % percent loc = (len(bar) - len(info)) // 2 return replace_at(bar, info, loc, loc + len(info))
def replace_at(str, new, start, stop): return str[:start] + new + str[stop:] def consoleprint(s): if sys.platform.lower().startswith("win"): print(s, "\r", end="") else: print("\r", s, end="") sys.stdout.flush() def ipythonprint(s): # pragma no cover print("\r", s, end="") sys.stdout.flush() class IPythonNotebookPB(ProgressBar): # pragma: no cover """Use :class:`Progress`""" def __init__(self, iterations, interval=None): self.divid = str(uuid.uuid4()) self.sec_id = str(uuid.uuid4()) pb = HTML( """ <div style="float: left; border: 1px solid black; width:500px"> <div id="%s" style="background-color:blue; width:0%%">&nbsp;</div> </div> <label id="%s" style="padding-left: 10px;" text = ""/> """ % (self.divid, self.sec_id) ) display(pb) ProgressBar.__init__(self, iterations, interval=interval) def animate(self, i, dummy=None): if dummy is not None: print("second argument in easydev.progress_bar.animate is deprecated. Update your code") # +1 if i starts at 0 and finishes at N-1 if divmod(i, self.interval)[1] != 0 and i != self.iterations: pass else: percentage = self._percentage(i) fraction = percentage display(Javascript("$('div#%s').width('%i%%')" % (self.divid, percentage))) display( Javascript("$('label#%s').text('%i%% in %.1f sec')" % (self.sec_id, fraction, round(self.elapsed, 1))) ) def _run_from_ipython(): try: __IPYTHON__ return True except NameError: return False
[docs]def progress_bar(iters, interval=None): """A progress bar for Python/IPython/IPython notebook :param int iters: number of iterations (steps in the loop) :param interval: number of intervals to use to update the progress bar (20 by default) :: from easydev import progress_bar pb = progress_bar(10) for i in range(1,10): import time time.sleep(0.1) pb.animate(i) """ if _run_from_ipython(): # pragma: no cover from easydev.misc import in_ipynb if in_ipynb() is True: return IPythonNotebookPB(iters, interval=interval) else: return TextProgressBar(iters, printer=ipythonprint, interval=interval) else: return TextProgressBar(iters, printer=consoleprint, interval=interval)
[docs]class Progress(object): """Generic progress bar for python, IPython, IPython notebook :: from easydev import Progress pb = Progress(100, interval=1) pb.animate(10) """ def __init__(self, iters, interval=None): self.pb = progress_bar(iters, interval=interval)
[docs] def animate(self, i): self.pb.animate(i)
def _get_elapsed(self): return self.pb.elapsed elapsed = property(_get_elapsed)