Re: [Web-SIG] Standardized template API
At 12:12 PM 2/1/2006 -0500, Michael Bayer wrote: On Feb 1, 2006, at 11:07 AM, Phillip J. Eby wrote: spec is about (like what is template polymorphism exactly ?) Specifying only a template's *name* in code, not its type. In peak.web, if I refer to a resource or template named foo, the system looks in the resource directory and determines the template type based on extensions. So if there's a foo.pwt or foo.html or foo.gif or foo.jpeg, it determines the resource type from that. When you combine this feature with skinning, it means that deployers are free to change the technology used to deliver a particular template or resource. For example, replacing a .gif or .jpeg with a .png or vice versa, or using a different template engine for a template. It seems like myghty resolver does this as well...you send in a URI, and as it walks down the chain, it can hit FileResolver (returns file- based templates), ModuleResolver (returns python callables), each of which are free to return whatever Component object they want if they have something to offer for that URI; each Component just has a run() method. you can inject whatever customized rule you want to return something else at some point. rules could be constructed to return an adapted version of any other template's template object too. So asking for foo can resolve to foo.gif or foo.jpeg in the file system? If you have to say in the code which it is, that's not what I mean. ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Standardized template API
At 11:43 AM 2/1/2006 -0500, Clark C. Evans wrote: On Tue, Jan 31, 2006 at 08:55:22PM -0500, Phillip J. Eby wrote: | Indeed, I'd argue that it'd be better here to create a WSGI-based | template interface, rather than a specialized template interface. | That is, if the compiled template returned by a template engine is | just a WSGI application object, then it provides a maximum of | flexibility. If individual frameworks want to supply additional data | or features, they can do so via additional environ keys. Let's follow this idea through. Would the ``environ`` essentially act like the dict that most template engines already use for input? Or would it require something like environ['wsgi.result'] be a dict that acts as this primary input? How does this application get its input? As I mentioned in my counter-proposal, there should probably be a key like 'wti.source' to contain either the object to be published (for publisher-oriented frameworks) or a dictionary of variables (for controller-oriented frameworks). I originally called it published object, but that's biased towards publisher frameworks so perhaps a more neutral name like 'source' or 'data' would be more appropriate. Ideally, I'd like for us to move forward with hammering out the details of this and any other APIs that should be present in a WSGI Template or WSGI Resource interface. Perhaps the WSGI application specification should be modified to allow the response to be an interation over any sort of object that can be converted to a str? This would allow filters to be written w/o emitting and re-parsing content in an intermediate format. Actually, my 'wti.return_string' idea in a previous post does this in a slightly different way. Having return_foo APIs allows you to return other types of objects that can be converted to normal WSGI or left alone, according to whether the caller understands them. Think of it as a Python form of HTTP_ACCEPT. :) For an existing example of this idea, consider WSGI's file_wrapper feature, that wraps a file as an iterable, but can bypass it and use the file directly if no intervening middleware uses the iterable. This idea could be extended to DOMs or other kinds of objects. On Tue, Jan 31, 2006 at 09:04:43PM -0600, Ian Bicking wrote: | Phillip J. Eby wrote: | 1. It disadvantages better solutions (whether frameworks or templates) | by reducing everything to the least common denominator | | I think exposing load_template is an escape for template languages that | don't fit into the standard dictionary-in-string-out approach. Besides | that, I don't know what Better Solution we're talking about. I don't see how something like this disadvantages better solutions. If anything, I can see how it would enable quicker adoption of better solutions: an adapter from this simple interface to the better interface would be easy to construct and thus give out of the gate any better interface a leg-up. No, it wouldn't. The WSGI templating proposal effectively requires the framework to allow resources full control of a WSGI response, whereas a framework that just strips off the WSGI bits and only keeps a string completely disempowers the template. That's what I mean by disadvantaging better solutions. We can and should turn that around: disadvantage the frameworks that *don't* let the resource have control, instead of disadvantaging the resources that want to get control. In fact, template is probably the wrong word for us to be using here; the issue is more about embedding rich dynamic resources, only some of which happen to be simple templates. If we get that, we get templates as a side effect. But if we only do templates, we make it harder for resource embedding to get a foothold. (This reminds me a bit of the complaints when the Microsoft CLR came out, that it basically makes every language into syntax sugar for C#, while disadvantaging more dynamic languages by making them relatively harder to implement and/or slower. Only in this case, we're not talking about something that can be worked around with partial interpretation and fancier compiler techniques.) | 3. Doesn't allow the framework to control the lifetime of compiled | resources | | Ok... so what should we do? We can say that .load_template is not | allowed to cache the thing it returns, and require find_resource to do | the caching. Phillip, I fail to see how this is a problem. Doesn't Python have garbage collecting and weak references? The earlier proposal, if I understood it correctly, never exposed a compiled template object to the framework, so GC and weak references wouldn't have helped. Any caching would've had to be done by the engine without any input from the framework as to how long something was needed. Arranging the API to expose compiled resource objects would fix that, since the framework could hold on to them as long as it liked, and normal refcounting would take care of resource
Re: [Web-SIG] Standardized template API
On Feb 1, 2006, at 12:59 PM, Phillip J. Eby wrote: At 1 So asking for foo can resolve to foo.gif or foo.jpeg in the file system? If you have to say in the code which it is, that's not what I mean. you can write a resolver that searches the filesystem for foo.* and does some type calculation based on the extension it located, sure. or you get a similar effect with two resolvers in a chain, one which is configured to look for name.jpeg and return a jpeg-template, and one configured to look for name.gif to return a gif- template. you can switch the order of those resolvers to specify one extension taking precendence over the other. the common use case in myghty is looking for .py, which gives you a ModuleComponent, or .myt or another file-based extension which gives you a FileComponent. ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Standardized template API
One specific concern about the returning the published object for publisher-based frameworks is that often the published object has references to other objects that might not make sense in the context of the thread handling the rendering of the template. For example, if you're using a thread pool behind a Twisted server, and the thing doing the rendering is in the main thread, methods hanging off of the published object might try to make use of thread-local storage, which would fail. Zope 3 uses thread-local storage for request objects, IIRC. This might be a nonissue, because I'm a little fuzzy on which component(s) actually do(es) the rendering of the template in the models being proposed. But the amount of fuzziness I have about what's trying to be specified here makes me wonder if there aren't better things to go specify. As I mentioned in my counter-proposal, there should probably be a key like 'wti.source' to contain either the object to be published (for publisher-oriented frameworks) or a dictionary of variables (for controller-oriented frameworks). I originally called it published object, but that's biased towards publisher frameworks so perhaps a more neutral name like 'source' or 'data' would be more appropriate. ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Standardized template API
Phillip J. Eby wrote: My criteria is that it would be easy to implement Phillip's proposal in terms of mine (and I could provide a sample implementation of that if it would help), but it doesn't seem so easy to do the opposite. Actually, I believe you've got that backwards. Many things the WSGI embedding proposal can do, yours can't do *at all*, no matter how much programming you do. vars'n'strings isn't a substitute for WSGI, but it's easy to piggyback other payloads *out* of WSGI using file_wrapper-like APIs or dual-use objects with __call__ methods. What exactly can't I do with a WSGI application (a specific implementation) that uses the non-WSGI plugin API? For instance, there's no way for a Cheetah template to extend a WSGI application. It can extend other Cheetah templates, and even other Python classes, but not a WSGI app. Provide extension APIs to allow finding other templates. Putting them in this context also helps make it clear that such APIs aren't -- and *can't* be -- universal, because the templates themselves aren't heterogeneous. You can't give a Cheetah template a Kid subtemplate. My API always indicates the type of object you are looking for, though that may be too strict, as you don't *always* want to have a single type. Though if there is a defined exception when a resource can't be found, maybe that could be handled at a higher level than find_resource. I'd prefer to take up template finding in the context of a resource deployment proposal, where I think we can get a lot more leverage. But if it enables needed use cases today, I could get behind providing a simple -- and *optional* -- template finding API as part of the WSGI template/resource proposal, especially if discussing it helps lay the groundwork for the resource deployment proposal. It's up to you to handle that in your application. So you might pass in the WSGI environment as some variable, or the specific header, or you might select a template based on that header. You're presuming a controller-based architecture here, not an object-publishing one or a PHP/ASP style active pages one. That's ignoring what, maybe half the web frameworks? object-publishing is a subset of controller-based frameworks, where there is a single controller known as the object publisher. In an active page model the controller is the framework (insofar as you want to project MVC terminology onto such systems). Here's a rough WSGI implementation of active pages using the resource spec: class TemplateApp(object): def __init__(self, find_resource, ext_to_plugin, index_name, default_ext): self.find_resource = find_resource # a dictionary of extensions to instantiated plugins: self.ext_to_plugin = ext_to_plugin self.index_name = index_name self.default_ext = default_ext def __call__(self, environ, start_response): # actually empty path_info should cause a redirect... path_info = environ.get('PATH_INFO', '/') if path_info.endswith('/'): path_info += self.index_name parts = path_info.rsplit('.', 1) if len(parts) == 1: ext = self.default_ext resource_name = path_info + ext else: ext = '.'+parts[1] resource_name = path_info plugin = self.ext_to_plugin[ext] environ['response.headers'] = {'Content-type': 'text/html'} resource = self.find_resource(plugin, resource_name) body = response.plugin.render(resource, {'environ': environ}) start_response('200 OK', environ['response.headers'].items()) return [body] There's a bunch of sloppy WSGI constructs, and the environment isn't a great request object, but that's not really the point. -- Ian Bicking / [EMAIL PROTECTED] / http://blog.ianbicking.org ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Standardized template API
On Wed, Feb 01, 2006 at 05:15:26PM -0500, Phillip J. Eby wrote: | The template doesn't get to control the status or headers if all it | can do is return is a string. WSGI the hammer! Must we necessarly have a nail here? I think what's missing in this discussion is that templates are often used to build but a small part of an result; a left toolbar, a menu, perhaps even a row in a table -- but no more. I think that the requirements and design constraints involved make them so different from full-fledged WSGI applications/filters that even thinking about them in WSGI terms isn't helpful. That said, I do like the idea of passing templates a WSGI ``environ`` in addition to the input data that they should render; however, everything else in WSGI doesn't seem particularly applicable. The composition patterns are completely different. Best, Clark ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Standardized template API
At 05:42 PM 2/1/2006 -0500, Clark C. Evans wrote: | The template doesn't get to control the status or headers if all it | can do is return is a string. WSGI the hammer! Must we necessarly have a nail here? Who's we? Strings don't meet *my* use cases, or those of other template system and application developers who are not necessarily here to defend themselves against the promulgation of a standard that will exclude or marginalize them, or who have been here but haven't figured out yet how the exclusion will affect them, or what opportunities will be lost by going down this road. (Or who have already given up and left, as it appears Jim may have done, though it's also likely he's just busy at the moment.) Anyway, for the we that I'm a member of, yes, there is definitely a nail. I think what's missing in this discussion is that templates are often used to build but a small part of an result; a left toolbar, a menu, perhaps even a row in a table -- but no more. Actually, I've explicitly covered this in my most recent messages, even giving an example of a templating system that already supports dual usage of page and fragment modes, where the page mode is more like WSGI and the fragment mode is more like strings for the *same* template, so it can be used as a page *or* in embedded form. I think that the requirements and design constraints involved make them so different from full-fledged WSGI applications/filters that even thinking about them in WSGI terms isn't helpful. Neither is it harmful. I'm not proposing that subtemplates be required to use WSGI, simply because most templating systems don't offer much heterogeneity in what their subtemplates can consist of, especially for layouts (macros in ZPT terms, or template inheritance in many other systems' terms). But, going the opposite way, to string-centrism, *will* be harmful. Even the example of PHP or ASP should be sufficient to show that some templates *need* to have the option of controlling their response. A standard that ignored this would clearly be broken. I'm beginning to think that I'm going to have to come up with a better metaphor to explain what I'm seeing here. Focusing on plugging string templates and aggregation is like trying to design a standard for USB-based power when we don't have *wall current yet*. Sure, it's nice for powering all your little mice and keyboards and such, but you're never going to be able to plug a dishwasher into it. You can always transform *down* from wall current to run a peripheral, or to power a USB hub, but if all you have is USB power, everybody who needs household appliances is out of luck. Ergo, it makes more sense to standardize wall current (WSGI embedding) *first*, and then move down to more fine-grained concerns like powering USB hubs (sub-template linkage in homogeneous or heterogeneous template systems). So far, the whole of the arguments presented *against* the WSGI embedding approach seem to be that I've proposed something that has *too much* ability. What a lousy no-good person I am, proposing things that accomplish more and allow more templating systems to participate in the standard. Shame on me! ;) Seriously, though, does anybody have any arguments against WSGI embedding *besides* it requiring a little extra wrapping in certain subtemplate scenarios? Anything that stacks up against the huge list of benefits it offers? Does anybody believe they have a way to support response control from templates without a kludged-on convention that's not part of the standard, and isn't just another WSGI in sheep's clothing? C'mon guys, where's the shooting down of my ideas that y'all promised? ;) ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com
Re: [Web-SIG] Standardized template API
On 2/2/06, Phillip J. Eby [EMAIL PROTECTED] wrote: C'mon guys, where's the shooting down of my ideas that y'all promised? ;) Bang. ___ Web-SIG mailing list Web-SIG@python.org Web SIG: http://www.python.org/sigs/web-sig Unsubscribe: http://mail.python.org/mailman/options/web-sig/archive%40mail-archive.com