annotate genshi/template/loader.py @ 935:705727288d7e

Merge r1143 from py3k: add support for python 3 to remaining genshi.template components: * minor changes to track encoding=None API change in core genshi modules. * genshi/template/directives: * slightly odd syntax changes to make the 2to3 .next() fixer pick up *stream.next() * minor test fix for change in behaviour of division (/) in Python 3. * genshi/template/loader: * add 'b' to file modes to ensure it's loaded as bytes in Python 3. * use not isinstance(s, unicode) instead of isinstance(s, str) since the former is correctly converted by 2to3.
author hodgestar
date Fri, 18 Mar 2011 09:17:52 +0000
parents 85e4678337cf
children
rev   line source
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
2 #
897
85e4678337cf Update changelog and copyright years.
cmlenz
parents: 876
diff changeset
3 # Copyright (C) 2006-2010 Edgewall Software
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
4 # All rights reserved.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
5 #
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
9 #
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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/.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
13
5f2c7782cd8a 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."""
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
15
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
16 import os
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
17 try:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
18 import threading
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
19 except ImportError:
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
21
400
8dd0d34a9fb7 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
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
24
773
b555a6769c5b Export the template loader factory functions from the `loader` module.
cmlenz
parents: 769
diff changeset
25 __all__ = ['TemplateLoader', 'TemplateNotFound', 'directory', 'package',
b555a6769c5b Export the template loader factory functions from the `loader` module.
cmlenz
parents: 769
diff changeset
26 'prefixed']
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
27 __docformat__ = 'restructuredtext en'
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
29
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
30 class TemplateNotFound(TemplateError):
5f2c7782cd8a 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."""
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
32
5f2c7782cd8a 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
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
34 """Create the exception.
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
35
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
36 :param name: the filename of the template
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
37 :param search_path: the search path used to lookup the template
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
38 """
336
5f2c7782cd8a 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)
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
41
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
42
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
43 class TemplateLoader(object):
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
45 path.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
46
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
47 >>> import tempfile
5f2c7782cd8a 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
705727288d7e Merge r1143 from py3k:
hodgestar
parents: 897
diff changeset
49 >>> os.write(fd, u'<p>$var</p>'.encode('utf-8'))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
50 11
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
51 >>> os.close(fd)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
52
5f2c7782cd8a 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
55
5f2c7782cd8a 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)])
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
57
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
61
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
62 >>> from genshi.template import MarkupTemplate
336
5f2c7782cd8a 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))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
64 >>> isinstance(template, MarkupTemplate)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
65 True
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
66
5f2c7782cd8a 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
69
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
71 True
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
72
548
c2e039c7e439 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
c2e039c7e439 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
c2e039c7e439 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.
c2e039c7e439 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
76
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
77 >>> os.remove(path)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
78 """
5f2c7782cd8a 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
b84c11a49ad2 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
9ada030ad986 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
81 variable_lookup='strict', allow_exec=True, callback=None):
336
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
83
425
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
85 searched for template files, or a string containing
696
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
91 template files, and reload them if they have changed
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
92 :param default_encoding: the default encoding to assume when loading
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
93 templates; defaults to UTF-8
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
95 cache
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
96 :param default_class: the default `Template` subclass to use when
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
97 instantiating templates
606
9ada030ad986 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
98 :param variable_lookup: the variable lookup mechanism; either "strict"
9ada030ad986 Changed the default error handling mode to "strict".
cmlenz
parents: 590
diff changeset
99 (the default), "lenient", or a custom lookup
442
ff7c72b52fb2 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
6e21c89d9255 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
b84c11a49ad2 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
b84c11a49ad2 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
b84c11a49ad2 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
b84c11a49ad2 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
b84c11a49ad2 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
ff7c72b52fb2 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
6e21c89d9255 Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents: 442
diff changeset
108
6e21c89d9255 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
110 """
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
111 from genshi.template.markup import MarkupTemplate
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
112
336
5f2c7782cd8a 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
5f2c7782cd8a 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:
5f2c7782cd8a 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
87b8e23610d4 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
5f2c7782cd8a 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
c2e039c7e439 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
118
336
5f2c7782cd8a 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
c2e039c7e439 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
c2e039c7e439 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
121 changed"""
c2e039c7e439 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
122
336
5f2c7782cd8a 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
caf7b68ab5dc 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
ff7c72b52fb2 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
6e21c89d9255 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
7cf2407671c2 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
b84c11a49ad2 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')
b84c11a49ad2 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
5f2c7782cd8a 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
7e6496bde18a 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
c2e039c7e439 Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents: 545
diff changeset
132 self._lock = threading.RLock()
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
133
876
52d7d6b7b6c1 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):
52d7d6b7b6c1 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()
52d7d6b7b6c1 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
52d7d6b7b6c1 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
52d7d6b7b6c1 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
52d7d6b7b6c1 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):
52d7d6b7b6c1 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
52d7d6b7b6c1 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()
52d7d6b7b6c1 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
caf7b68ab5dc 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
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
145
696
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
149
435
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
150 If the requested template is not found, a `TemplateNotFound` exception
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
151 is raised. Otherwise, a `Template` object is returned that represents
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
152 the parsed template.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
153
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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
5b248708bbed 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
5f2c7782cd8a 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.)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
159
5f2c7782cd8a 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
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
162
425
5b248708bbed 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
5b248708bbed 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
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
165 template is being loaded, or ``None`` if the
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
166 template is being loaded directly
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
167 :param cls: the class of the template object to instantiate
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 408
diff changeset
169 ``default_encoding`` of the loader instance
435
7800a61eae43 More API doc enhancements.
cmlenz
parents: 425
diff changeset
170 :return: the loaded `Template` instance
695
3d11d6b1d3d4 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
3d11d6b1d3d4 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
173 """
363
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
174 if cls is None:
caf7b68ab5dc Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents: 336
diff changeset
175 cls = self.default_class
769
834e8fd2d822 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
834e8fd2d822 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
834e8fd2d822 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
834e8fd2d822 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
834e8fd2d822 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
834e8fd2d822 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
5f2c7782cd8a 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
834e8fd2d822 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
5f2c7782cd8a 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
1f08da62e8fd 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
186
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
187 self._lock.acquire()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
188 try:
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
190 try:
699
1f08da62e8fd 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
87b8e23610d4 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:
87b8e23610d4 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
7e6496bde18a 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]
7e6496bde18a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
196 return tmpl
721
15c31c0e0df4 Properly wrap exceptions we want to catch.
jruigrok
parents: 719
diff changeset
197 except (KeyError, OSError):
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
198 pass
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
199
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
200 isabs = False
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
201
5f2c7782cd8a 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):
5f2c7782cd8a 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
5f2c7782cd8a 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)]
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
205 isabs = True
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
206
5f2c7782cd8a 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):
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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)
5f2c7782cd8a 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
6f402009e953 Fix for #205.
cmlenz
parents: 696
diff changeset
212 search_path = list(search_path) + [dirname]
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
213 isabs = True
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
214
5f2c7782cd8a 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:
5f2c7782cd8a 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
5f2c7782cd8a 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')
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
218
696
87b8e23610d4 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:
87b8e23610d4 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
654e1d1b3953 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
222 try:
714
7e6496bde18a 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
87b8e23610d4 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:
87b8e23610d4 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
87b8e23610d4 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
227 try:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
228 if isabs:
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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
87b8e23610d4 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
233 # search path
714
7e6496bde18a 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
7e6496bde18a 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,
7e6496bde18a 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
b84c11a49ad2 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:
b84c11a49ad2 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
1f08da62e8fd 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
7e6496bde18a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
241 finally:
696
87b8e23610d4 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'):
87b8e23610d4 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
244 return tmpl
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
245
5f2c7782cd8a 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)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
247
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
248 finally:
5f2c7782cd8a 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
3d11d6b1d3d4 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
7e6496bde18a 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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.
3d11d6b1d3d4 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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.
3d11d6b1d3d4 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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
7e6496bde18a 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
7e6496bde18a 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
7e6496bde18a 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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
3d11d6b1d3d4 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`
3d11d6b1d3d4 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 """
3d11d6b1d3d4 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:
3d11d6b1d3d4 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
7e6496bde18a 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
3d11d6b1d3d4 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,
3d11d6b1d3d4 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
87b8e23610d4 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
ce5ad2d540b3 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
87b8e23610d4 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):
87b8e23610d4 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.
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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``
87b8e23610d4 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 """
87b8e23610d4 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):
87b8e23610d4 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)
935
705727288d7e Merge r1143 from py3k:
hodgestar
parents: 897
diff changeset
286 fileobj = open(filepath, 'rbU')
714
7e6496bde18a 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)
7e6496bde18a 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():
7e6496bde18a 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)
7e6496bde18a 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
87b8e23610d4 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
87b8e23610d4 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
ce5ad2d540b3 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
87b8e23610d4 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):
87b8e23610d4 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.
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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``
87b8e23610d4 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 """
87b8e23610d4 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
87b8e23610d4 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):
87b8e23610d4 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
7e6496bde18a 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
87b8e23610d4 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
87b8e23610d4 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
ce5ad2d540b3 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
87b8e23610d4 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):
87b8e23610d4 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
87b8e23610d4 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.
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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.
87b8e23610d4 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
87b8e23610d4 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
654e1d1b3953 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),
654e1d1b3953 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
87b8e23610d4 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
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 822
diff changeset
320 >>> print(load('app1/foo.html'))
714
7e6496bde18a 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
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 822
diff changeset
322 >>> print(load('app2/bar.html'))
714
7e6496bde18a 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)
7e6496bde18a 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
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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``
87b8e23610d4 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 """
87b8e23610d4 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):
87b8e23610d4 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():
87b8e23610d4 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):
87b8e23610d4 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
654e1d1b3953 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
7e6496bde18a 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
654e1d1b3953 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('/\\')
654e1d1b3953 Fix for prefix-dispatched template loading. Closes #206. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents: 697
diff changeset
336 )
714
7e6496bde18a 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
0d9e87c6cf6e 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
87b8e23610d4 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
ce5ad2d540b3 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
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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
87b8e23610d4 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