Skip to content

Commit

Permalink
Update the task decoration.
Browse files Browse the repository at this point in the history
If the task sets the timeout and contextify, the timeout stays on the original method,
not the contextify wrapper. Calling `.fill` ends up removing the `timeout`. Sharing the `_garcon_`
dictionary between the two methods solves this issue.

@rantonmattei
  • Loading branch information
xethorn committed Mar 4, 2015
1 parent ca88af3 commit ff140df
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 0 deletions.
21 changes: 21 additions & 0 deletions garcon/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,26 @@ def _decorate(fn, key=None, value=None):
})


def _link_decorator(source_fn, dest_fn):
"""Link the garcon decorator values between two methods.
If the destination method already have a value on `__garcon__`, we get it
and merge it with the other one (so no values are lost.)
Args:
source_fn (callable): The method that contains `__garcon__`.
dest_fn (callable): The method that receives the decorator.
"""

source_values = getattr(source_fn, '__garcon__', dict())

if hasattr(dest_fn, '__garcon__'):
source_values.update(dest_fn.__garcon__)

setattr(dest_fn, '__garcon__', source_values)
setattr(source_fn, '__garcon__', source_values)


def contextify(fn):
"""Decorator to take values from the context and apply them to fn.
Expand Down Expand Up @@ -115,6 +135,7 @@ def wrapper(context, **kwargs):

# Keep a record of the requirements value. This allows us to trim the
# size of the context sent to the activity as an input.
_link_decorator(fn, wrapper)
_decorate(wrapper, 'requirements', requirements.values())
return wrapper

Expand Down
37 changes: 37 additions & 0 deletions tests/test_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,43 @@ def test():
assert test.__garcon__.get('foo') is 'bar'


def test_link_decorator():
"""Test linking the decorator between two methods.
"""

def testA():
pass

def testB():
pass

task._decorate(testA, 'foo', 'value')
task._link_decorator(testA, testB)
assert testA.__garcon__ is testB.__garcon__
assert testA.__garcon__.get('foo') == 'value'
assert testB.__garcon__.get('foo') == 'value'


def test_link_decorator_with_empty_source():
"""Test linking decorators when garcon is not set on the source.
"""

def testA():
pass

def testB():
pass

task._link_decorator(testA, testB)
assert testA.__garcon__ is testB.__garcon__
assert len(testA.__garcon__) is 0
assert len(testB.__garcon__) is 0

task._decorate(testB, 'foo', 'value')
task._link_decorator(testA, testB)
assert testA.__garcon__.get('foo') == 'value'


def test_task_decorator():
"""Test the task decorator.
"""
Expand Down

0 comments on commit ff140df

Please sign in to comment.