annotate genshi/template/loader.py @ 966:570226c48119 trunk

Templates should be loaded as bytes -- the encoding is passed around with the source explicitly. Fixes bugs in test suite in Python 3.3.
author hodgestar
date Sat, 29 Dec 2012 19:12:14 +0000
parents bef1e8701e79
children
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 #
897
64f04a2c5e66 Update changelog and copyright years.
cmlenz
parents: 876
diff changeset
3 # Copyright (C) 2006-2010 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
773
e01c9ad52f09 Export the template loader factory functions from the `loader` module.
cmlenz
parents: 769
diff changeset
25 __all__ = ['TemplateLoader', 'TemplateNotFound', 'directory', 'package',
e01c9ad52f09 Export the template loader factory functions from the `loader` module.
cmlenz
parents: 769
diff changeset
26 'prefixed']
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
27 __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
28
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
29
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
30 class TemplateNotFound(TemplateError):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
31 """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
32
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
33 def __init__(self, name, search_path):
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
34 """Create the exception.
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
35
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
36 :param name: the filename of the template
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
37 :param search_path: the search path used to lookup the template
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
38 """
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
39 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
40 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
41
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
42
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
43 class TemplateLoader(object):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
44 """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
45 path.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
46
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
47 >>> import tempfile
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
48 >>> fd, path = tempfile.mkstemp(suffix='.html', prefix='template')
935
59463031d904 Merge r1143 from py3k:
hodgestar
parents: 897
diff changeset
49 >>> os.write(fd, u'<p>$var</p>'.encode('utf-8'))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
50 11
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
51 >>> os.close(fd)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
52
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
53 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
54 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
55
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
56 >>> 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
57
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
58 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
59 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
60 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
61
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
62 >>> 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
63 >>> 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
64 >>> isinstance(template, MarkupTemplate)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
65 True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
66
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
67 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
68 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
69
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
70 >>> 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
71 True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
72
548
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
73 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
74 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
75 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
76
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
77 >>> os.remove(path)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
78 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
79 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
80 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
81 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
82 """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
83
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
84 :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
85 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
86 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
87 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
88 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
89 metadata
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
90 :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
91 template files, and reload them if they have changed
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
92 :param default_encoding: the default encoding to assume when loading
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
93 templates; defaults to UTF-8
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
94 :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
95 cache
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
96 :param default_class: the default `Template` subclass to use when
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
97 instantiating templates
606
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
98 :param variable_lookup: the variable lookup mechanism; either "strict"
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
99 (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
100 class
545
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
101 :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
102 :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
103 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
104 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
105 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
106 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
107 :see: `LenientLookup`, `StrictLookup`
545
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
108
619340e2d805 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
109 :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
110 """
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
111 from genshi.template.markup import MarkupTemplate
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
112
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
113 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
114 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
115 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
116 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
117 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
118
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
119 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
120 """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
121 changed"""
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
122
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
123 self.default_encoding = default_encoding
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
124 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
125 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
126 self.allow_exec = allow_exec
793
be88c77839fc Get rid of a couple more -3 warnings.
cmlenz
parents: 773
diff changeset
127 if callback is not None and not hasattr(callback, '__call__'):
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
128 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
129 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
130 self._cache = LRUCache(max_cache_size)
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
131 self._uptodate = {}
548
1cc1afc39176 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
132 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
133
876
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
134 def __getstate__(self):
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
135 state = self.__dict__.copy()
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
136 state['_lock'] = None
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
137 return state
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
138
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
139 def __setstate__(self, state):
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
140 self.__dict__ = state
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
141 self._lock = threading.RLock()
124b57282f81 Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents: 854
diff changeset
142
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
143 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
144 """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
145
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
146 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
147 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
148 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
149
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
150 If the requested template is not found, a `TemplateNotFound` exception
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
151 is raised. Otherwise, a `Template` object is returned that represents
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
152 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
153
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
154 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
155 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
156 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
157 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
158 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
159
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
160 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
161 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
162
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
163 :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
164 :param relative_to: the filename of the template from which the new
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
165 template is being loaded, or ``None`` if the
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
166 template is being loaded directly
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
167 :param cls: the class of the template object to instantiate
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
168 :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
169 ``default_encoding`` of the loader instance
435
be39660919a5 More API doc enhancements.
cmlenz
parents: 425
diff changeset
170 :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
171 :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
172 be found
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
173 """
363
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
174 if cls is None:
37e4b4bb0b53 Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
175 cls = self.default_class
769
3a59144a35b1 Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured. Closes #240.
cmlenz
parents: 721
diff changeset
176 search_path = self.search_path
3a59144a35b1 Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured. Closes #240.
cmlenz
parents: 721
diff changeset
177
3a59144a35b1 Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured. Closes #240.
cmlenz
parents: 721
diff changeset
178 # Make the filename relative to the template file its being loaded
3a59144a35b1 Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured. Closes #240.
cmlenz
parents: 721
diff changeset
179 # from, but only if that file is specified as a relative path, or no
3a59144a35b1 Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured. Closes #240.
cmlenz
parents: 721
diff changeset
180 # search path has been set up
3a59144a35b1 Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured. Closes #240.
cmlenz
parents: 721
diff changeset
181 if relative_to and (not search_path or not os.path.isabs(relative_to)):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
182 filename = os.path.join(os.path.dirname(relative_to), filename)
769
3a59144a35b1 Includes from templates loaded via an absolute path now include the correct file in nested directories as long if no search path has been configured. Closes #240.
cmlenz
parents: 721
diff changeset
183
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
184 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
185 cachekey = filename
336
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 self._lock.acquire()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
188 try:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
189 # 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
190 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
191 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
192 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
193 return tmpl
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
194 uptodate = self._uptodate[cachekey]
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
195 if uptodate is not None and uptodate():
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
196 return tmpl
721
e922f7190eea Properly wrap exceptions we want to catch.
jruigrok
parents: 719
diff changeset
197 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
198 pass
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 isabs = False
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
201
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
202 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
203 # 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
204 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
205 isabs = True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
206
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
207 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
208 # 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
209 # 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
210 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
211 if dirname not in search_path:
697
3d3c322ca978 Fix for #205.
cmlenz
parents: 696
diff changeset
212 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
213 isabs = True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
214
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
215 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
216 # 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
217 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
218
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
219 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
220 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
221 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
222 try:
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
223 filepath, filename, fileobj, uptodate = loadfunc(filename)
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
224 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
225 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
226 else:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
227 try:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
228 if isabs:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
229 # 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
230 # 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
231 # 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
232 # 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
233 # search path
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
234 filename = filepath
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
235 tmpl = self._instantiate(cls, fileobj, filepath,
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
236 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
237 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
238 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
239 self._cache[cachekey] = tmpl
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
240 self._uptodate[cachekey] = uptodate
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
241 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
242 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
243 fileobj.close()
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
244 return tmpl
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
245
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
246 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
247
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
248 finally:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
249 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
250
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
251 def _instantiate(self, cls, fileobj, filepath, filename, encoding=None):
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
252 """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
253 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
254
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 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
256 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
257 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
258
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 :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
260 :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
261 source
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
262 :param filepath: the absolute path to the template file
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
263 :param filename: the path to the template file relative to the search
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
264 path
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
265 :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
266 ``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
267 :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
268 :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
269 """
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
270 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
271 encoding = self.default_encoding
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
272 return cls(fileobj, filepath=filepath, filename=filename, loader=self,
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
273 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
274 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
275
822
70fddd2262f5 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 793
diff changeset
276 @staticmethod
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
277 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
278 """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
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 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
281 :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
282 :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
283 """
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 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
285 filepath = os.path.join(path, filename)
966
570226c48119 Templates should be loaded as bytes -- the encoding is passed around with the source explicitly. Fixes bugs in test suite in Python 3.3.
hodgestar
parents: 955
diff changeset
286 fileobj = open(filepath, 'rb')
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
287 mtime = os.path.getmtime(filepath)
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
288 def _uptodate():
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
289 return mtime == os.path.getmtime(filepath)
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
290 return filepath, filename, fileobj, _uptodate
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
291 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
292
822
70fddd2262f5 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 793
diff changeset
293 @staticmethod
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
294 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
295 """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
296
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 :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
298 :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
299 :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
300 :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
301 """
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 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
303 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
304 filepath = os.path.join(path, filename)
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
305 return filepath, filename, resource_stream(name, filepath), 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
306 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
307
822
70fddd2262f5 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 793
diff changeset
308 @staticmethod
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
309 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
310 """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
311 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
312
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 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
314 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
315
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
316 >>> load = prefixed(
698
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
317 ... 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
318 ... 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
319 ... )
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 822
diff changeset
320 >>> print(load('app1/foo.html'))
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
321 ('app1', 'app1/foo.html', None, None)
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 822
diff changeset
322 >>> print(load('app2/bar.html'))
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
323 ('app2', 'app2/bar.html', None, None)
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
324
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
325 :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
326 :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
327 :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
328 """
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
329 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
330 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
331 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
332 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
333 delegate = directory(delegate)
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
334 filepath, _, fileobj, uptodate = delegate(
698
408ab81767c7 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
335 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
336 )
714
fc6d9d2a3527 The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 699
diff changeset
337 return filepath, filename, fileobj, uptodate
854
4d9bef447df9 More work on reducing the size of the diff produced by 2to3.
cmlenz
parents: 853
diff changeset
338 raise TemplateNotFound(filename, list(delegates.keys()))
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
339 return _dispatch_by_prefix
822
70fddd2262f5 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 793
diff changeset
340
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
341
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
342 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
343 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
344 prefixed = TemplateLoader.prefixed
Copyright (C) 2012-2017 Edgewall Software