Mercurial > genshi > genshi-test
annotate genshi/template/base.py @ 590:880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
author | cmlenz |
---|---|
date | Fri, 10 Aug 2007 09:44:00 +0000 |
parents | b3b07279b86c |
children | bc5faca93699 |
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 # |
407
ea71a51e0258
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
405
diff
changeset
|
3 # Copyright (C) 2006-2007 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 |
427 | 14 """Basic templating functionality.""" |
15 | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
16 try: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
17 from collections import deque |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
18 except ImportError: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
19 class deque(list): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
20 def appendleft(self, x): self.insert(0, x) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
21 def popleft(self): return self.pop(0) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
22 import os |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
23 from StringIO import StringIO |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
24 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
25 from genshi.core import Attrs, Stream, StreamEventKind, START, TEXT, _ensure |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
26 from genshi.input import ParseError |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
27 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
28 __all__ = ['Context', 'Template', 'TemplateError', 'TemplateRuntimeError', |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
29 'TemplateSyntaxError', 'BadDirectiveError'] |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
420
diff
changeset
|
30 __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
|
31 |
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 class TemplateError(Exception): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
34 """Base exception class for errors related to template processing.""" |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
35 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
36 def __init__(self, message, filename='<string>', lineno=-1, offset=-1): |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
37 """Create the exception. |
435 | 38 |
39 :param message: the error message | |
40 :param filename: the filename of the template | |
41 :param lineno: the number of line in the template at which the error | |
42 occurred | |
43 :param offset: the column number at which the error occurred | |
44 """ | |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
45 self.msg = message #: the error message string |
407
ea71a51e0258
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
405
diff
changeset
|
46 if filename != '<string>' or lineno >= 0: |
ea71a51e0258
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
405
diff
changeset
|
47 message = '%s (%s, line %d)' % (self.msg, filename, lineno) |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
48 Exception.__init__(self, message) |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
49 self.filename = filename #: the name of the template file |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
50 self.lineno = lineno #: the number of the line containing the error |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
51 self.offset = offset #: the offset on the line |
336
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 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
54 class TemplateSyntaxError(TemplateError): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
55 """Exception raised when an expression in a template causes a Python syntax |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
56 error, or the template is not well-formed. |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
57 """ |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
58 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
59 def __init__(self, message, filename='<string>', lineno=-1, offset=-1): |
435 | 60 """Create the exception |
61 | |
62 :param message: the error message | |
63 :param filename: the filename of the template | |
64 :param lineno: the number of line in the template at which the error | |
65 occurred | |
66 :param offset: the column number at which the error occurred | |
67 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
68 if isinstance(message, SyntaxError) and message.lineno is not None: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
69 message = str(message).replace(' (line %d)' % message.lineno, '') |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
70 TemplateError.__init__(self, message, filename, lineno) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
71 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
72 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
73 class BadDirectiveError(TemplateSyntaxError): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
74 """Exception raised when an unknown directive is encountered when parsing |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
75 a template. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
76 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
77 An unknown directive is any attribute using the namespace for directives, |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
78 with a local name that doesn't match any registered directive. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
79 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
80 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
81 def __init__(self, name, filename='<string>', lineno=-1): |
435 | 82 """Create the exception |
83 | |
84 :param name: the name of the directive | |
85 :param filename: the filename of the template | |
86 :param lineno: the number of line in the template at which the error | |
87 occurred | |
88 """ | |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
89 TemplateSyntaxError.__init__(self, 'bad directive "%s"' % name, |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
90 filename, lineno) |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
91 |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
92 |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
93 class TemplateRuntimeError(TemplateError): |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
94 """Exception raised when an the evaluation of a Python expression in a |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
95 template causes an error. |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
96 """ |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
97 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
98 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
99 class Context(object): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
100 """Container for template input data. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
101 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
102 A context provides a stack of scopes (represented by dictionaries). |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
103 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
104 Template directives such as loops can push a new scope on the stack with |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
105 data that should only be available inside the loop. When the loop |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
106 terminates, that scope can get popped off the stack again. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
107 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
108 >>> ctxt = Context(one='foo', other=1) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
109 >>> ctxt.get('one') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
110 'foo' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
111 >>> ctxt.get('other') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
112 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
113 >>> ctxt.push(dict(one='frost')) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
114 >>> ctxt.get('one') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
115 'frost' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
116 >>> ctxt.get('other') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
117 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
118 >>> ctxt.pop() |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
119 {'one': 'frost'} |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
120 >>> ctxt.get('one') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
121 'foo' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
122 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
123 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
124 def __init__(self, **data): |
435 | 125 """Initialize the template context with the given keyword arguments as |
126 data. | |
127 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
128 self.frames = deque([data]) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
129 self.pop = self.frames.popleft |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
130 self.push = self.frames.appendleft |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
131 self._match_templates = [] |
553
887bbbfa4098
Store state information for py:choose outside of the regular context data.
cmlenz
parents:
548
diff
changeset
|
132 self._choice_stack = [] |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
133 |
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:
438
diff
changeset
|
134 # Helper functions for use in expressions |
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:
438
diff
changeset
|
135 def defined(name): |
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:
438
diff
changeset
|
136 """Return whether a variable with the specified name exists in the |
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:
438
diff
changeset
|
137 expression scope.""" |
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:
438
diff
changeset
|
138 return name in self |
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:
438
diff
changeset
|
139 def value_of(name, default=None): |
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:
438
diff
changeset
|
140 """If a variable of the specified name is defined, return its value. |
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:
438
diff
changeset
|
141 Otherwise, return the provided default value, or ``None``.""" |
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:
438
diff
changeset
|
142 return self.get(name, default) |
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:
438
diff
changeset
|
143 data.setdefault('defined', defined) |
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:
438
diff
changeset
|
144 data.setdefault('value_of', value_of) |
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:
438
diff
changeset
|
145 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
146 def __repr__(self): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
147 return repr(list(self.frames)) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
148 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
149 def __contains__(self, key): |
435 | 150 """Return whether a variable exists in any of the scopes. |
151 | |
152 :param key: the name of the variable | |
153 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
154 return self._find(key)[1] is not None |
564
b3b07279b86c
Alias `__contains__` to `has_key` in `Context` class for code outside of Genshi that may expect that for some wild reason.
cmlenz
parents:
553
diff
changeset
|
155 has_key = __contains__ |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
156 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
157 def __delitem__(self, key): |
435 | 158 """Remove a variable from all scopes. |
159 | |
160 :param key: the name of the variable | |
161 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
162 for frame in self.frames: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
163 if key in frame: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
164 del frame[key] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
165 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
166 def __getitem__(self, key): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
167 """Get a variables's value, starting at the current scope and going |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
168 upward. |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
169 |
435 | 170 :param key: the name of the variable |
171 :return: the variable value | |
172 :raises KeyError: if the requested variable wasn't found in any scope | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
173 """ |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
174 value, frame = self._find(key) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
175 if frame is None: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
176 raise KeyError(key) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
177 return value |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
178 |
420 | 179 def __len__(self): |
435 | 180 """Return the number of distinctly named variables in the context. |
181 | |
182 :return: the number of variables in the context | |
183 """ | |
420 | 184 return len(self.items()) |
185 | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
186 def __setitem__(self, key, value): |
435 | 187 """Set a variable in the current scope. |
188 | |
189 :param key: the name of the variable | |
190 :param value: the variable value | |
191 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
192 self.frames[0][key] = value |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
193 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
194 def _find(self, key, default=None): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
195 """Retrieve a given variable's value and the frame it was found in. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
196 |
435 | 197 Intended primarily for internal use by directives. |
198 | |
199 :param key: the name of the variable | |
200 :param default: the default value to return when the variable is not | |
201 found | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
202 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
203 for frame in self.frames: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
204 if key in frame: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
205 return frame[key], frame |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
206 return default, None |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
207 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
208 def get(self, key, default=None): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
209 """Get a variable's value, starting at the current scope and going |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
210 upward. |
435 | 211 |
212 :param key: the name of the variable | |
213 :param default: the default value to return when the variable is not | |
214 found | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
215 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
216 for frame in self.frames: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
217 if key in frame: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
218 return frame[key] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
219 return default |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
220 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
221 def keys(self): |
435 | 222 """Return the name of all variables in the context. |
223 | |
224 :return: a list of variable names | |
225 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
226 keys = [] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
227 for frame in self.frames: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
228 keys += [key for key in frame if key not in keys] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
229 return keys |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
230 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
231 def items(self): |
435 | 232 """Return a list of ``(name, value)`` tuples for all variables in the |
233 context. | |
234 | |
235 :return: a list of variables | |
236 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
237 return [(key, self.get(key)) for key in self.keys()] |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
238 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
239 def push(self, data): |
435 | 240 """Push a new scope on the stack. |
241 | |
242 :param data: the data dictionary to push on the context stack. | |
243 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
244 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
245 def pop(self): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
246 """Pop the top-most scope from the stack.""" |
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 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
249 def _apply_directives(stream, ctxt, directives): |
435 | 250 """Apply the given directives to the stream. |
251 | |
252 :param stream: the stream the directives should be applied to | |
253 :param ctxt: the `Context` | |
254 :param directives: the list of directives to apply | |
255 :return: the stream with the given directives applied | |
256 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
257 if directives: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
258 stream = directives[0](iter(stream), ctxt, directives[1:]) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
259 return stream |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
260 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
261 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
262 class TemplateMeta(type): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
263 """Meta class for templates.""" |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
264 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
265 def __new__(cls, name, bases, d): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
266 if 'directives' in d: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
267 d['_dir_by_name'] = dict(d['directives']) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
268 d['_dir_order'] = [directive[1] for directive in d['directives']] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
269 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
270 return type.__new__(cls, name, bases, d) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
271 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
272 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
273 class Template(object): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
274 """Abstract template base class. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
275 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
276 This class implements most of the template processing model, but does not |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
277 specify the syntax of templates. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
278 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
279 __metaclass__ = TemplateMeta |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
280 |
427 | 281 EXPR = StreamEventKind('EXPR') |
282 """Stream event kind representing a Python expression.""" | |
283 | |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
284 INCLUDE = StreamEventKind('INCLUDE') |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
285 """Stream event kind representing the inclusion of another template.""" |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
286 |
427 | 287 SUB = StreamEventKind('SUB') |
288 """Stream event kind representing a nested stream to which one or more | |
289 directives should be applied. | |
290 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
291 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
292 def __init__(self, source, basedir=None, filename=None, loader=None, |
545
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
293 encoding=None, lookup='lenient', allow_exec=True): |
427 | 294 """Initialize a template from either a string, a file-like object, or |
295 an already parsed markup stream. | |
296 | |
297 :param source: a string, file-like object, or markup stream to read the | |
298 template from | |
299 :param basedir: the base directory containing the template file; when | |
300 loaded from a `TemplateLoader`, this will be the | |
301 directory on the template search path in which the | |
302 template was found | |
303 :param filename: the name of the template file, relative to the given | |
304 base directory | |
492 | 305 :param loader: the `TemplateLoader` to use for loading included |
306 templates | |
427 | 307 :param encoding: the encoding of the `source` |
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:
438
diff
changeset
|
308 :param lookup: the variable lookup mechanism; either "lenient" (the |
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:
438
diff
changeset
|
309 default), "strict", or a custom lookup class |
545
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
310 :param allow_exec: whether Python code blocks in templates should be |
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
311 allowed |
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
312 |
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
313 :note: Changed in 0.5: Added the `allow_exec` argument |
427 | 314 """ |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
315 self.basedir = basedir |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
316 self.filename = filename |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
317 if basedir and filename: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
318 self.filepath = os.path.join(basedir, filename) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
319 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
320 self.filepath = filename |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
321 self.loader = loader |
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:
438
diff
changeset
|
322 self.lookup = lookup |
545
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
323 self.allow_exec = allow_exec |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
324 |
374
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
363
diff
changeset
|
325 if isinstance(source, basestring): |
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
363
diff
changeset
|
326 source = StringIO(source) |
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
363
diff
changeset
|
327 else: |
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
363
diff
changeset
|
328 source = source |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
329 try: |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
330 self.stream = list(self._prepare(self._parse(source, encoding))) |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
331 except ParseError, e: |
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
332 raise TemplateSyntaxError(e.msg, self.filepath, e.lineno, e.offset) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
333 self.filters = [self._flatten, self._eval] |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
334 if loader: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
335 self.filters.append(self._include) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
336 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
337 def __repr__(self): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
338 return '<%s "%s">' % (self.__class__.__name__, self.filename) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
339 |
374
ca46dc9c7761
`MarkupTemplate`s can now be instantiated from markup streams, in addition to strings and file-like objects. Thanks to David Fraser for the patch. Closes #69.
cmlenz
parents:
363
diff
changeset
|
340 def _parse(self, source, encoding): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
341 """Parse the template. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
342 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
343 The parsing stage parses the template and constructs a list of |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
344 directives that will be executed in the render stage. The input is |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
345 split up into literal output (text that does not depend on the context |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
346 data) and directives or expressions. |
427 | 347 |
348 :param source: a file-like object containing the XML source of the | |
349 template, or an XML event stream | |
350 :param encoding: the encoding of the `source` | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
351 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
352 raise NotImplementedError |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
353 |
351
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
354 def _prepare(self, stream): |
427 | 355 """Call the `attach` method of every directive found in the template. |
356 | |
357 :param stream: the event stream of the template | |
358 """ | |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
359 from genshi.template.loader import TemplateNotFound |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
360 |
351
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
361 for kind, data, pos in stream: |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
362 if kind is SUB: |
362
0910d5978f45
Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents:
361
diff
changeset
|
363 directives = [] |
0910d5978f45
Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents:
361
diff
changeset
|
364 substream = data[1] |
0910d5978f45
Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents:
361
diff
changeset
|
365 for cls, value, namespaces, pos in data[0]: |
0910d5978f45
Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents:
361
diff
changeset
|
366 directive, substream = cls.attach(self, substream, value, |
0910d5978f45
Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents:
361
diff
changeset
|
367 namespaces, pos) |
0910d5978f45
Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents:
361
diff
changeset
|
368 if directive: |
0910d5978f45
Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents:
361
diff
changeset
|
369 directives.append(directive) |
351
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
370 substream = self._prepare(substream) |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
371 if directives: |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
372 yield kind, (directives, list(substream)), pos |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
373 else: |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
374 for event in substream: |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
375 yield event |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
376 else: |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
377 if kind is INCLUDE: |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
378 href, fallback = data |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
379 if isinstance(href, basestring) and \ |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
380 not getattr(self.loader, 'auto_reload', True): |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
381 # If the path to the included template is static, and |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
382 # auto-reloading is disabled on the template loader, |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
383 # the template is inlined into the stream |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
384 try: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
385 tmpl = self.loader.load(href, relative_to=pos[0], |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
386 cls=self.__class__) |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
387 for event in tmpl.stream: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
388 yield event |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
389 except TemplateNotFound: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
390 if fallback is None: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
391 raise |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
392 for event in self._prepare(fallback): |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
393 yield event |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
394 continue |
590
880b1a75d046
Fix includes so that they again raise an exception when the included template is not found and no fallback has been provided.
cmlenz
parents:
564
diff
changeset
|
395 elif fallback: |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
396 # Otherwise the include is performed at run time |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
397 data = href, list(self._prepare(fallback)) |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
398 |
351
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
399 yield kind, data, pos |
50f4e199e3aa
The `py:content`, `py:replace`, and `py:strip=""` directives are now expanded when the template is loaded (as opposed to when it's rendered).
cmlenz
parents:
345
diff
changeset
|
400 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
401 def generate(self, *args, **kwargs): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
402 """Apply the template to the given context data. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
403 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
404 Any keyword arguments are made available to the template as context |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
405 data. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
406 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
407 Only one positional argument is accepted: if it is provided, it must be |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
408 an instance of the `Context` class, and keyword arguments are ignored. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
409 This calling style is used for internal processing. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
410 |
427 | 411 :return: a markup event stream representing the result of applying |
412 the template to the context data. | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
413 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
414 if args: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
415 assert len(args) == 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
416 ctxt = args[0] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
417 if ctxt is None: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
418 ctxt = Context(**kwargs) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
419 assert isinstance(ctxt, Context) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
420 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
421 ctxt = Context(**kwargs) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
422 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
423 stream = self.stream |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
424 for filter_ in self.filters: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
425 stream = filter_(iter(stream), ctxt) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
426 return Stream(stream) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
427 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
428 def _eval(self, stream, ctxt): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
429 """Internal stream filter that evaluates any expressions in `START` and |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
430 `TEXT` events. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
431 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
432 filters = (self._flatten, self._eval) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
433 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
434 for kind, data, pos in stream: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
435 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
436 if kind is START and data[1]: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
437 # Attributes may still contain expressions in start tags at |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
438 # this point, so do some evaluation |
345 | 439 tag, attrs = data |
440 new_attrs = [] | |
441 for name, substream in attrs: | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
442 if isinstance(substream, basestring): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
443 value = substream |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
444 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
445 values = [] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
446 for subkind, subdata, subpos in self._eval(substream, |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
447 ctxt): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
448 if subkind is TEXT: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
449 values.append(subdata) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
450 value = [x for x in values if x is not None] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
451 if not value: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
452 continue |
345 | 453 new_attrs.append((name, u''.join(value))) |
454 yield kind, (tag, Attrs(new_attrs)), pos | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
455 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
456 elif kind is EXPR: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
457 result = data.evaluate(ctxt) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
458 if result is not None: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
459 # First check for a string, otherwise the iterable test below |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
460 # succeeds, and the string will be chopped up into individual |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
461 # characters |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
462 if isinstance(result, basestring): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
463 yield TEXT, result, pos |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
464 elif hasattr(result, '__iter__'): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
465 substream = _ensure(result) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
466 for filter_ in filters: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
467 substream = filter_(substream, ctxt) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
468 for event in substream: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
469 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
470 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
471 yield TEXT, unicode(result), pos |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
472 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
473 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
474 yield kind, data, pos |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
475 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
476 def _flatten(self, stream, ctxt): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
477 """Internal stream filter that expands `SUB` events in the stream.""" |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
478 for event in stream: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
479 if event[0] is SUB: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
480 # This event is a list of directives and a list of nested |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
481 # events to which those directives should be applied |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
482 directives, substream = event[1] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
483 substream = _apply_directives(substream, ctxt, directives) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
484 for event in self._flatten(substream, ctxt): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
485 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
486 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
487 yield event |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
488 |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
489 def _include(self, stream, ctxt): |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
490 """Internal stream filter that performs inclusion of external |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
491 template files. |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
492 """ |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
493 from genshi.template.loader import TemplateNotFound |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
494 |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
495 for event in stream: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
496 if event[0] is INCLUDE: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
497 href, fallback = event[1] |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
498 if not isinstance(href, basestring): |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
499 parts = [] |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
500 for subkind, subdata, subpos in self._eval(href, ctxt): |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
501 if subkind is TEXT: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
502 parts.append(subdata) |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
503 href = u''.join([x for x in parts if x is not None]) |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
504 try: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
505 tmpl = self.loader.load(href, relative_to=event[2][0], |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
506 cls=self.__class__) |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
507 for event in tmpl.generate(ctxt): |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
508 yield event |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
509 except TemplateNotFound: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
510 if fallback is None: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
511 raise |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
512 for filter_ in self.filters: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
513 fallback = filter_(iter(fallback), ctxt) |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
514 for event in fallback: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
515 yield event |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
516 else: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
517 yield event |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
518 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
519 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
520 EXPR = Template.EXPR |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
521 INCLUDE = Template.INCLUDE |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
522 SUB = Template.SUB |