From 2165ce64ea867fd20c2b3cfd0a7e385701020e44 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sat, 2 Jun 2007 12:12:56 +0200 Subject: [PATCH] [svn] made jinja platform depending and adedd manifest for the built documentation. Improved loader documentation --HG-- branch : trunk --- MANIFEST.in | 1 + docs/src/loaders.txt | 103 +++++++++++++++++++++++++++++++++++++++++-- jinja/environment.py | 13 +++--- setup.py | 1 - 4 files changed, 108 insertions(+), 10 deletions(-) create mode 100644 MANIFEST.in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..69083cd --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1 @@ +include docs/build/*.html diff --git a/docs/src/loaders.txt b/docs/src/loaders.txt index 306b14d..18a8fbd 100644 --- a/docs/src/loaders.txt +++ b/docs/src/loaders.txt @@ -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. diff --git a/jinja/environment.py b/jinja/environment.py index 91cd2a5..034d092 100644 --- a/jinja/environment.py +++ b/jinja/environment.py @@ -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: diff --git a/setup.py b/setup.py index a0be447..456a5b9 100644 --- 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 -- 2.26.2