218 lines
5.9 KiB
Python
Raw Normal View History

2021-10-25 20:04:55 +01:00
# -*- python -*-
# -*- coding: utf-8 -*-
#
# This file is part of the easydev software
#
# Copyright (c) 2011-2017
#
# File author(s): Thomas Cokelaer <cokelaer@gmail.com>
#
# Distributed under the GPLv3 License.
# See accompanying file LICENSE.txt or copy at
# http://www.gnu.org/licenses/gpl-3.0.html
#
# Website: https://github.com/cokelaer/easydev
# Documentation: http://easydev-python.readthedocs.io
#
##############################################################################
"""A progress bar copied and adapted from pyMC code (dec 2014)"""
from __future__ import print_function
import sys
import time
import uuid
try:
from IPython.core.display import HTML, Javascript, display
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)
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)
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))
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),
)
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
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)
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)
def animate(self, i):
self.pb.animate(i)
def _get_elapsed(self):
return self.pb.elapsed
elapsed = property(_get_elapsed)