annotate genshi/template/loader.py @ 724:919809e55d16 experimental-match-fastpaths

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