[svn] some api changes in the loader system regarding subclassing.
authorArmin Ronacher <armin.ronacher@active-4.com>
Mon, 19 Mar 2007 15:02:43 +0000 (16:02 +0100)
committerArmin Ronacher <armin.ronacher@active-4.com>
Mon, 19 Mar 2007 15:02:43 +0000 (16:02 +0100)
--HG--
branch : trunk

docs/src/loaders.txt
jinja/__init__.py
jinja/loaders.py

index 13c44eeac4ec759e4688bc97f78f9ffe54fc04e1..4522c35b379bce67f0f979465173225bc228eebe 100644 (file)
@@ -13,22 +13,21 @@ Developing Loaders
 ==================
 
 Template loaders are just normal Python classes that have to provide some
-functions used to load and translate templates.
+functions used to load and translate templates. Because some of the tasks
+a loader has to do are redundant there are some classes that make loader
+development easier.
 
-Because some of the tasks a loader has to do are redundant there are mixin
-classes that make loader development easier.
-
-Here the implementation of a simple loader based on the `LoaderMixin` from
+Here the implementation of a simple loader based on the `BaseLoader` from
 `jinja.loaders`:
 
 .. sourcecode:: python
 
     import codecs
     from os.path import join
-    from jinja.loaders import LoaderMixin
+    from jinja.loaders import BaseLoader
     from jinja.exceptions import TemplateNotFound
 
-    class SimpleLoader(LoaderMixin):
+    class SimpleLoader(BaseLoader):
         
         def __init__(self, path):
             self.path = path
@@ -44,21 +43,21 @@ Here the implementation of a simple loader based on the `LoaderMixin` from
                 f.close()
 
 The functions `load` and `parse` which are a requirement for a loader are
-added automatically by the `LoaderMixin`.
+added automatically by the `BaseLoader`.
 
-Additionally to the `LoaderMixin` there is a second mixin called
+Additionally to the `BaseLoader` there is a mixin class called
 `CachedLoaderMixin` that implements memory and disk caching of templates.
-
-It works basically the same, just that there are two more things to implement:
+Note that you have to give it a higher priority in the MRO than the
+`BaseLoader` which means that's the first base class when inheriting from it:
 
 .. sourcecode:: python
 
     import codecs
     from os.path import join, getmtime
-    from jinja.loaders import CachedLoaderMixin
+    from jinja.loaders import BaseLoaderCachedLoaderMixin
     from jinja.exceptions import TemplateNotFound
 
-    class CachedLoader(CachedLoaderMixin):
+    class CachedLoader(CachedLoaderMixin, BaseLoader):
         
         def __init__(self, path):
             self.path = path
index 9ee395a5a6826ab0834144b4a9bffd5ba690d994..cc60b4a83716f8336634f57dc2ed412ca203b745 100644 (file)
@@ -9,5 +9,4 @@
 from jinja.environment import Environment
 from jinja.loaders import *
 
-
 from_string = Environment().from_string
index 00d18f2d4bf0327398fe17a2374add3c315f1922..5642732c5cda51d058d327879557e7210a2095cd 100644 (file)
@@ -89,16 +89,16 @@ class LoaderWrapper(object):
         return self.loader is not None
 
 
-class LoaderMixin(object):
+class BaseLoader(object):
     """
     Use this class to implement loaders.
 
-    Just mixin this class and implement a method called `get_source`
-    with the signature (`environment`, `name`, `parent`) that returns
-    sourcecode for the template.
+    Just inherit from this class and implement a method called
+    `get_source` with the signature (`environment`, `name`, `parent`)
+    that returns sourcecode for the template.
 
     For more complex loaders you probably want to override `load` to
-    or not use the `LoaderMixin` at all.
+    or not use the `BaseLoader` at all.
     """
 
     def parse(self, environment, name, parent):
@@ -116,9 +116,9 @@ class LoaderMixin(object):
         return translator.process(environment, ast)
 
 
-class CachedLoaderMixin(LoaderMixin):
+class CachedLoaderMixin(object):
     """
-    Works like the loader mixin just that it supports caching.
+    Mixin this class to implement simple memory and disk caching.
     """
 
     def __init__(self, use_memcache, cache_size, cache_folder, auto_reload):
@@ -135,6 +135,13 @@ class CachedLoaderMixin(LoaderMixin):
         self.__lock = Lock()
 
     def load(self, environment, name, translator):
+        """
+        Load and translate a template. First we check if there is a
+        cached version of this template in the memory cache. If this is
+        not the cache check for a compiled template in the disk cache
+        folder. And if none of this is the case we translate the temlate
+        using the `LoaderMixin.load` function, cache and return it.
+        """
         self.__lock.acquire()
         try:
             # caching is only possible for the python translator. skip
@@ -177,8 +184,8 @@ class CachedLoaderMixin(LoaderMixin):
 
                     # no template so far, parse, translate and compile it
                     elif tmpl is None:
-                        tmpl = LoaderMixin.load(self, environment,
-                                                name, translator)
+                        tmpl = super(CachedLoaderMixin, self).load(
+                                     environment, name, translator)
 
                     # save the compiled template
                     f = file(cache_fn, 'wb')
@@ -196,12 +203,13 @@ class CachedLoaderMixin(LoaderMixin):
 
             # if we reach this point we don't have caching enabled or translate
             # to something else than python
-            return LoaderMixin.load(self, environment, name, translator)
+            return super(CachedLoaderMixin, self).load(
+                         environment, name, translator)
         finally:
             self.__lock.release()
 
 
-class FileSystemLoader(CachedLoaderMixin):
+class FileSystemLoader(CachedLoaderMixin, BaseLoader):
     """
     Loads templates from the filesystem:
 
@@ -256,7 +264,7 @@ class FileSystemLoader(CachedLoaderMixin):
         return path.getmtime(get_template_filename(self.searchpath, name))
 
 
-class PackageLoader(CachedLoaderMixin):
+class PackageLoader(CachedLoaderMixin, BaseLoader):
     """
     Loads templates from python packages using setuptools.
 
@@ -319,3 +327,25 @@ class PackageLoader(CachedLoaderMixin):
         name = '/'.join([self.package_path] + [p for p in name.split('/')
                         if p and p[0] != '.'])
         return path.getmtime(resource_filename(name))
+
+
+class DictLoader(BaseLoader):
+    """
+    Load templates from a given dict:
+
+    .. sourcecode:: python
+
+        from jinja import Environment, DictLoader
+        e = Environment(loader=DictLoader(dict(
+            layout='...',
+            index='{% extends layout %}...'
+        )))
+    """
+
+    def __init__(self, templates):
+        self.templates = templates
+
+    def get_source(self, environment, name, parent):
+        if name in self.templates:
+            return self.templates[name]
+        raise TemplateNotFound(name)