Well, here's the proposal I had before, tweaked slightly. This is mostly like the TG/Buffet API, but with find_resource extracted. I realize this is the basis of the whole WSGI offshoot before, and maybe an API without that would be useful or easier to implement. But it would also be way more useful to me with a resource finding callback, and I know Kevin has also indicated he wants that feature in TG.
It *is* hard to implement find_resource and will likely require updates or monkeypatching of existing template systems, because they don't always expose the internal process of fetching some other template. The API is here: http://svn.pythonpaste.org/home/ianb/templateapi/interface.py and copied below: """ These interfaces represent two sides of a resource-fetching implementation. ``IFindResource`` is meant to be implemented by the framework, and can implement things like search paths. ``IResourceType`` produces resources. Major open issues: * Where does caching occur? What are the promises we can make about caching? How can we know about the dependencies between templates, so we know when a template has to be recompiled because something it depends upon has been recompiled? * How will this really be used for non-template resources? Most immediately important is media files like CSS files, which are often changed in concert with template changes, but are usually just static. * Should the expected output type be separate from the expected input type? Right now IResourceType distinguishes template engines, but doesn't necessarily distinguish the expected mime type. Other questions are in [] in the docstrings below... """ class IResourceFinder: def __call__(resource_name, resource_type=None, relative_to_name=None, relative_to_object=None): """ Finds a resource by the given name. If this is being called *by* a resource, then both ``relative_to_name`` and ``relative_to_object`` should be given. The implementation of this callable is *not* part of a template plugin, but is something provided by the framework. This is only a callable; it could be created in such a way that it is bound to the current request in a web environment, or with any other implementation that seems appropriate. ``resource_name`` and ``relative_to_name`` are strings or unicode objects. ``relative_to_object`` is something that ``find_resource()`` itself returned. ``resource_type`` is the type of object we are looking for, an instance of IResourceType. If not given (or None) then this object should try to determine the type itself, possibly changing the name and calling itself recursively. [I think there should be some convention on what names should look like -- like filenames (with / separators), or like module names...? Should they include extensions?] """ class IResourceType: """ A kind of resource, like 'cheetah templates' or 'CSS files'. [Should this include some attribute with the mime type, extensions, name of the type, ...?] """ def load_resource(resource_name, find_resource, resource_stream, resource_location=None): """ Returns the resource. ``resource_name`` is an opaque identifier, but should be kept. ``find_resource`` is the implementation of ``IResourceFinder`` that is creating the resource. This same implementation should be used for any recursive resource fetching. The resource content is given in ``resource_stream``, a file-like object. [Does the caller close the file?] ``resource_location`` is a string identifier for the actual location of the resource. This might be a filename, or some other unambiguous representation of where the resource came from. This is meant for use in tracebacks or debugging, and is only meant to mean something to a human and is not used by the resource itself. """ class ITemplatePlugin(IResourceType): def __init__(extra_vars_func=None, options=None): """ Create a template plugin instance. ``extra_vars_func`` is a function that returns a dictionary of 'standard' variables for the environment. ``options`` is a dictionary of options for the template (e.g., compiler settings) with no defined contents. [Is ``extra_vars_func`` necessary? Couldn't it be handled by a wrapper around ``render``?] """ def load_resource(...): """ Return an instance of the template. No interface for the return value is defined, but the return value can be used with ``render``. Note that some templating languages don't work well with ``render``, so the returned resource may be the more useful interface, and frameworks should allow users to get at this return value directly. This value should typically be the 'native' template object for the template language. """ def render(template_instance, vars, format="html", fragment=False): """ Render the template instance (as returned by ``load_resource``) to a string or unicode object. [Should there be some way to return metadata about what was rendered, like the type of object being returned -- e.g., text/html or text/plain] ``vars`` is typically a dictionary (-like object) of variables for use in substitution. format may be 'xhtml', 'plain', 'elementtree' etc., but plugins may ignore that value. Depending on the value, the return value may not be a string. However, the caller should try to handle a string return value. For instance, if you ask for 'elementtree' and get a string response, you should be ready to call ``XML()`` on that string. [Should this optionally be a list of formats, in order of preference?] 'fragment' indicates if an incomplete document should be created (e.g., with no DOCTYPE); again templates may ignore this. """ _______________________________________________ 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