from decorator import decorator from garcon import runner from garcon import task from feed_ingestion.flows import base def decorator_changing_signature(orig_func): """ The problem of this implementation is that returned wrapper has a different signature than the original function. When garcon tries to resolve requirements from context it checkes what parameters the task needs and passes exclusively those. Id does it here: function_arguments = fn.__code__.co_varnames[:fn.__code__.co_argcount] (https://github.com/xethorn/garcon/blob/master/garcon/task.py#L239) """ def wrapper(*args, **kwargs): print('Args: %s' % (args,)) print('Kwargs: %s' % (kwargs,)) return orig_func(*args, **kwargs) return wrapper @decorator def decorator_preserving_signature(orig_func, *args, **kwargs): """decorator library lets us preserve the signature of the original function thus garcon stays happy.""" print('Args: %s' % (args,)) print('Kwargs: %s' % (kwargs,)) return orig_func(*args, **kwargs) class Flow(base.FlowBase): def __init__(self): super(Flow, self).__init__('decorator_demo', version='1.0') def decider(self, schedule): bootstrap = schedule('bootstrap', self.bootstrap_activity) schedule('cool', self.cool_activity, requires=[bootstrap]) @property def bootstrap_activity(self): return self.create( name='bootstrap', tasks=runner.Sync(bootstrap.fill( date='context_date' ))) @property def cool_activity(self): return self.create( name='cool', tasks=runner.Sync( cool_task.fill( param_1='param_1', param_2='param_2'))) @task.decorate(timeout=1000) def bootstrap(activity, date): activity.logger.info('Bootstrap: %s', date) return { 'param_1': 'param_1_value', 'param_2': 'param_2_value' } @task.decorate(timeout=1000) # @decorator_changing_signature @decorator_preserving_signature def cool_task(activity, param_1, param_2): activity.logger.info('Cool task (1): %s', param_1) activity.logger.info('Cool task (2): %s', param_2)