From 6d6d54c91d95214ec070f42bbbb4bcb7a8dc089a Mon Sep 17 00:00:00 2001 From: supriyopaul Date: Tue, 30 Jan 2018 17:10:44 +0530 Subject: [PATCH] New keeprunning for taking arguments in functions more efficiently --- .travis.yml | 4 +- deeputil/keep_running.py | 98 ++++++++++++++++++++++++---------------- setup.py | 2 +- 3 files changed, 62 insertions(+), 42 deletions(-) diff --git a/.travis.yml b/.travis.yml index a002b5c..d533c9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,8 +10,8 @@ deploy: skip_cleanup: true api-key: secure: Q3wwYSZkwXAG1DwgKZrR/vZTGLZlDBfR9O5MoZ+dpmy6EmFozQLRB+qFh+eWh2Y8xYIdXz+6CaJLcM92JU5zJTslWLHyhO7kTOt31fxuZu+HGnR835Try6TlU11948nn2Ramk4nI3lT/G4jO+PdNq23sOPdhV4KDI0nv9Pc9Ywqoyg+4okpSnbJNWn7bdinthA88iMRNxqH88LJ4CM6J/eh0qJUm2xcAOTpw9gIkq188UTCbT71qGUWhWFicvbV1oJ6r+C87Ru/rf+nHJyZ7Dn2y8odBx+MHicUp7XomKP/niM2K9TkX/wOMqopE6XrmAnZ/6W/8cGOoqLWT0oqksktIqlOrUYQAq5UNXee3cHPq6k+Q/CGhbGb9feNEzb3PMPKkD6wict90arhHfpqk0yGP1lCRSwM0eIgegMWgSpFXi2Zc+K/6iucZ21ayVDZf20f7Pe70SEgjB/VJiTgI+BMmOG70a2MYsHUG+rK4fYiSDiO+9ADVNHHNy5r9dL+VLhRxkkcgaIkkZsx/xoE2KUO601EOEfjX55S0C8R/VRNDpxg1VXhu2i19E3G08Xcv+xuz8awst3gvVImVJY9j9GiimMtT0l/pLMjWTeAvMmlraxRaMa36Q96BntThdwRkNCAhsfCTF364egRI+PEWciRcrb0Tpj8/L8p2OUMMqgI= - name: deeputil-0.1.1 - tag_name: 0.1.1 + name: deeputil-0.1.2 + tag_name: 0.1.2 on: branch: master repo: deep-compute/deeputil diff --git a/deeputil/keep_running.py b/deeputil/keep_running.py index 3dfe0dd..4cadcad 100644 --- a/deeputil/keep_running.py +++ b/deeputil/keep_running.py @@ -1,4 +1,5 @@ import time +import inspect class KeepRunningTerminate(Exception): pass @@ -11,7 +12,7 @@ def keeprunning(wait_secs=0, exit_on_success=False, # without needing to have a loop in its code. Also, when error # happens, we should NOT terminate execution - >>> from deeputil.misc import AttrDict + >>> from deeputil import AttrDict >>> @keeprunning(wait_secs=1) ... def dosomething(state): ... state.i += 1 @@ -42,8 +43,8 @@ def keeprunning(wait_secs=0, exit_on_success=False, # dosomething keeps running, or perform any other action # when an exceptions arise - >>> def some_error(fn, args, kwargs, exc): - ... print (exc) + >>> def some_error(__exc__): + ... print (__exc__) ... >>> @keeprunning(on_error=some_error) ... def dosomething(state): @@ -75,54 +76,75 @@ def keeprunning(wait_secs=0, exit_on_success=False, Done - # Example 3:Full set of arguments that can be passed in @keeprunning() + # Example 3: Full set of arguments that can be passed in @keeprunning() + # with class implementations - >>> def success(fn, args, kwargs): - ... print('yay!!') - ... - >>> def failure(fn, args, kwargs, exc): - ... print('fck!', exc) - ... - >>> def task_done(fn, args, kwargs): - ... print('STOPPED AT NOTHING!') - ... - >>> @keeprunning(wait_secs=1, exit_on_success=False, + >>> # Class that has some class variables + ... class Demo(object): + ... SUCCESS_MSG = 'Yay!!' + ... DONE_MSG = 'STOPPED AT NOTHING!' + ... ERROR_MSG = 'Error' + ... + ... # Functions to be called by @keeprunning + ... def success(self): + ... print(self.SUCCESS_MSG) + ... + ... def failure(self, __exc__): + ... print(self.ERROR_MSG, __exc__) + ... + ... def task_done(self): + ... print(self.DONE_MSG) + ... + ... #Actual use of keeprunning with all arguments passed + ... @keeprunning(wait_secs=1, exit_on_success=False, ... on_success=success, on_error=failure, on_done=task_done) - ... def dosomething(state): - ... state.i += 1 - ... print (state) - ... if state.i % 2 == 0: - ... print("Error happened") - ... 1 / 0 # create an error condition - ... if state.i >= 7: - ... print ("Done") - ... raise keeprunning.terminate + ... def dosomething(self, state): + ... state.i += 1 + ... print (state) + ... if state.i % 2 == 0: + ... print("Error happened") + ... 1 / 0 # create an error condition + ... if state.i >= 7: + ... print ("Done") + ... raise keeprunning.terminate ... + >>> demo = Demo() >>> state = AttrDict(i=0) - >>> dosomething(state) + >>> demo.dosomething(state) AttrDict({'i': 1}) - yay!! + Yay!! AttrDict({'i': 2}) Error happened - ('fck!', ZeroDivisionError('integer division or modulo by zero',)) + ('Error', ZeroDivisionError('integer division or modulo by zero',)) AttrDict({'i': 3}) - yay!! + Yay!! AttrDict({'i': 4}) Error happened - ('fck!', ZeroDivisionError('integer division or modulo by zero',)) + ('Error', ZeroDivisionError('integer division or modulo by zero',)) AttrDict({'i': 5}) - yay!! + Yay!! AttrDict({'i': 6}) Error happened - ('fck!', ZeroDivisionError('integer division or modulo by zero',)) + ('Error', ZeroDivisionError('integer division or modulo by zero',)) AttrDict({'i': 7}) Done STOPPED AT NOTHING! - >>> + ''' def decfn(fn): + def _call_callback(cb, fargs): + if not cb: return + # get the getargspec fn in inspect module (python 2/3 support) + G = getattr(inspect, 'getfullargspec', getattr(inspect, 'getargspec')) + cb_args = G(cb).args + cb_args = dict([(a, fargs.get(a, None)) for a in cb_args]) + cb(**cb_args) + def _fn(*args, **kwargs): + fargs = inspect.getcallargs(fn, *args, **kwargs) + fargs.update(dict(__fn__=fn, __exc__=None)) + while 1: try: fn(*args, **kwargs) @@ -132,20 +154,18 @@ def _fn(*args, **kwargs): except KeepRunningTerminate: break except Exception, exc: - if on_error: - on_error(fn, args, kwargs, exc) + fargs.update(dict(__exc__=exc)) + _call_callback(on_error, fargs) + fargs.update(dict(__exc__=None)) if wait_secs: time.sleep(wait_secs) continue - if on_success: - on_success(fn, args, kwargs) - - if on_done: - on_done(fn, args, kwargs) + _call_callback(on_success, fargs) + + _call_callback(on_done, fargs) return _fn return decfn keeprunning.terminate = KeepRunningTerminate - diff --git a/setup.py b/setup.py index 29ffc1a..11fa754 100644 --- a/setup.py +++ b/setup.py @@ -3,7 +3,7 @@ setup( name="deeputil", - version="0.1", + version="0.1.2", description="Commonly re-used logic kept in one library", keywords="deeputil", author="Deep Compute, LLC",