On Nov 8, 2007 11:22 AM, Philip Jenvey <[EMAIL PROTECTED]> wrote: > Sometimes I wish we didn't have StackedObjectProxies, but they're > worth it for all their convenience.
SOPs are the biggest hurdle in Pylons' learning curve. Only a few people really understand how they and the registry work; everyone else just has to hope they work correctly. They're transparent but not completely. If you want to see a request attribute/method but don't remember what it's called or whether it exists, you can't just do "dir(request)" because that just shows the proxy's methods -- and ._currentObj() isn't even in the list! Instead you have to plow through the source thinking, "There must be a current-object method of some sort!" or find an incantation somewhere in the list archives. Then you get to SQLAlchemy's scoped_session, which is essentially the same thing but has a different API. I believe earlier versions of Pylons or one of its libraries had a third kind of proxy too. Quixote has explicit get_request(), get_response(), and get_session() functions. Sometimes I think that would have been a better idea. Second best would be properties, but I think you can have properties only in classes, not in modules. > We need to address the fact that they can't be used inside of > generators. > > One issue being that render doesn't work (see eleith's example on > pylons-discuss a little while back). Having to grab references to > _current_obj() before calling the generator is also pretty lame. > > I see a couple options: > > o Make SOPs work inside of generators. There are a couple ways of > doing this, both are pretty evil in the situation that you have an > app internally calling another app, and both apps reference the same > SOPs (e.g. a Pylons app internally calling another Pylons app). > > - The registry could not cleanup after itself (leave the SOPs in > the state they're in) if the housed wsgi app returns a generator. > This is very evil; the internally called app overwrites the calling > app's SOPs. Not really an option > > - The registry could notice when a generator was returned, cleanup > after itself like it does now, then return the generator wrapped in > an add_start_close_func (see paste.wsgilib). The start func would > restore the registry to the state it was previously in when > start_func was called, then clean it up again when close_func is > called. This is still evil, though not as bad as the alternative. It > could be really confusing in some rare situations. > > o We could provide alternative means of calling render() for > generators. render needs a reference to the buffet object > > - render(_buffet=buffet._current_obj()) > > - Maintain a reference to buffet in some context object that has a > render method. Then we might as well provide access to other SOP > objects on that context object. A decorator could set this object up > for the controller method -- and since it negates the need for any > pre-generator initialization, the controller method could be the > actual generator with the help of that decorator: > > class MyController(BaseController): > > @generator # assumes the method is a generator, and creates a > context object for it to use > def yieldstuff(self, pylons, id): > pylons.session['stuff'] = get_stuff(id, pylons.request.POST.get > ('value')) > yield pylons.render('/a.mako') > > pylons.c.name = None > yield pylons.render('/b.mako') > > yield 'more stuff' > > And of course 'pylons' could just be self. I'm all for fail-safe solutions with implementations that users can understand and verify they're correct. The @generator looks like the best compromise. The _buffet is also straightforward though ugly. What would the overhead be of creating a context object for all requests? That would avoid the ugly decorator. There's no reason we can't require users to call 'self.render' instead of 'render' if it streamlines the implementation and fixes a design bug. The first two solutions are the least desirable because if even the Pylons developers can't be sure they'll work in all cases, they're too fragile. -- Mike Orr <[EMAIL PROTECTED]> --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "pylons-devel" group. To post to this group, send email to pylons-devel@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/pylons-devel?hl=en -~----------~----~----~----~------~----~------~--~---