mirror of
https://github.com/vale981/jobmanager
synced 2025-03-06 02:11:39 -05:00
minor change to make python 3.4 compatible. Changed default behavior of progressBar decorator. The functions to be decorated NEEDS (c,m) in their definition. made it also possible to call the decorated functions with c or/and m as positional agruments. Added test for that, moved existing tests to test/test_decorators.py. This closes #11
This commit is contained in:
parent
0301665936
commit
3594d67c12
2 changed files with 130 additions and 64 deletions
|
@ -5,7 +5,8 @@
|
|||
from __future__ import division, print_function
|
||||
|
||||
import multiprocessing as mp
|
||||
import time
|
||||
#import time
|
||||
from inspect import getcallargs
|
||||
|
||||
|
||||
from . import progress
|
||||
|
@ -15,7 +16,6 @@ from .jobmanager import getCountKwargs, validCountKwargs
|
|||
__all__ = ["ProgressBar"]
|
||||
|
||||
|
||||
|
||||
class ProgressBar(object):
|
||||
""" A wrapper/decorator with a text-based progress bar.
|
||||
|
||||
|
@ -23,23 +23,44 @@ class ProgressBar(object):
|
|||
- __init__
|
||||
- __call__
|
||||
|
||||
The idea is to add a status bar for a regular
|
||||
function just by wrapping the function via
|
||||
python's decorator syntax.
|
||||
|
||||
Examples
|
||||
--------
|
||||
In order to do so, the function needs to provide some
|
||||
extra information, namely the current state 'count' and
|
||||
the final state 'max_count'. Simply expand your function
|
||||
by these two additional keyword arguments (or other pairs
|
||||
specified in jobmanager.validCountKwargs) and set their
|
||||
values during the calculation (see example 1 below). In that
|
||||
manner the decorated function as well as the not decorated
|
||||
function can simple be called as one would not care about
|
||||
any status information.
|
||||
|
||||
Alternatively one could explicitly set count and max_count
|
||||
in the function call, which circumvents the need to change
|
||||
the value of max_count AFTER instantiation of the progressBar.
|
||||
|
||||
|
||||
Example 1
|
||||
---------
|
||||
|
||||
>>> from jobmanager.decorators import ProgressBar
|
||||
>>> from jobmanager.decorators.progress import UnsignedIntValue
|
||||
>>> import time
|
||||
>>>
|
||||
>>> @ProgressBar
|
||||
>>> def my_func(arg, kwarg="1", count=None, max_count=None):
|
||||
>>> def my_func_1(arg,
|
||||
>>> kwarg = "1",
|
||||
>>> count = UnsignedIntValue(val=0),
|
||||
>>> max_count = UnsignedIntValue(val=1)):
|
||||
>>> # max_count should as default always be set to a value > 0
|
||||
>>> maxval = 100
|
||||
>>> if max_count is not None:
|
||||
>>> max_count.value = maxval
|
||||
>>>
|
||||
>>> max_count.value = maxval
|
||||
>>>
|
||||
>>> for i in range(maxval):
|
||||
>>> if count is not None:
|
||||
>>> count.value += 1
|
||||
>>> time.sleep(0.05)
|
||||
>>> count.value += 1
|
||||
>>> time.sleep(0.02)
|
||||
>>>
|
||||
>>> return arg+kwarg
|
||||
>>>
|
||||
|
@ -47,6 +68,22 @@ class ProgressBar(object):
|
|||
# The progress of my_func is monitored on stdout.
|
||||
one argument second argument
|
||||
|
||||
Example 2
|
||||
---------
|
||||
|
||||
>>> from jobmanager.decorators import ProgressBar
|
||||
>>> from jobmanager.decorators.progress import UnsignedIntValue
|
||||
>>> import time
|
||||
>>>
|
||||
>>> @ProgressBar
|
||||
>>> def my_func(c, m):
|
||||
>>> for i in range(m.value):
|
||||
>>> c.value = i
|
||||
>>> time.sleep(0.02)
|
||||
>>>
|
||||
>>> c = progress.UnsignedIntValue(val=0)
|
||||
>>> m = progress.UnsignedIntValue(val=100)
|
||||
>>> my_func(c, m)
|
||||
|
||||
Notes
|
||||
-----
|
||||
|
@ -57,7 +94,7 @@ class ProgressBar(object):
|
|||
>>> result = wrapper("wrapped function", kwarg=" test")
|
||||
|
||||
"""
|
||||
def __init__(self, func, *args, **kwargs):
|
||||
def __init__(self, func, **kwargs):
|
||||
""" Initiates the wrapper objet.
|
||||
|
||||
A function can be wrapped by decorating it with
|
||||
|
@ -72,8 +109,6 @@ class ProgressBar(object):
|
|||
two keyword-arguments `count` and `max_count` (or `c` and
|
||||
`m`). The method `func` increments `count.value` up to
|
||||
`max_count.value` (`c.value`, `m.value`).
|
||||
*args : list
|
||||
Arguments for `jobmanager.ProgressBar`.
|
||||
**kwargs : dict
|
||||
Keyword-arguments for `jobmanager.ProgressBar`.
|
||||
|
||||
|
@ -87,16 +122,13 @@ class ProgressBar(object):
|
|||
"""
|
||||
self.__name__ = func.__name__ # act like the function
|
||||
self.func = func
|
||||
self.args = args
|
||||
self.kwargs = kwargs
|
||||
# works with Python 2.7 and 3.3
|
||||
valid = func.__code__.co_varnames[:func.__code__.co_argcount]
|
||||
# Check arguments
|
||||
self.cm = getCountKwargs(func)
|
||||
if self.cm is None:
|
||||
raise ValueError(
|
||||
"The wrapped function `{}` ".format(func.func_name)+
|
||||
"must accept one of the folling pairs of "+
|
||||
"must accept one of the following pairs of "+
|
||||
"keyword arguments:{}".format(validCountKwargs))
|
||||
|
||||
|
||||
|
@ -110,18 +142,18 @@ class ProgressBar(object):
|
|||
**kwargs : dict
|
||||
Keyword-arguments for `func`.
|
||||
"""
|
||||
# check if the kwarg is already given
|
||||
# (e.g. by a function that is nested.
|
||||
if not kwargs.has_key(self.cm[0]) or kwargs[self.cm[0]] is None:
|
||||
# count
|
||||
kwargs[self.cm[0]] = progress.UnsignedIntValue(0)
|
||||
if not kwargs.has_key(self.cm[1]) or kwargs[self.cm[1]] is None:
|
||||
# max_count
|
||||
kwargs[self.cm[1]] = progress.UnsignedIntValue(1)
|
||||
with progress.ProgressBar(kwargs[self.cm[0]], kwargs[self.cm[1]],
|
||||
*self.args, **self.kwargs) as pb:
|
||||
|
||||
# Bind the args and kwds to the argument names of self.func
|
||||
callargs = getcallargs(self.func, *args, **kwargs)
|
||||
|
||||
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()
|
||||
return self.func(*args, **kwargs)
|
||||
return self.func(**callargs)
|
||||
|
||||
|
||||
|
||||
|
@ -157,40 +189,5 @@ def decorate_module_ProgressBar(module, **kwargs):
|
|||
kwargs["verbose"] > 0):
|
||||
print("Jobmanager wrapped {}.{}".format(
|
||||
module.__name__, key))
|
||||
|
||||
|
||||
@ProgressBar
|
||||
def _my_func_1(arg, kwarg="1", count=None, max_count=None):
|
||||
maxval = 100
|
||||
if max_count is not None:
|
||||
max_count.value = maxval
|
||||
|
||||
for i in range(maxval):
|
||||
if count is not None:
|
||||
count.value += 1
|
||||
|
||||
time.sleep(0.02)
|
||||
|
||||
return arg+kwarg
|
||||
|
||||
|
||||
def _my_func_2(arg, c, m, kwarg="2"):
|
||||
maxval = 100
|
||||
m.value += maxval
|
||||
|
||||
for i in range(maxval):
|
||||
c.value += 1
|
||||
|
||||
time.sleep(0.02)
|
||||
|
||||
return arg+kwarg
|
||||
|
||||
|
||||
def _test_ProgressBar():
|
||||
result1 = _my_func_1("decorated function", kwarg=" 1")
|
||||
print(result1)
|
||||
|
||||
wrapper = ProgressBar(_my_func_2, interval=.1)
|
||||
result2 = wrapper("wrapped function", kwarg=" 2")
|
||||
print(result2)
|
||||
|
||||
|
|
69
test/test_decorators.py
Normal file
69
test/test_decorators.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
from __future__ import division, print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
|
||||
from os.path import abspath, dirname, split
|
||||
|
||||
# Add parent directory to beginning of path variable
|
||||
sys.path = [split(dirname(abspath(__file__)))[0]] + sys.path
|
||||
|
||||
from jobmanager import decorators, progress
|
||||
|
||||
@decorators.ProgressBar
|
||||
def _my_func_1(arg,
|
||||
kwarg = "1",
|
||||
count = decorators.progress.UnsignedIntValue(val=0),
|
||||
max_count = decorators.progress.UnsignedIntValue(val=1)):
|
||||
maxval = 100
|
||||
max_count.value = maxval
|
||||
|
||||
for i in range(maxval):
|
||||
count.value += 1
|
||||
time.sleep(0.02)
|
||||
|
||||
return arg+kwarg
|
||||
|
||||
|
||||
def _my_func_2(arg,
|
||||
c = decorators.progress.UnsignedIntValue(val=0),
|
||||
m = decorators.progress.UnsignedIntValue(val=1),
|
||||
kwarg = "2"):
|
||||
maxval = 100
|
||||
m.value += maxval
|
||||
|
||||
for i in range(maxval):
|
||||
c.value += 1
|
||||
time.sleep(0.02)
|
||||
|
||||
return arg+kwarg
|
||||
|
||||
|
||||
def test_ProgressBar():
|
||||
result1 = _my_func_1("decorated function", kwarg=" 1")
|
||||
print(result1)
|
||||
|
||||
wrapper = decorators.ProgressBar(_my_func_2, interval=.1)
|
||||
result2 = wrapper("wrapped function", kwarg=" 2")
|
||||
print(result2)
|
||||
|
||||
@decorators.ProgressBar
|
||||
def my_func(c, m):
|
||||
for i in range(m.value):
|
||||
c.value = i
|
||||
time.sleep(0.02)
|
||||
|
||||
def test_decorator():
|
||||
c = progress.UnsignedIntValue(val=0)
|
||||
m = progress.UnsignedIntValue(val=100)
|
||||
my_func(c=c, m=m)
|
||||
my_func(c, m)
|
||||
|
||||
if __name__ == "__main__":
|
||||
test_ProgressBar()
|
||||
test_decorator()
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue