I did a quick test which seems to work :

class Essai(object):

    def requires_login(self, next=None, message="login required" ):

        """

        decorator that prevents access to action if not logged in

        """


>         def decorator(action):


>             def f(*a, **b):

                *pnext = next*

                self.flash = message

                if not pnext:

                    pnext = "defaulturl"

                print pnext, self.flash

                return action(*a, **b)

            f.__doc__ = action.__doc__

            f.__name__ = action.__name__

            f.__dict__.update(action.__dict__)

            return f


>         return decorator


>
> e=Essai()


> @e.requires_login()

def myfunc(x,y):

        print "myfunc",x,y


> @e.requires_login(next="other_next", message = "failed")

def myfunc2(x,y):

        print "myfunc2",x,y


> myfunc(0,"c")

myfunc2(1,"a")


Which output :

> defaulturl login required

myfunc 0 c

other_next failed

myfunc2 1 a


 But you're right, we have to be careful with the variable scope. Without
copying the decorator parameter into the local scope (see pnext), I
get UnboundLocalError: local variable 'next' referenced before
assignment....

-Mathieu


On Sun, May 30, 2010 at 01:57, mdipierro <[email protected]> wrote:

> I need to try this. there is a potential issue wich scope of
> variables.
>
> On May 29, 11:09 am, Mathieu Clabaut <[email protected]>
> wrote:
> > Did i miss something ot the following would be ok ?
> >
> >     def requires_login(self, next=None,
> message=self.message.access_denied
> > ):
> >         """
> >         decorator that prevents access to action if not logged in
> >         """
> >
> >         def decorator(action):
> >
> >             def f(*a, **b):
> >
> >                 if not self.basic() and not self.is_logged_in():
> >                     request = self.environment.request
> >                     self.environment.session.flash = message
> >                     if not next:
> >                         next = self.settings.login_url + '?_next=' + \
> >
> >  urllib.quote(URL(r=request,args=request.args,
> >                                 vars=request.get_vars))
> >                     redirect(next)
> >                 return action(*a, **b)
> >             f.__doc__ = action.__doc__
> >             f.__name__ = action.__name__
> >             f.__dict__.update(action.__dict__)
> >             return f
> >
> >         return decorator
> >
> > On Tue, May 25, 2010 at 01:07, Massimo Di Pierro <
> [email protected]>wrote:
> >
> > > It would be nice to be able to pass the following arguments to
> >
> > > @auth.requires_login(next=URL(...),message=T(...))
> >
> > > where next is the url to redirect to in case of no login. message is
> the
> > > message to be displayed.
> > > If somebody has time and wants to take a crack at it, let me know. It
> > > should be possible by modifying only the requires_login method.
> > > The problem is passing the arguments from the decorator to the function
> > > being returned.
> >
> > > Once the problem is solved we can add the feature to
> requires_membership
> > > and requires_permissions.
> >
> > > Massimo
>

Reply via email to