I would propose a "task protocol" like so:

1. @task wraps a function in a task object (if it is not already such an
object)
2. Any decorator that assumes a task wraps the function in a task object, if
it is not already such an object.
3. Any decorator that doesn't assume a task (but is officially part of
fabric) must have semantics that can work with a task object or explicitly
fails because it doesn't handle task objects.

To get there, some changes need to be made, but surprisingly few as adding
attributes to a function or adding attributes to an object are the same
basic thing.

This would result in:
1. No ordering requirements
2. fewer confusions over stacking issues.
3. a @task decorator that occasionally does nothing (but not worries, it
still helps the readability of the code)

example code:

class Task(object):
    def __init__(self, f):
        self.f = f
    def __call__(self, *args, **kw):
        return self.f(*args, **kw)

def task(f):
    print "in task deco",
    if not isinstance(f, Task):
        print "making task"
        return Task(f)
    else:
        print "task already made"
        return f

def hostdeco(hostname):
    def actualdeco(f):
        f = task(f)
        print "in hostdeco setting hostname"
        f.hostname = hostname
        return f
    return actualdeco

print "setting up tasks"
print "@hostdeco then @task:"

@hostdeco("foo")
@task
def mytask():
    print "mytask"

print '------------------------------'
print "@task then @hostdeco"
# equivalent
@task
@hostdeco("foo")
def mytask2():
    print "mytask2"

print '------------------------------'
print "running tasks"
mytask()
mytask2()

outputs:

setting up tasks
@hostdeco then @task:
in task deco making task
in task deco task already made
in hostdeco setting hostname
------------------------------
@task then @hostdeco
in task deco making task
in hostdeco setting hostname
in task deco task already made
------------------------------
running tasks
mytask
mytask2

Regards,
Erich

On Thu, Jul 14, 2011 at 7:33 PM, Jeff Forcier <[email protected]> wrote:

> Hi Corry,
>
> On Thu, Jul 14, 2011 at 3:50 PM, Corry Haines <[email protected]>
> wrote:
> > I have some fab files that stack decorators, and while trying the name
> > spacing feature, I seem to have hit an odd issue.
> > Below are some example files, but the basic issue is that some decorators
> do
> > not seem to stack (and order matters).
>
> Well, decorators in general always have an "order matters" behavior,
> unfortunately -- since they are not guaranteed to always return the
> function they were given.
>
> This is the case with @task -- it wraps the function in a richer task
> class.
>
> So, it does need to come first/at the top of the list of decorators.
> We should probably add this to the docs so it's explicitly obvious.
>
> Please let us know if that doesn't answer the question -- since *most*
> of the other decorators don't care about the ordering (other Fab
> decorators simply tack attributes onto the functions and return them)
> it shouldn't be a problem, per se, to always stick @task at the top.
>
> Best,
> Jeff
>
> --
> Jeff Forcier
> Unix sysadmin; Python/Ruby engineer
> http://bitprophet.org
>
> _______________________________________________
> Fab-user mailing list
> [email protected]
> https://lists.nongnu.org/mailman/listinfo/fab-user
>
_______________________________________________
Fab-user mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/fab-user

Reply via email to