annotate genshi/template/loader.py @ 699:cfe3b4f02d77 trunk

Fix for caching in template loader for templates included by templates loaded from an absolute path. Closes #193. Thanks to Waldemar Kornewald for the test case.
author cmlenz
date Thu, 27 Mar 2008 14:49:06 +0000
parents 408ab81767c7
children fc6d9d2a3527
rev   line source
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
2 #
408
4675d5cf6c67 Update copyright year for files modified this year.
cmlenz
parents: 400
diff changeset
3 # Copyright (C) 2006-2007 Edgewall Software
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
4 # All rights reserved.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
5 #
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
9 #
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
13
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
14 """Template loading and caching."""
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
15
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
16 import os
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
17 try:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
18 import threading
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
19 except ImportError:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
20 import dummy_threading as threading
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
21
400
e29a94b3ba0c Renamed `genshi.template.core` to `genshi.template.base`, mainly to avoid confusion with `genshi.core`.
cmlenz
parents: 363
diff changeset
22 from genshi.template.base import TemplateError
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
23 from genshi.util import LRUCache
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
24
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
25 __all__ = ['TemplateLoader', 'TemplateNotFound']
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
26 __docformat__ = 'restructuredtext en'
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
27
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
29 class TemplateNotFound(TemplateError):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
30 """Exception raised when a specific template file could not be found."""
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
31
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
32 def __init__(self, name, search_path):
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
33 """Create the exception.
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
34
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
35 :param name: the filename of the template
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
36 :param search_path: the search path used to lookup the template
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
37 """
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
38 TemplateError.__init__(self, 'Template "%s" not found' % name)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
39 self.search_path = search_path
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
40
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
41
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
42 class TemplateLoader(object):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
43 """Responsible for loading templates from files on the specified search
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
44 path.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
45
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
46 >>> import tempfile
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
47 >>> fd, path = tempfile.mkstemp(suffix='.html', prefix='template')
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
48 >>> os.write(fd, '<p>$var</p>')
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
49 11
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
50 >>> os.close(fd)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
51
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
52 The template loader accepts a list of directory paths that are then used
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
53 when searching for template files, in the given order:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
54
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
55 >>> loader = TemplateLoader([os.path.dirname(path)])
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
56
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
57 The `load()` method first checks the template cache whether the requested
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
58 template has already been loaded. If not, it attempts to locate the
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
59 template file, and returns the corresponding `Template` object:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
60
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
61 >>> from genshi.template import MarkupTemplate
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
62 >>> template = loader.load(os.path.basename(path))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
63 >>> isinstance(template, MarkupTemplate)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
64 True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
65
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
66 Template instances are cached: requesting a template with the same name
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
67 results in the same instance being returned:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
68
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
69 >>> loader.load(os.path.basename(path)) is template
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
70 True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
71
548
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
72 The `auto_reload` option can be used to control whether a template should
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
73 be automatically reloaded when the file it was loaded from has been
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
74 changed. Disable this automatic reloading to improve performance.
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
75
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
76 >>> os.remove(path)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
77 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
78 def __init__(self, search_path=None, auto_reload=False,
439
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
79 default_encoding=None, max_cache_size=25, default_class=None,
606
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
80 variable_lookup='strict', allow_exec=True, callback=None):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
81 """Create the template laoder.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
82
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
83 :param search_path: a list of absolute path names that should be
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
84 searched for template files, or a string containing
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
85 a single absolute path; alternatively, any item on
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
86 the list may be a ''load function'' that is passed
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
87 a filename and returns a file-like object and some
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
88 metadata
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
89 :param auto_reload: whether to check the last modification time of
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
90 template files, and reload them if they have changed
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
91 :param default_encoding: the default encoding to assume when loading
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
92 templates; defaults to UTF-8
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
93 :param max_cache_size: the maximum number of templates to keep in the
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
94 cache
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
95 :param default_class: the default `Template` subclass to use when
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
96 instantiating templates
606
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
97 :param variable_lookup: the variable lookup mechanism; either "strict"
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
98 (the default), "lenient", or a custom lookup
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 439
diff changeset
99 class
545
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
100 :param allow_exec: whether to allow Python code blocks in templates
439
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
101 :param callback: (optional) a callback function that is invoked after a
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
102 template was initialized by this loader; the function
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
103 is passed the template object as only argument. This
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
104 callback can be used for example to add any desired
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
105 filters to the template
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 439
diff changeset
106 :see: `LenientLookup`, `StrictLookup`
545
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
107
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
108 :note: Changed in 0.5: Added the `allow_exec` argument
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
109 """
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
110 from genshi.template.markup import MarkupTemplate
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
111
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
112 self.search_path = search_path
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
113 if self.search_path is None:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
114 self.search_path = []
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
115 elif not isinstance(self.search_path, (list, tuple)):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
116 self.search_path = [self.search_path]
548
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
117
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
118 self.auto_reload = auto_reload
548
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
119 """Whether templates should be reloaded when the underlying file is
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
120 changed"""
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
121
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
122 self.default_encoding = default_encoding
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
123 self.default_class = default_class or MarkupTemplate
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 439
diff changeset
124 self.variable_lookup = variable_lookup
545
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
125 self.allow_exec = allow_exec
439
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
126 if callback is not None and not callable(callback):
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
127 raise TypeError('The "callback" parameter needs to be callable')
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
128 self.callback = callback
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
129 self._cache = LRUCache(max_cache_size)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
130 self._mtime = {}
548
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
131 self._lock = threading.RLock()
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
132
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
133 def load(self, filename, relative_to=None, cls=None, encoding=None):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
134 """Load the template with the given name.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
135
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
136 If the `filename` parameter is relative, this method searches the
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
137 search path trying to locate a template matching the given name. If the
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
138 file name is an absolute path, the search path is ignored.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
139
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
140 If the requested template is not found, a `TemplateNotFound` exception
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
141 is raised. Otherwise, a `Template` object is returned that represents
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
142 the parsed template.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
143
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
144 Template instances are cached to avoid having to parse the same
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
145 template file more than once. Thus, subsequent calls of this method
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
146 with the same template file name will return the same `Template`
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
147 object (unless the ``auto_reload`` option is enabled and the file was
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
148 changed since the last parse.)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
149
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
150 If the `relative_to` parameter is provided, the `filename` is
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
151 interpreted as being relative to that path.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
152
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
153 :param filename: the relative path of the template file to load
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
154 :param relative_to: the filename of the template from which the new
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
155 template is being loaded, or ``None`` if the
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
156 template is being loaded directly
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
157 :param cls: the class of the template object to instantiate
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
158 :param encoding: the encoding of the template to load; defaults to the
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
159 ``default_encoding`` of the loader instance
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
160 :return: the loaded `Template` instance
695
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
161 :raises TemplateNotFound: if a template with the given name could not
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
162 be found
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
163 """
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
164 if cls is None:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
165 cls = self.default_class
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
166 if relative_to and not os.path.isabs(relative_to):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
167 filename = os.path.join(os.path.dirname(relative_to), filename)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
168 filename = os.path.normpath(filename)
699
cfe3b4f02d77 Fix for caching in template loader for templates included by templates loaded from an absolute path. Closes #193. Thanks to Waldemar Kornewald for the test case.
cmlenz
parents: 698
diff changeset
169 cachekey = filename
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
170
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
171 self._lock.acquire()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
172 try:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
173 # First check the cache to avoid reparsing the same file
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
174 try:
699
cfe3b4f02d77 Fix for caching in template loader for templates included by templates loaded from an absolute path. Closes #193. Thanks to Waldemar Kornewald for the test case.
cmlenz
parents: 698
diff changeset
175 tmpl = self._cache[cachekey]
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
176 if not self.auto_reload:
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
177 return tmpl
699
cfe3b4f02d77 Fix for caching in template loader for templates included by templates loaded from an absolute path. Closes #193. Thanks to Waldemar Kornewald for the test case.
cmlenz
parents: 698
diff changeset
178 mtime = self._mtime[cachekey]
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
179 if mtime and mtime == os.path.getmtime(tmpl.filepath):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
180 return tmpl
590
36b5a03534a0 Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents: 548
diff changeset
181 except KeyError, OSError:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
182 pass
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
183
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
184 search_path = self.search_path
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
185 isabs = False
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
186
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
187 if os.path.isabs(filename):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
188 # Bypass the search path if the requested filename is absolute
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
189 search_path = [os.path.dirname(filename)]
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
190 isabs = True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
191
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
192 elif relative_to and os.path.isabs(relative_to):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
193 # Make sure that the directory containing the including
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
194 # template is on the search path
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
195 dirname = os.path.dirname(relative_to)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
196 if dirname not in search_path:
697
3d3c322ca978 Fix for #205.
cmlenz
parents: 696
diff changeset
197 search_path = list(search_path) + [dirname]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
198 isabs = True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
199
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
200 elif not search_path:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
201 # Uh oh, don't know where to look for the template
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
202 raise TemplateError('Search path for templates not configured')
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
203
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
204 for loadfunc in search_path:
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
205 if isinstance(loadfunc, basestring):
698
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
206 loadfunc = directory(loadfunc)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
207 try:
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
208 dirname, filename, fileobj, mtime = loadfunc(filename)
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
209 except IOError:
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
210 continue
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
211 else:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
212 try:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
213 if isabs:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
214 # If the filename of either the included or the
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
215 # including template is absolute, make sure the
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
216 # included template gets an absolute path, too,
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
217 # so that nested includes work properly without a
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
218 # search path
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
219 filename = os.path.join(dirname, filename)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
220 dirname = ''
695
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
221 tmpl = self.instantiate(cls, fileobj, dirname,
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
222 filename, encoding=encoding)
439
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
223 if self.callback:
9f11c745fac9 Add support for adding custom template filters by passing a custom callback function to the `TemplateLoader`. Closes #89 (see added unit test).
cmlenz
parents: 435
diff changeset
224 self.callback(tmpl)
699
cfe3b4f02d77 Fix for caching in template loader for templates included by templates loaded from an absolute path. Closes #193. Thanks to Waldemar Kornewald for the test case.
cmlenz
parents: 698
diff changeset
225 self._cache[cachekey] = tmpl
cfe3b4f02d77 Fix for caching in template loader for templates included by templates loaded from an absolute path. Closes #193. Thanks to Waldemar Kornewald for the test case.
cmlenz
parents: 698
diff changeset
226 self._mtime[cachekey] = mtime
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
227 finally:
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
228 if hasattr(fileobj, 'close'):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
229 fileobj.close()
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
230 return tmpl
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
231
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
232 raise TemplateNotFound(filename, search_path)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
233
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
234 finally:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
235 self._lock.release()
695
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
236
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
237 def instantiate(self, cls, fileobj, dirname, filename, encoding=None):
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
238 """Instantiate and return the `Template` object based on the given
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
239 class and parameters.
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
240
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
241 This function is intended for subclasses to override if they need to
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
242 implement special template instantiation logic. Code that just uses
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
243 the `TemplateLoader` should use the `load` method instead.
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
244
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
245 :param cls: the class of the template object to instantiate
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
246 :param fileobj: a readable file-like object containing the template
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
247 source
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
248 :param dirname: the name of the base directory containing the template
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
249 file
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
250 :param filename: the name of the template file, relative to the given
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
251 base directory
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
252 :param encoding: the encoding of the template to load; defaults to the
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
253 ``default_encoding`` of the loader instance
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
254 :return: the loaded `Template` instance
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
255 :rtype: `Template`
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
256 """
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
257 if encoding is None:
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
258 encoding = self.default_encoding
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
259 return cls(fileobj, basedir=dirname, filename=filename, loader=self,
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
260 encoding=encoding, lookup=self.variable_lookup,
ed5044d318ed The `TemplateLoader` class now provides an `instantiate()` method that can be overridden by subclasses to implement advanced template instantiation logic. Fixes #204.
cmlenz
parents: 606
diff changeset
261 allow_exec=self.allow_exec)
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
262
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
263 def directory(path):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
264 """Loader factory for loading templates from a local directory.
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
265
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
266 :param path: the path to the local directory containing the templates
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
267 :return: the loader function to load templates from the given directory
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
268 :rtype: ``function``
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
269 """
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
270 def _load_from_directory(filename):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
271 filepath = os.path.join(path, filename)
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
272 fileobj = open(filepath, 'U')
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
273 return path, filename, fileobj, os.path.getmtime(filepath)
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
274 return _load_from_directory
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
275 directory = staticmethod(directory)
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
276
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
277 def package(name, path):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
278 """Loader factory for loading templates from egg package data.
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
279
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
280 :param name: the name of the package containing the resources
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
281 :param path: the path inside the package data
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
282 :return: the loader function to load templates from the given package
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
283 :rtype: ``function``
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
284 """
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
285 from pkg_resources import resource_stream
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
286 def _load_from_package(filename):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
287 filepath = os.path.join(path, filename)
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
288 return path, filename, resource_stream(name, filepath), None
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
289 return _load_from_package
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
290 package = staticmethod(package)
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
291
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
292 def prefixed(**delegates):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
293 """Factory for a load function that delegates to other loaders
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
294 depending on the prefix of the requested template path.
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
295
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
296 The prefix is stripped from the filename when passing on the load
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
297 request to the delegate.
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
298
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
299 >>> load = prefixed(
698
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
300 ... app1 = lambda filename: ('app1', filename, None, None),
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
301 ... app2 = lambda filename: ('app2', filename, None, None)
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
302 ... )
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
303 >>> print load('app1/foo.html')
698
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
304 ('', 'app1/foo.html', None, None)
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
305 >>> print load('app2/bar.html')
698
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
306 ('', 'app2/bar.html', None, None)
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
307
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
308 :param delegates: mapping of path prefixes to loader functions
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
309 :return: the loader function
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
310 :rtype: ``function``
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
311 """
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
312 def _dispatch_by_prefix(filename):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
313 for prefix, delegate in delegates.items():
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
314 if filename.startswith(prefix):
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
315 if isinstance(delegate, basestring):
698
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
316 delegate = directory(delegate)
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
317 path, _, fileobj, mtime = delegate(
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
318 filename[len(prefix):].lstrip('/\\')
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
319 )
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
320 dirname = path[len(prefix):].rstrip('/\\')
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
321 return dirname, filename, fileobj, mtime
696
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
322 raise TemplateNotFound(filename, delegates.keys())
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
323 return _dispatch_by_prefix
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
324 prefixed = staticmethod(prefixed)
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
325
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
326 directory = TemplateLoader.directory
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
327 package = TemplateLoader.package
66eead58c120 More flexible template loader allowing for loading from package data and dispatching to different template directories based on path prefix. Can be easily extended for using custom template loading. Closes #182.
cmlenz
parents: 695
diff changeset
328 prefixed = TemplateLoader.prefixed
Copyright (C) 2012-2017 Edgewall Software