mirror of
https://github.com/vale981/jobmanager
synced 2025-03-06 02:11:39 -05:00
new progress decorator, 1) (de)activate with kwargs in function call 2) gives access to the progressBar instance -> allows for stop to do clean printing -- and tests for that
This commit is contained in:
parent
3179cc27ec
commit
ec23d5d168
4 changed files with 203 additions and 31 deletions
|
@ -4,11 +4,8 @@
|
|||
"""
|
||||
from __future__ import division, print_function
|
||||
|
||||
import multiprocessing as mp
|
||||
#import time
|
||||
from inspect import getcallargs
|
||||
|
||||
|
||||
from . import progress
|
||||
|
||||
from .jobmanager import getCountKwargs, validCountKwargs
|
||||
|
@ -148,6 +145,7 @@ class ProgressBar(object):
|
|||
|
||||
count = callargs[self.cm[0]]
|
||||
max_count = callargs[self.cm[1]]
|
||||
|
||||
with progress.ProgressBar(count = count,
|
||||
max_count = max_count,
|
||||
prepend = "{} ".format(self.__name__),
|
||||
|
@ -155,6 +153,71 @@ class ProgressBar(object):
|
|||
pb.start()
|
||||
return self.func(**callargs)
|
||||
|
||||
class ProgressBarExtended(ProgressBar):
|
||||
"""
|
||||
extends the ProgressBar such that
|
||||
|
||||
on can turn of the ProgressBar by giving an extra argument,
|
||||
namely 'progress_bar_off' and set its value to 'True'.
|
||||
|
||||
further there will be an additional argument passed to the function
|
||||
called 'progress_bar' which allows to stop the progress bar from
|
||||
within the function. note that there will be an function signature error
|
||||
if the function does not accept the extra argument 'progress_bar'. So a
|
||||
general **kwargs at the end of the functions arguments will help.
|
||||
That is also the reason why the extended version comes in an extra class
|
||||
because it might otherwise break compatibility.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
>>> import jobmanager as jm
|
||||
|
||||
>>> c = jm.progress.UnsignedIntValue(val=0)
|
||||
>>> m = jm.progress.UnsignedIntValue(val=20)
|
||||
|
||||
>>> @jm.decorators.ProgressBarExtended # choose 'ProgressBarExtended'
|
||||
>>> def my_func_kwargs(c, m, **kwargs): # simply add '**kwargs' here
|
||||
>>> for i in range(m.value):
|
||||
>>> c.value = i+1
|
||||
>>> time.sleep(0.1)
|
||||
|
||||
>>> # same as when using ProgressBar
|
||||
>>> my_func_kwargs(c, m)
|
||||
|
||||
>>> # a simple kwarg will switch the progressBar off
|
||||
>>> my_func_kwargs(c, m, progress_bar_off=True)
|
||||
"""
|
||||
def __call__(self, *args, **kwargs):
|
||||
# Bind the args and kwds to the argument names of self.func
|
||||
callargs = getcallargs(self.func, *args, **kwargs)
|
||||
|
||||
progress_bar_off = False
|
||||
try:
|
||||
progress_bar_off = callargs['progress_bar_off']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
try:
|
||||
progress_bar_off = callargs['kwargs']['progress_bar_off']
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
if progress_bar_off:
|
||||
return self.func(**callargs)
|
||||
|
||||
|
||||
count = callargs[self.cm[0]]
|
||||
max_count = callargs[self.cm[1]]
|
||||
|
||||
with progress.ProgressBar(count = count,
|
||||
max_count = max_count,
|
||||
prepend = "{} ".format(self.__name__),
|
||||
**self.kwargs) as pb:
|
||||
pb.start()
|
||||
callargs['progress_bar'] = pb
|
||||
return self.func(**callargs)
|
||||
|
||||
|
||||
class ProgressBarOverrideCount(ProgressBar):
|
||||
def __call__(self, *args, **kwargs):
|
||||
|
|
|
@ -676,6 +676,7 @@ class Progress(Loop):
|
|||
self.interval = interval
|
||||
self.verbose = verbose
|
||||
self.name = name
|
||||
self.show_on_exit = False
|
||||
|
||||
self.add_args = {}
|
||||
|
||||
|
@ -709,8 +710,9 @@ class Progress(Loop):
|
|||
show a last progress -> see the full 100% on exit
|
||||
"""
|
||||
super(Progress, self).__exit__(*exc_args)
|
||||
self._show_stat()
|
||||
print('\n'*(self.len-1))
|
||||
if self.show_on_exit:
|
||||
self._show_stat()
|
||||
print('\n'*(self.len-1))
|
||||
|
||||
def _show_stat(self):
|
||||
"""
|
||||
|
@ -877,7 +879,11 @@ class Progress(Loop):
|
|||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def stop(self):
|
||||
def start(self):
|
||||
super(Progress, self).start()
|
||||
self.show_on_exit = True
|
||||
|
||||
def stop(self, make_sure_its_down = False):
|
||||
"""
|
||||
trigger clean up by hand, needs to be done when not using
|
||||
context management via 'with' statement
|
||||
|
@ -885,6 +891,14 @@ class Progress(Loop):
|
|||
super(Progress, self).stop()
|
||||
self._show_stat()
|
||||
print('\n'*(self.len-1))
|
||||
self.show_on_exit = False
|
||||
if make_sure_its_down and (self._proc is not None):
|
||||
check_process_termination(proc = self._proc,
|
||||
identifier = self._identifier,
|
||||
timeout = 2*self.interval,
|
||||
verbose = self.verbose,
|
||||
auto_kill_on_last_resort = True)
|
||||
|
||||
|
||||
def _reset_all(self):
|
||||
"""
|
||||
|
@ -970,7 +984,6 @@ class ProgressBar(Progress):
|
|||
|
||||
l = len_string_without_ESC(s1+s3)
|
||||
|
||||
|
||||
if max_count_value != 0:
|
||||
l2 = width - l - 1
|
||||
a = int(l2 * count_value / max_count_value)
|
||||
|
|
|
@ -85,10 +85,72 @@ def test_ProgressBarOverrideCount():
|
|||
my_func_ProgressBarOverrideCount_dec()
|
||||
print("done!")
|
||||
|
||||
def test_extended_PB_get_access_to_progress_bar():
|
||||
def my_func(c, m, **kwargs):
|
||||
for i in range(m.value):
|
||||
c.value = i+1
|
||||
time.sleep(0.1)
|
||||
|
||||
try:
|
||||
kwargs['progress_bar'].stop(make_sure_its_down=True)
|
||||
except:
|
||||
pass
|
||||
|
||||
print("let me show you something")
|
||||
|
||||
c = progress.UnsignedIntValue(val=0)
|
||||
m = progress.UnsignedIntValue(val=20)
|
||||
|
||||
print("call decorated func")
|
||||
my_func_dec = decorators.ProgressBarExtended(my_func)
|
||||
my_func_dec(c=c, m=m)
|
||||
|
||||
print("call non decorated func")
|
||||
my_func(c, m)
|
||||
|
||||
def test_extended_PB_progress_bar_off():
|
||||
c = progress.UnsignedIntValue(val=0)
|
||||
m = progress.UnsignedIntValue(val=20)
|
||||
|
||||
@decorators.ProgressBarExtended
|
||||
def my_func_kwargs(c, m, **kwargs):
|
||||
for i in range(m.value):
|
||||
c.value = i+1
|
||||
time.sleep(0.1)
|
||||
|
||||
@decorators.ProgressBarExtended
|
||||
def my_func_normal(c, m, progress_bar_off=False, **kwargs):
|
||||
for i in range(m.value):
|
||||
c.value = i+1
|
||||
time.sleep(0.1)
|
||||
|
||||
print("call with no kwarg -> normal progressBar")
|
||||
my_func_kwargs(c, m)
|
||||
|
||||
print("call with kwarg 'progress_bar_off = True' -> NO progressBar")
|
||||
my_func_kwargs(c, m, progress_bar_off = True)
|
||||
|
||||
print("call with kwarg 'progress_bar_off = False' -> normal progressBar")
|
||||
my_func_kwargs(c, m, progress_bar_off = False)
|
||||
|
||||
print("call with argument 'progress_bar_off = False' -> normal progressBar")
|
||||
my_func_normal(c, m, progress_bar_off = False)
|
||||
|
||||
print("call with default argument 'progress_bar_off = False' -> normal progressBar")
|
||||
my_func_normal(c, m)
|
||||
|
||||
print("call with argument 'progress_bar_off = True' -> NO progressBar")
|
||||
my_func_normal(c, m, progress_bar_off = True)
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_ProgressBar()
|
||||
test_decorator()
|
||||
test_ProgressBarOverrideCount()
|
||||
# test_ProgressBar()
|
||||
# test_decorator()
|
||||
# test_ProgressBarOverrideCount()
|
||||
# test_extended_PB_get_access_to_progress_bar()
|
||||
test_extended_PB_progress_bar_off()
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -509,25 +509,59 @@ def test_progress_bar_slow_change():
|
|||
time.sleep(1)
|
||||
count.value = i
|
||||
|
||||
def test_progress_bar_start_stop():
|
||||
max_count_value = 20
|
||||
|
||||
count = progress.UnsignedIntValue(0)
|
||||
max_count = progress.UnsignedIntValue(max_count_value)
|
||||
|
||||
with progress.ProgressBar(count=count,
|
||||
max_count=max_count,
|
||||
interval=0.5,
|
||||
speed_calc_cycles=5,
|
||||
verbose=1) as sbm:
|
||||
|
||||
sbm.start()
|
||||
|
||||
for i in range(max_count_value):
|
||||
time.sleep(0.1)
|
||||
count.value = i+1
|
||||
if i == 10:
|
||||
sbm.stop(make_sure_its_down = True)
|
||||
print("this will not overwrite the progressbar, because we stopped it explicitly")
|
||||
sbm.start()
|
||||
print("this WILL overwrite the progressbar, because we are still inside it's context (still running)")
|
||||
|
||||
print()
|
||||
print("create a progress bar, but do not start")
|
||||
with progress.ProgressBar(count=count,
|
||||
max_count=max_count,
|
||||
interval=0.5,
|
||||
speed_calc_cycles=5,
|
||||
verbose=1) as sbm:
|
||||
pass
|
||||
print("this is after progress.__exit__, there should be no prints from the progress")
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = [
|
||||
test_loop_basic,
|
||||
test_loop_signals,
|
||||
test_loop_normal_stop,
|
||||
test_loop_need_sigterm_to_stop,
|
||||
test_loop_need_sigkill_to_stop,
|
||||
test_why_with_statement,
|
||||
test_progress_bar,
|
||||
test_progress_bar_with_statement,
|
||||
test_progress_bar_multi,
|
||||
test_status_counter,
|
||||
test_status_counter_multi,
|
||||
test_intermediate_prints_while_running_progess_bar,
|
||||
test_intermediate_prints_while_running_progess_bar_multi,
|
||||
test_progress_bar_counter,
|
||||
test_progress_bar_counter_non_max,
|
||||
test_progress_bar_counter_hide_bar,
|
||||
test_progress_bar_slow_change,
|
||||
# test_loop_basic,
|
||||
# test_loop_signals,
|
||||
# test_loop_normal_stop,
|
||||
# test_loop_need_sigterm_to_stop,
|
||||
# test_loop_need_sigkill_to_stop,
|
||||
# test_why_with_statement,
|
||||
# test_progress_bar,
|
||||
# test_progress_bar_with_statement,
|
||||
# test_progress_bar_multi,
|
||||
# test_status_counter,
|
||||
# test_status_counter_multi,
|
||||
# test_intermediate_prints_while_running_progess_bar,
|
||||
# test_intermediate_prints_while_running_progess_bar_multi,
|
||||
# test_progress_bar_counter,
|
||||
# test_progress_bar_counter_non_max,
|
||||
# test_progress_bar_counter_hide_bar,
|
||||
# test_progress_bar_slow_change,
|
||||
test_progress_bar_start_stop,
|
||||
lambda: print("END")
|
||||
]
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue