Yes, it will work for some common combinations. Thank you for this note.

But I still have to import the combine function to some of my modules, 
which provide its own decorators. I use a custom auth library, which has a 
number of @authorize_* decorators.


On Thursday, June 21, 2012 6:28:00 PM UTC+4, Chris McDonough wrote:
>
> On 06/21/2012 10:18 AM, Max Avanov wrote: 
> > What are you talking about? This is not just my stupid ideological 
> > behavior. My current project has 30+ different subpackages, each of thes 
> > has view-modules. For now, I have to make 30+ extra imports just 
> > because.... hmm... I still don't get why I have to. 
>
> Not that it matters, but no.. you don't have to do any extra imports, at 
> least no more imports than importing the decorator(s) from somewhere 
> anyway.  In fact, you'd have to do fewer imports if you chained them 
> together in a place and imported the resulting chain, rather than 
> importing each of them separately and putting them into a list. 
>
> Without chaining, and with a patch to Pyramid to support a list argument 
> to decorator= : 
>
>    # in decorators.py 
>
>    def decorator1(context, request): 
>        ... 
>
>    def decorator2(context, request): 
>        ... 
>
>    def decorator3(context, request): 
>        ... 
>
>    # in views.py 
>
>    from decorators import decorator1, decorator2, decorator3 
>
>    @view_config(decorator=[decorator1, decorator2, decorator3]) 
>    def aview(request): 
>        ... 
>
> With chaining that becomes: 
>
>    # in decorators.py 
>
>    def combine(*decorators): 
>      def floo(view_callable): 
>          for decorator in decorators: 
>              view_callable = decorator(view_callable) 
>          return view_callable 
>      return floo 
>
>    def decorator1(context, request): 
>        ... 
>
>    def decorator2(context, request): 
>        ... 
>
>    def decorator3(context, request): 
>        ... 
>
>    combined = combine(decorator1, decorator2, decorator3) 
>
>    # in views.py 
>
>    from decorators import combined 
>
>    @view_config(decorator=combined) 
>    def aview(request): 
>        ... 
>
> So it's a seven-line difference in code, and arguably a bit cleaner in 
> the veiws module when the decorators are combined together using code 
> from the recipe. 
>
> > On Thursday, June 21, 2012 6:10:07 PM UTC+4, Chris Rossi wrote: 
> > 
> >     Don't let the perfect be the enemy of the good. 
> > 
> >     Chris 
> > 
> >     On Thu, Jun 21, 2012 at 9:59 AM, Max Avanov <[email protected] 
> >     <mailto:[email protected]>> wrote: 
> >      > But I want to. I really do. And view_config doesn't allow me to 
> >     do so. 
> >      > You should understand me. I don't want to have extra imports in 
> >     my project. 
> >      > I want transparent support from the framework. This example makes 
> >     sense for 
> >      > me: 
> >      > 
> >      > from pyramid.view import view_config 
> >      > @view_config(decorator=(decorator1, decorator2, ...)) 
> >      > 
> >      > But this is not: 
> >      > from pyramid.view import view_config 
> >      > # Why should I do this for each of my view modules? 
> >      > from somewhere import chain_decorators 
> >      > 
> >      > @view_config(decorator=chain_decorators(decorator1, decorator2, 
> >     ...)) 
> >      > 
> >      > 
> >      > 
> >      > On Thursday, June 21, 2012 4:21:24 PM UTC+4, Chris McDonough 
> wrote: 
> >      >> 
> >      >> On 06/21/2012 07:29 AM, Max Avanov wrote: 
> >      >> > > No! View callable functions must accept at least a request 
> >     argument. 
> >      >> > There will never be something this that will work as a view 
> >     callable: 
> >      >> > 
> >      >> > This is my typo. I was talking about a regular generic view 
> >     callable. 
> >      >> > I still don't get how to rewrite these @authenticate_form and 
> >     @https (as 
> >      >> > an example) - 
> >      >> > 
> >     
> https://github.com/Pylons/pylons/blob/master/pylons/decorators/secure.py 
> >     <
> https://github.com/Pylons/pylons/blob/master/pylons/decorators/secure.py> 
> > 
> >      >> > - to be able to do the common: 
> >      >> > 
> >      >> > @view_config() 
> >      >> > @https() 
> >      >> > @autnenticate_form 
> >      >> > def view(request) - or - def view(context, request) - or - def 
> >      >> > view(self) 
> >      >> > 
> >      >> > without passing it to view_config 
> >      >> 
> >      >> Why you don't want to pass the decorator to view_config via 
> >     decorator= I 
> >      >> have no idea, given that dealing with the differences is the 
> entire 
> >      >> purpose of that machinery and the code to support a chain of 
> >     decorators 
> >      >> is entirely boilerplate. 
> >      >> 
> >      >> But assuming you didn't, and assuming this isn't an entirely 
> >     theoretical 
> >      >> exercise which we're beating to death, you could write a 
> >     decorator that 
> >      >> assumed *one* signature which also set __module__, and __doc__ 
> >     and on 
> >      >> the function returned from the decorator: 
> >      >> 
> >      >> from functools import wraps 
> >      >> 
> >      >> def adecorator(wrapped): 
> >      >> def inner(request): 
> >      >> print request.url 
> >      >> return wrapped(request) 
> >      >> return wraps(wrapped, ('__module__', '__doc__'))(decorator) 
> >      >> 
> >      >> @view_config(....) 
> >      >> @adecorator 
> >      >> def view(request): 
> >      >> .... 
> >      >> 
> >      >> - C 
> >      >> 
> >      >> 
> >      >> 
> >      >> > 
> >      >> > 
> >      >> > On Thursday, June 21, 2012 2:39:57 AM UTC+4, Chris McDonough 
> >     wrote: 
> >      >> > 
> >      >> > On 06/20/2012 06:13 PM, Max Avanov wrote: 
> >      >> > > > So I'm lost as to what 
> >      >> > > you mean by "no other way to get access to request object" 
> >      >> > > 
> >      >> > > Because I must 
> >      >> > > - either to follow the official approach provided by Michael 
> >     (" a 
> >      >> > > consistent signature no matter whether the actual view is a 
> >      >> > method, or a 
> >      >> > > function 
> >      >> > > that accepts either (context, request) or just 
> (request)...") 
> >      >> > with the 
> >      >> > > consequent @view_config(decorator=...) and the chained code 
> >      >> > snipped. 
> >      >> > > - or use the "classic" way: 
> >      >> > > @decorator1 
> >      >> > > @decorator2 
> >      >> > > @decoratorN 
> >      >> > > @view_config 
> >      >> > > def func() 
> >      >> > > 
> >      >> > > For classic way I use the decorator package - 
> >      >> > > 
> >     http://micheles.googlecode.com/hg/decorator/documentation.html 
> >     <http://micheles.googlecode.com/hg/decorator/documentation.html> 
> >      >> > 
> >     <http://micheles.googlecode.com/hg/decorator/documentation.html 
> >     <http://micheles.googlecode.com/hg/decorator/documentation.html>> - 
> >      >> > But the 
> >      >> > > classic way allows me only one generic approach to get the 
> >      >> > request 
> >      >> > > object - via get_current_request, right? 
> >      >> > 
> >      >> > No! View callable functions must accept at least a request 
> >     argument. 
> >      >> > There will never be something this that will work as a view 
> >      >> > callable: 
> >      >> > 
> >      >> > def func(): 
> >      >> > ... 
> >      >> > 
> >      >> > It just wont work. A view callable must be: 
> >      >> > 
> >      >> > def func(request): 
> >      >> > ... 
> >      >> > 
> >      >> > An alternate view callable signature optionally accepts 
> >     "(context, 
> >      >> > request)" but if your code doesn't use that signature for any 
> of 
> >      >> > your 
> >      >> > view callables, you won't care. Pyramid view callables can 
> >     also be 
> >      >> > methods of classes, but if your code doesn't use view classes, 
> >     you 
> >      >> > won't 
> >      >> > care about that either. 
> >      >> > 
> >      >> > If you *do* care about reusing a decorator across all of these 
> >     view 
> >      >> > callable conventions, however, you can use the decorator= 
> >     argument 
> >      >> > to 
> >      >> > view_config. The point of the decorator= argument to 
> >     view_config is 
> >      >> > to 
> >      >> > provide genericness by accepting a decorator that can use a 
> >     single 
> >      >> > common call signature for a decorator ("(context, request)"). 
> >     So you 
> >      >> > can use the following decorator: 
> >      >> > 
> >      >> > def adecorator(viewcallable): 
> >      >> > def inner(context, request): 
> >      >> > print request.url 
> >      >> > return viewcallable(context, request) 
> >      >> > return inner 
> >      >> > 
> >      >> > .. against this kind of view configuration ... 
> >      >> > 
> >      >> > class AView(object): 
> >      >> > def __init__(self, request): 
> >      >> > self.request = request 
> >      >> > 
> >      >> > @view_config(decorator=adecorator) 
> >      >> > def aview(self): 
> >      >> > return Response('OK') 
> >      >> > 
> >      >> > .. or this kind ... 
> >      >> > 
> >      >> > @view_config(decorator=adecorator) 
> >      >> > def aview(request): 
> >      >> > return Response('OK') 
> >      >> > 
> >      >> > ... or this kind ... 
> >      >> > 
> >      >> > @view_config(decorator=adecorator) 
> >      >> > def aview(context, request): 
> >      >> > return Response('OK') 
> >      >> > 
> >      >> > ... or this kind ... 
> >      >> > 
> >      >> > @view_config(decorator=adecorator) 
> >      >> > class AView(object): 
> >      >> > def __init__(self, request): 
> >      >> > self.request = request 
> >      >> > 
> >      >> > def __call__(self): 
> >      >> > return Response('OK') 
> >      >> > 
> >      >> > ... or this kind ... 
> >      >> > 
> >      >> > class AView(object): 
> >      >> > def __init__(self, context, request): 
> >      >> > self.context = context 
> >      >> > self.request = request 
> >      >> > 
> >      >> > @view_config(decorator=adecorator) 
> >      >> > def aview(self): 
> >      >> > return Response('OK') 
> >      >> > 
> >      >> > You get the point. The *same decorator* will work against any 
> >     view 
> >      >> > callable you define, even though the place it gets used 
> differs: 
> >      >> > against a method of a class, against a class object, against a 
> >      >> > function 
> >      >> > object, and the associated callable may have different 
> >     arguments. It 
> >      >> > will still work in all scenarios. 
> >      >> > 
> >      >> > Since a decorator is just a callable that returns a callable, 
> >      >> > whether 
> >      >> > you use the package you linked to or not to produce one is 
> >      >> > irrelevant. 
> >      >> > Even the "@" syntax is just sugar. Instead of: 
> >      >> > 
> >      >> > @decorator1 
> >      >> > @decorator2 
> >      >> > def func(): 
> >      >> > ... 
> >      >> > 
> >      >> > it could just be: 
> >      >> > 
> >      >> > def func(): 
> >      >> > ... 
> >      >> > 
> >      >> > func = decorator2(decorator1(func)) 
> >      >> > 
> >      >> > If you're decorating functions or methods that you don't know 
> the 
> >      >> > argument list for, just make the decorator accept *arg, **kw 
> and 
> >      >> > pass 
> >      >> > those along to the wrapped function from your wrapper function 
> >      >> > defined 
> >      >> > inside the decorator. That will work for any sort of wrapped 
> >      >> > function, 
> >      >> > even those for a view callable. 
> >      >> > 
> >      >> > If you mean you want to create some sort of omniscient 
> decorator 
> >      >> > that 
> >      >> > can be used for both a view callable *and any other kind of 
> >      >> > function*, 
> >      >> > but which in both cases requires a request to.. do 
> something.., 
> >      >> > then, 
> >      >> > yes, you could use get_current_request inside the decorator 
> >     logic. 
> >      >> > It'd 
> >      >> > be insane to try to define such a decorator, when you could 
> just 
> >      >> > create 
> >      >> > one that expected the decorated function to supply the 
> (context, 
> >      >> > request) signature, but you could do it. 
> >      >> > 
> >      >> > If this all boils down to "why dont you support a sequence 
> rather 
> >      >> > than a 
> >      >> > single function as a valid decorator= argument" because you 
> >     need to 
> >      >> > mix 
> >      >> > and match logic in your decorators, please either submit some 
> >     code 
> >      >> > that 
> >      >> > makes it so or use the recipe for chained decorators. 
> >      >> > 
> >      >> > - C 
> >      >> > 
> >      >> > -- 
> >      >> > You received this message because you are subscribed to the 
> >     Google 
> >      >> > Groups "pylons-discuss" group. 
> >      >> > To view this discussion on the web visit 
> >      >> > https://groups.google.com/d/msg/pylons-discuss/-/fhyzewf5dfkJ 
> >     <https://groups.google.com/d/msg/pylons-discuss/-/fhyzewf5dfkJ>. 
> >      >> > To post to this group, send email to 
> >     [email protected] 
> >     <mailto:[email protected]>. 
> >      >> > To unsubscribe from this group, send email to 
> >      >> > [email protected] 
> >     <mailto:pylons-discuss%[email protected]>. 
> >      >> > For more options, visit this group at 
> >      >> > http://groups.google.com/group/pylons-discuss?hl=en 
> >     <http://groups.google.com/group/pylons-discuss?hl=en>. 
> >      >> 
> >      > -- 
> >      > You received this message because you are subscribed to the 
> >     Google Groups 
> >      > "pylons-discuss" group. 
> >      > To view this discussion on the web visit 
> >      > https://groups.google.com/d/msg/pylons-discuss/-/vp2QABR9sV0J 
> >     <https://groups.google.com/d/msg/pylons-discuss/-/vp2QABR9sV0J>. 
> >      > 
> >      > To post to this group, send email to 
> >     [email protected] 
> >     <mailto:[email protected]>. 
> >      > To unsubscribe from this group, send email to 
> >      > [email protected] 
> >     <mailto:pylons-discuss%[email protected]>. 
> >      > For more options, visit this group at 
> >      > http://groups.google.com/group/pylons-discuss?hl=en 
> >     <http://groups.google.com/group/pylons-discuss?hl=en>. 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> > Groups "pylons-discuss" group. 
> > To view this discussion on the web visit 
> > https://groups.google.com/d/msg/pylons-discuss/-/uf3n-nRpxvYJ. 
> > 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. 
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"pylons-discuss" group.
To view this discussion on the web visit 
https://groups.google.com/d/msg/pylons-discuss/-/NRuV692Zy5wJ.
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