218 lines
5.9 KiB
Python
218 lines
5.9 KiB
Python
|
# -*- 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%%"> </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)
|