Marek,
You're right this class based decorator works, except for the first
problem mentioned, that is, 'unexpected keyword argument
`start_response`'.  It works with or without the 'self' param, that
ends up being the controller instance when decorating a Pylons
action.  This decorator will work fine on methods that are not Pylons
actions.

class deco(object):
    def __init__(self, option):
        print '__init__', option
        self.option = option

    def __call__(self, func):
        print '__call__: decorating', func.func_name
        def newfunc(self, *args, **kwargs):
            print 'newfunc', self, args, kwargs.keys()
            # passing in kwargs here throws exception
            return func(self, *args, **kwargs)
        return newfunc
.....
@deco('myoption')
def action(self):
    return 'action result'


I can avoid the 'unexpected kwarg `start_response`' error by using the
decorator module to wrap a function based decorator.  I believe the
decorator module somehow does the magic of preserving the function
signature so it does not throw the kwarg error.  For now, I guess I
will go with this.  I would like to figure out how to apply the
decorator module to the class based decorator as well.

def factory(option):
    def deco(func, self, *args, **kwargs):
        print 'deco decorating ', func.func_name, self, args,
kwargs.keys()
        return func(self, *args, **kwargs)
    return decorator(deco)

Thanks,
Chris

On Feb 10, 10:34 am, "Marek Stępniowski" <[EMAIL PROTECTED]>
wrote:
> 09-02-08, Chris <[EMAIL PROTECTED]> napisał(a):
>
>
>
>
>
> (cut!)
> > I think you get the AssertionError because the authorize function
> > accepts arguments.  In that case, I believe it is called a decorator
> > factory and you need to call it like @authorize() with parenthesis.
> > But obviously, I'm not an expert :)
>
> > One other question/comment, it seems a class based decorator is not
> > doable on a controller method.
>
> > class deco(object):
> >     def __init__(self, func):
> >         self.func = func
> >     def __call__(self, *args, **kwargs):
> >         return self.func(*args, **kwargs)
>
> > @deco
> > def myaction(self):
> >   return 'results'
>
> > This results in:
> > <type 'exceptions.NotImplementedError'>: Action u'myaction' is not
> > implemented
>
> > THis happens because _dispatch_call in pylons.controllers.core, check
> > the type of the func and expects it to be of type 'instancemethod'.
> > But a class based decorator will be of some 'class' type, even though
> > it is still callable.  Expected, bug?
>
> I didn't test it, but in your example above class deco seems to be a
> decorator factory
> (because __call__ is an instance method, not a class method, and
> calling a class always returns a new instance of this class).
> So you should probably call it like this:
>
> class deco(object):
>     def __init__(self, func):
>         self.func = func
>     def __call__(self, *args, **kwargs):
>         return self.func(*args, **kwargs)
>
> @deco()
> def myaction(self):
>   return 'results'
>
> As I said, I haven't tested it :-)
>
> --
> Marek Stępniowski
> email: [EMAIL PROTECTED] || [EMAIL PROTECTED]
> gg: 5354504
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/pylons-discuss?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to