Gary Godfrey wrote: > Fun stuff. BTW, if it didn't come across in my last message, I really > got a feeling of "drinking the cool-aid" during pycon. Finally "got" > paste (and many aspects of TG) that I didn't before. Some of the > zelotry will likely wear off soon :-).
Yes, once you "get" it, its amazing where the thoughts start roaming. :) > The main issue that I have with library functions is that it's not > (currently) portable across frameworks. I can't do: > from <current running parent framework> import Identity Sure you can. Library functions are absolutely portable if they're well encapsulated. The Python Email library works great regardless of framework, the WebHelpers package spits out HTML in templates regardless of template/framework choice, etc. Libraries can absolutely be portable across frameworks.... if they're designed not to rely on framework specific environment variables that is. ;) > So I'm thinking of using environ as a proxy. You can still do calls > within this scope (just for example): > environ['Identity'].user_can(permission='edit_people') Again, is there some reason that won't work as a function? Heck, its just a function you put in the environ, isn't it? That already means you can use it as a library. Why does sticking the function in a dict thats passed around make it any more framework-portable than a library? When I heard about Identity being created, I asked at the time why not make it as a combination. That is, middleware, and functions you use in the framework. The middleware part of it is what you initialize before your webapp starts, it also sets up a thread-safe global for use by Identity functions throughout your application. This makes it easier to use identity functions since you don't need to keep passing environ all over the place in your application. Functions can just use a thread-safe (request-local) global to pull config/objects out. > I sort of like the idea that environ as the primary thread-safe area to > use. We need to be _very_ careful about namespace and clutter, but the > same is true for any namespace. Sure, though environ is thread-safe mainly because its a dict. Cluttering environ is no better than cluttering the namespace, but thread-safe module globals are a good way for some things to function. Consider with the Identity middleware, if it sets a thread-safe global as its called, before it calls your app, you would be able to do this anywhere inside your webapp: from identity import app_identity print app_identity.user_can(permission='edit_people') This could work, because the middleware during its call, initializes the thread-local global for itself. Then any function that uses Identity could import the config and get to the functions and active setup that it needs to. No cluttering of environ, no cluttering of the namespace, and its framework neutral. Middleware ensures that the request-local module global is present, library functions can then be used easily anywhere. > Cool - I can see a big thing here is documentation. It's going to be > very easy to get this thing confused! I'm also envisioning that the > docstrings for these routines should have dot embedded in them. Now, > how to automagically create a pretty graph which automatically searches > the source and looks for callbacks and exceptions up the wsgi stack... Yup, definitely a big thing. Also, having a very handy way to setup the middleware stack for a webapp is a good idea. In Pylons, the middleware stack is setup for you, and put in the new projects config data, it looks like this: http://pylonshq.com/project/pylonshq/browser/Pylons/trunk/pylons/templates/paster_template/%2Bpackage%2B/config/middleware.py_tmpl Making TurboGears run with full Paste-compatibility will lead to a config file along these lines somewhere anyways, it'd be great to have a format thats fairly generic and is in the same place between frameworks even. Despite what pieces of middleware is being loaded, we can then start standardizing on project layouts when possible. > That's sort of what we have with WSGI, isn't it? The only difference > is that the method name and additional parameters are pulled from > environ['PATH_INFO'] rather than passed in parameters. I am thinking > of making a function or two which will make managing this while doing > RESTful stuff a bit easier. Yes, that does work to an extent. I should note here, URL generation is absolutely important at this point. Every single URL, whether referring to a static or dynamic section, needs to use URL generation to ensure the app works (as it needs to add SCRIPT_NAME when needed). Since no one is going to want to hold environ and be passing it all over the place during the template rendering, etc. its useful to provide a module request-local access to it. > Again, still easy to do WSGIish (top of head, no error checking)i: > def __call__(self, environ, start_response): > tgEnviron(environ) # Make sure environment has things in place > # lc path_info has PATH_INFO split on '/' and cleaned up. > if not environ['path_info'][0] in ['Login','Logout']: > identity.require(environ, identity.in_group('admin')) > return self.defaultCall(environ, start_response) # standard > Controller __call__ There's a lot to be said for nice request objects. While environ is pretty easy to work with, having a nice request object to deal with is even better. Other than that, I think your example looks slick. Does every controller call tgEnviron then? > Nope - only the wsgi Server/Gateway side needs to worry about that. > environ is thread safe - if we hang everything there, then we're safe. Hopefully my spiel about request-local module globals convinced you? :) > You're right - each controller is really WSGI middleware. Mmm, its not really middleware either, as middleware will assume its between things, it still seems wrong to me to have middleware that won't work by itself in the middle of some other stack. Consider the following example: You have a Blog app, the blog app has a few dozen controllers, one of them is admin.comments for administrating the comments section as an admin. How would you be able to use admin.comments in a Finance webapp stack? I really don't see how, because your admin.comments controller is exceptionally dependent on the fact that its part of your Blog app and is surrounded by other controllers you wrote it with. If it was truly WSGI middleware, then it'd be pluggable into any stack you'd want to use it in. This is what I meant by abusing terminology. However, if you say that your controllers use a WSGI interface when called, then you *could* put in a fully independent wsgi middleware/app, or one of your apps controllers, and it'd work the same either way. This is mainly a terminology issue, as we seem to be in agreement that using the WSGI interface is a "good idea". :) > Again, I think it's completely valid (and necessary) for Applications > to make assumpions about upstream middleware. I'm assuming that a TG > application which is running under a different Server/Gateway would > have a small piece of middleware which marshalls the enviorn > appropriately to resemble the normal TG Server environment. Yup, makes sense. I think it sounds like a great idea, and is very pluggable indeed. I'd consider using request-local module globals for things like Identity and some middleware. Paste does this as well, and its a pretty useful thing so that functions in various locations can get to request-local data that was setup by middleware. I think it'd be great to standardize on a few things so that besides for being able to re-use components of frameworks like middleware, we can re-use other chunks. To an extent some of the work done during the sprint went this direction. Given the WSGI stuff you spoke of, I think there's a few clear things that standardizing on would be great for: request object - Paste's goes a good distance already, RT's does as well, CP provides the cpg.request, etc. This could even be a small bit of middleware that your application puts up front and then the rest of your app can get to it like how you can get to cpg.request from anywhere. Also, out of all the frameworks I've used, the request object seems to differ the least. middleware config - Having a nice place to setup the middleware stack for your application is a good idea. I'd propose a config/ directory in the project, with middleware.py. It's worked out quite well for Pylons but am open to better ideas as well. I should note that we tried a single config.py file as well, but setting up routes, middleware stacks, etc. all in a single file became a real chore. Hmm, now that I think about it, TG decorators could be quite portable as well if they could assume there was a standard request object available, and it was known that the method content was being returned via the WSGI interface.... Some thoughts anyways. :) - Ben --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "TurboGears" 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/turbogears -~----------~----~----~----~------~----~------~--~---

