[svn] made jinja platform depending and adedd manifest for the built documentation...
authorArmin Ronacher <armin.ronacher@active-4.com>
Sat, 2 Jun 2007 10:12:56 +0000 (12:12 +0200)
committerArmin Ronacher <armin.ronacher@active-4.com>
Sat, 2 Jun 2007 10:12:56 +0000 (12:12 +0200)
--HG--
branch : trunk

MANIFEST.in [new file with mode: 0644]
docs/src/loaders.txt
jinja/environment.py
setup.py

diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644 (file)
index 0000000..69083cd
--- /dev/null
@@ -0,0 +1 @@
+include docs/build/*.html
index 306b14ddebc59bc83ad0849ee2e92a05c7fe9838..18a8fbd2208a04f71f290603584b1abaa16cc6ac 100644 (file)
@@ -15,10 +15,11 @@ modification:
 Loader Baseclasses
 ==================
 
-With Jinja 1.1 onwards all the loaders have (except of the uncached) now have
-baseclasses you can use to mix your own caching layer in. This technique is
-explained below. The `BaseLoader` itself is also a loader baseclass but because
-it's the baseclass of each loader it's explained in detail below.
+With Jinja 1.1 onwards all the loaders have (except of the uncached)
+baseclasses. You can use them to mix your own caching layer in. This technique
+is described below. The `BaseLoader` itself is also a loader baseclass but
+because it's the baseclass of all loaders it's covered in the "Developing
+Loaders" section.
 
 [[list_of_baseloaders]]
 
@@ -144,3 +145,97 @@ for the `FunctionLoader`:
             )
 
 .. _memcached: http://www.danga.com/memcached/
+
+How Mixin Classes Work
+======================
+
+The idea of the cached loader mixins is that you override the `load`
+method of the other base class so that it's only called to get the data
+from the loader and put it into a cache and then bypass the original `load`.
+
+This works because mixin classes, as well as the loaders are so called "new
+style classes" with a MRO (method resolution order). So it's possible to
+access the parent without actually knowing the name of it.
+
+Here as small mixin class that stores everything after loading in a
+dict:
+
+.. sourcecode:: python
+
+    class SimpleCacheMixin(object):
+
+        def __init__(self):
+            self.__cache = {}
+
+        def load(self, environment, name, translator):
+            if name in self.__cache:
+                return self.__cache[name]
+            tmpl = super(SimpleCacheMixin, self).load(environment, name,
+                                                      translator)
+            self.__cache[name] = tmpl
+            return tmpl
+
+You can then mix the class in like any other mixin class. Note that
+all non public attributes **must** be prefixed with two underscores to
+enable the name mangling. Otherwise the mixin class could break the
+internal structure of the loader.
+
+The ``super(SimpleCacheMixin, self)`` call returns an object that looks
+up all the attributes you request in all the parent classes. The
+`SimpleCacheMixin` just has the `object` parent which makes it a new
+style class, but as soon as a loader is mixed in it will call the
+`load` method of the loader that is the other parent of the resulting
+class. Here a full example.
+
+Combining Everything
+====================
+
+Here a full example with a custom cache mixin and a custom base loader:
+
+.. sourcecode:: python
+
+    import codecs
+    from os.path import join
+    from jinja.loaders import BaseLoader
+    from jinja.exceptions import TemplateNotFound
+
+    class SimpleBaseLoader(BaseLoader):
+        
+        def __init__(self, path):
+            self.path = path
+
+        def get_source(self, environment, name, parent):
+            filename = join(self.path, name)
+            if not path.exists(filename):
+                raise TemplateNotFound(name)
+            f = codecs.open(filename, 'r', environment.template_charset)
+            try:
+                return f.read()
+            finally:
+                f.close()
+
+
+    class SimpleCacheMixin(object):
+
+        def __init__(self):
+            self.__cache = {}
+
+        def load(self, environment, name, translator):
+            if name in self.__cache:
+                return self.__cache[name]
+            tmpl = super(SimpleCacheMixin, self).load(environment, name,
+                                                      translator)
+            self.__cache[name] = tmpl
+            return tmpl
+
+
+    class SimpleLoader(SimpleBaseLoader, SimpleCacheMixin):
+
+        def __init__(self, path):
+            SimpleBaseLoader.__init__(self, path)
+            SimpleCacheMixin.__init__()
+
+You can of course put all the functionallity into the `SimpleLoader` but then
+you cannot exchange parts of it without rewriting much code. In the example
+above replacing the `SimpleCacheMixin` with a `MemcachedLoaderMixin` is a
+matter of 20 seconds.
index 91cd2a52fab4f05204fb986d3a6809122e661ff5..034d09287a2f709f0b3c5831fe61e03a1d975c72 100644 (file)
@@ -129,8 +129,12 @@ class Environment(object):
         self.template_charset = template_charset
         self.charset = charset
         self.loader = loader
-        self.filters = filters is None and DEFAULT_FILTERS.copy() or filters
-        self.tests = tests is None and DEFAULT_TESTS.copy() or tests
+        if filters is None:
+            filters = DEFAULT_FILTERS.copy()
+        self.filters = filters
+        if tests is None:
+            tests = DEFAULT_TESTS.copy()
+        self.tests = tests
         self.default_filters = default_filters or []
         self.context_class = context_class
         self.undefined_singleton = undefined_singleton
@@ -138,9 +142,8 @@ class Environment(object):
 
         # global namespace
         if namespace is None:
-            self.globals = DEFAULT_NAMESPACE.copy()
-        else:
-            self.globals = namespace
+            namespace = DEFAULT_NAMESPACE.copy()
+        self.globals = namespace
 
         # jinja 1.0 compatibility
         if auto_escape:
index a0be447d49ecb53b289e35de1563f4676b72274c..456a5b9975fd49c7a7d3be8f93cb8f806c67c866 100644 (file)
--- a/setup.py
+++ b/setup.py
@@ -73,7 +73,6 @@ setup(
         ('docs', list(list_files('docs/build'))),
         ('docs/txt', list(list_files('docs/src')))
     ],
-    platforms = 'any',
     entry_points='''
     [python.templating.engines]
     jinja = jinja.plugin:BuffetPlugin