On Thu, Jun 21, 2012 at 06:59:03AM -0700, Max Avanov 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, ...))
Woo-hoo! Looks like this thread just went another time around the racetrack! Go a few messages back and Chris says: "lack of framework-based multiple decorator support just hasn't been a real pressing issue for anyone, especially given the linked recipe. If we're lucky, someone for whom it seems to be a pressing issue can help provide a patch that integrates the linked recipe into the config with docs and tests." Which looks to me to be exactly what you want above. So, if this is a pressing issue for you, please "help provide a patch that integrates the linked recipe into the config with docs and tests." > > > 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 > > > - 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> - > > > 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. > > > To post to this group, send email to pylons-discuss@googlegroups.com. > > > To unsubscribe from this group, send email to > > > pylons-discuss+unsubscr...@googlegroups.com. > > > 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/-/vp2QABR9sV0J. > To post to this group, send email to pylons-discuss@googlegroups.com. > To unsubscribe from this group, send email to > pylons-discuss+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/pylons-discuss?hl=en. > -- Brian Sutherland -- You received this message because you are subscribed to the Google Groups "pylons-discuss" group. To post to this group, send email to pylons-discuss@googlegroups.com. To unsubscribe from this group, send email to pylons-discuss+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/pylons-discuss?hl=en.