Mercurial > genshi > genshi-test
annotate genshi/template/base.py @ 935:705727288d7e
Merge r1143 from py3k:
add support for python 3 to remaining genshi.template components:
* minor changes to track encoding=None API change in core genshi modules.
* genshi/template/directives:
* slightly odd syntax changes to make the 2to3 .next() fixer pick up *stream.next()
* minor test fix for change in behaviour of division (/) in Python 3.
* genshi/template/loader:
* add 'b' to file modes to ensure it's loaded as bytes in Python 3.
* use not isinstance(s, unicode) instead of isinstance(s, str) since the former is correctly converted by 2to3.
author | hodgestar |
---|---|
date | Fri, 18 Mar 2011 09:17:52 +0000 |
parents | 85e4678337cf |
children |
rev | line source |
---|---|
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
1 # -*- coding: utf-8 -*- |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
2 # |
897 | 3 # Copyright (C) 2006-2010 Edgewall Software |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
4 # All rights reserved. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
5 # |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
6 # This software is licensed as described in the file COPYING, which |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
7 # you should have received as part of this distribution. The terms |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
8 # are also available at http://genshi.edgewall.org/wiki/License. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
9 # |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
10 # This software consists of voluntary contributions made by many |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
11 # individuals. For the exact contribution history, see the revision |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
12 # history and logs, available at http://genshi.edgewall.org/log/. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
13 |
427 | 14 """Basic templating functionality.""" |
15 | |
822
ce5ad2d540b3
Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents:
817
diff
changeset
|
16 from collections import deque |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
17 import os |
609
237050080827
Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents:
606
diff
changeset
|
18 import sys |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
19 |
935 | 20 from genshi.compat import StringIO, BytesIO |
636
e0f12a6f3612
Follow-up to [751]: applying the optimization to text templates was actually slowing them down, so only do it for markup templates.
cmlenz
parents:
635
diff
changeset
|
21 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
|
22 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
|
23 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
24 __all__ = ['Context', 'DirectiveFactory', 'Template', 'TemplateError', |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
25 'TemplateRuntimeError', 'TemplateSyntaxError', 'BadDirectiveError'] |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
420
diff
changeset
|
26 __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
|
27 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
28 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
29 class TemplateError(Exception): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
30 """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
|
31 |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
32 def __init__(self, message, filename=None, lineno=-1, offset=-1): |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
33 """Create the exception. |
435 | 34 |
35 :param message: the error message | |
36 :param filename: the filename of the template | |
37 :param lineno: the number of line in the template at which the error | |
38 occurred | |
39 :param offset: the column number at which the error occurred | |
40 """ | |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
41 if filename is None: |
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
42 filename = '<string>' |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
43 self.msg = message #: the error message string |
407
ea71a51e0258
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
405
diff
changeset
|
44 if filename != '<string>' or lineno >= 0: |
ea71a51e0258
Move string interpolation code into separate module (`genshi.template.interpolation`).
cmlenz
parents:
405
diff
changeset
|
45 message = '%s (%s, line %d)' % (self.msg, filename, lineno) |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
46 Exception.__init__(self, message) |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
47 self.filename = filename #: the name of the template file |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
48 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
|
49 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
|
50 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
51 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
52 class TemplateSyntaxError(TemplateError): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
53 """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
|
54 error, or the template is not well-formed. |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
55 """ |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
56 |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
57 def __init__(self, message, filename=None, lineno=-1, offset=-1): |
435 | 58 """Create the exception |
59 | |
60 :param message: the error message | |
61 :param filename: the filename of the template | |
62 :param lineno: the number of line in the template at which the error | |
63 occurred | |
64 :param offset: the column number at which the error occurred | |
65 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
66 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
|
67 message = str(message).replace(' (line %d)' % message.lineno, '') |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
68 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
|
69 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
70 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
71 class BadDirectiveError(TemplateSyntaxError): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
72 """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
|
73 a template. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
74 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
75 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
|
76 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
|
77 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
78 |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
79 def __init__(self, name, filename=None, lineno=-1): |
435 | 80 """Create the exception |
81 | |
82 :param name: the name of the directive | |
83 :param filename: the filename of the template | |
84 :param lineno: the number of line in the template at which the error | |
85 occurred | |
86 """ | |
438
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
87 TemplateSyntaxError.__init__(self, 'bad directive "%s"' % name, |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
88 filename, lineno) |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
89 |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
90 |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
91 class TemplateRuntimeError(TemplateError): |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
92 """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
|
93 template causes an error. |
6fd7e4dc0318
Added documentation page on the builtin stream filters.
cmlenz
parents:
435
diff
changeset
|
94 """ |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
95 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
96 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
97 class Context(object): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
98 """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
|
99 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
100 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
|
101 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
102 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
|
103 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
|
104 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
|
105 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
106 >>> 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
|
107 >>> ctxt.get('one') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
108 'foo' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
109 >>> ctxt.get('other') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
110 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
111 >>> 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
|
112 >>> ctxt.get('one') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
113 '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('other') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
115 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
116 >>> ctxt.pop() |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
117 {'one': 'frost'} |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
118 >>> ctxt.get('one') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
119 'foo' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
120 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
121 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
122 def __init__(self, **data): |
435 | 123 """Initialize the template context with the given keyword arguments as |
124 data. | |
125 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
126 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
|
127 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
|
128 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
|
129 self._match_templates = [] |
553
887bbbfa4098
Store state information for py:choose outside of the regular context data.
cmlenz
parents:
548
diff
changeset
|
130 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
|
131 |
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
|
132 # 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
|
133 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
|
134 """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
|
135 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
|
136 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
|
137 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
|
138 """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
|
139 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
|
140 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
|
141 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
|
142 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
|
143 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
144 def __repr__(self): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
145 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
|
146 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
147 def __contains__(self, key): |
435 | 148 """Return whether a variable exists in any of the scopes. |
149 | |
150 :param key: the name of the variable | |
151 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
152 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
|
153 has_key = __contains__ |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
154 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
155 def __delitem__(self, key): |
435 | 156 """Remove a variable from all scopes. |
157 | |
158 :param key: the name of the variable | |
159 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
160 for frame in self.frames: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
161 if key in frame: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
162 del frame[key] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
163 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
164 def __getitem__(self, key): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
165 """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
|
166 upward. |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
167 |
435 | 168 :param key: the name of the variable |
169 :return: the variable value | |
170 :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
|
171 """ |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
172 value, frame = self._find(key) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
173 if frame is None: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
174 raise KeyError(key) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
175 return value |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
176 |
420 | 177 def __len__(self): |
435 | 178 """Return the number of distinctly named variables in the context. |
179 | |
180 :return: the number of variables in the context | |
181 """ | |
420 | 182 return len(self.items()) |
183 | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
184 def __setitem__(self, key, value): |
435 | 185 """Set a variable in the current scope. |
186 | |
187 :param key: the name of the variable | |
188 :param value: the variable value | |
189 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
190 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
|
191 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
192 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
|
193 """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
|
194 |
435 | 195 Intended primarily for internal use by directives. |
196 | |
197 :param key: the name of the variable | |
198 :param default: the default value to return when the variable is not | |
199 found | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
200 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
201 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
|
202 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
|
203 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
|
204 return default, None |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
205 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
206 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
|
207 """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
|
208 upward. |
435 | 209 |
210 :param key: the name of the variable | |
211 :param default: the default value to return when the variable is not | |
212 found | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
213 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
214 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
|
215 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
|
216 return frame[key] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
217 return default |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
218 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
219 def keys(self): |
435 | 220 """Return the name of all variables in the context. |
221 | |
222 :return: a list of variable names | |
223 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
224 keys = [] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
225 for frame in self.frames: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
226 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
|
227 return keys |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
228 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
229 def items(self): |
435 | 230 """Return a list of ``(name, value)`` tuples for all variables in the |
231 context. | |
232 | |
233 :return: a list of variables | |
234 """ | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
400
diff
changeset
|
235 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
|
236 |
731
6514d9889ac8
Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents:
715
diff
changeset
|
237 def update(self, mapping): |
6514d9889ac8
Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents:
715
diff
changeset
|
238 """Update the context from the mapping provided.""" |
6514d9889ac8
Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents:
715
diff
changeset
|
239 self.frames[0].update(mapping) |
6514d9889ac8
Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents:
715
diff
changeset
|
240 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
241 def push(self, data): |
435 | 242 """Push a new scope on the stack. |
243 | |
244 :param data: the data dictionary to push on the context stack. | |
245 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
246 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
247 def pop(self): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
248 """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
|
249 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
250 |
827
0319a8874510
Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents:
825
diff
changeset
|
251 def _apply_directives(stream, directives, ctxt, vars): |
435 | 252 """Apply the given directives to the stream. |
253 | |
254 :param stream: the stream the directives should be applied to | |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
255 :param directives: the list of directives to apply |
435 | 256 :param ctxt: the `Context` |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
257 :param vars: additional variables that should be available when Python |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
258 code is executed |
435 | 259 :return: the stream with the given directives applied |
260 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
261 if directives: |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
262 stream = directives[0](iter(stream), directives[1:], ctxt, **vars) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
263 return stream |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
264 |
827
0319a8874510
Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents:
825
diff
changeset
|
265 |
0319a8874510
Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents:
825
diff
changeset
|
266 def _eval_expr(expr, ctxt, vars=None): |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
267 """Evaluate the given `Expression` object. |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
268 |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
269 :param expr: the expression to evaluate |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
270 :param ctxt: the `Context` |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
271 :param vars: additional variables that should be available to the |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
272 expression |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
273 :return: the result of the evaluation |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
274 """ |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
275 if vars: |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
276 ctxt.push(vars) |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
277 retval = expr.evaluate(ctxt) |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
278 if vars: |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
279 ctxt.pop() |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
280 return retval |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
281 |
827
0319a8874510
Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents:
825
diff
changeset
|
282 |
0319a8874510
Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents:
825
diff
changeset
|
283 def _exec_suite(suite, ctxt, vars=None): |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
284 """Execute the given `Suite` object. |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
285 |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
286 :param suite: the code suite to execute |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
287 :param ctxt: the `Context` |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
288 :param vars: additional variables that should be available to the |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
289 code |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
290 """ |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
291 if vars: |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
292 ctxt.push(vars) |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
293 ctxt.push({}) |
750 | 294 suite.execute(ctxt) |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
295 if vars: |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
296 top = ctxt.pop() |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
297 ctxt.pop() |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
298 ctxt.frames[0].update(top) |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
299 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
300 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
301 class DirectiveFactoryMeta(type): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
302 """Meta class for directive factories.""" |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
303 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
304 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
|
305 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
|
306 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
|
307 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
|
308 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
309 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
|
310 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
311 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
312 class DirectiveFactory(object): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
313 """Base for classes that provide a set of template directives. |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
314 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
315 :since: version 0.6 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
316 """ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
317 __metaclass__ = DirectiveFactoryMeta |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
318 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
319 directives = [] |
848 | 320 """A list of ``(name, cls)`` tuples that define the set of directives |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
321 provided by this factory. |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
322 """ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
323 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
324 def get_directive(self, name): |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
325 """Return the directive class for the given name. |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
326 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
327 :param name: the directive name as used in the template |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
328 :return: the directive class |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
329 :see: `Directive` |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
330 """ |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
331 return self._dir_by_name.get(name) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
332 |
847
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
333 def get_directive_index(self, dir_cls): |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
334 """Return a key for the given directive class that should be used to |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
335 sort it among other directives on the same `SUB` event. |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
336 |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
337 The default implementation simply returns the index of the directive in |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
338 the `directives` list. |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
339 |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
340 :param dir_cls: the directive class |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
341 :return: the sort key |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
342 """ |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
343 if dir_cls in self._dir_order: |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
344 return self._dir_order.index(dir_cls) |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
345 return len(self._dir_order) |
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
346 |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
347 |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
348 class Template(DirectiveFactory): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
349 """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
|
350 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
351 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
|
352 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
|
353 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
354 |
609
237050080827
Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents:
606
diff
changeset
|
355 EXEC = StreamEventKind('EXEC') |
237050080827
Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents:
606
diff
changeset
|
356 """Stream event kind representing a Python code suite to execute.""" |
237050080827
Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents:
606
diff
changeset
|
357 |
427 | 358 EXPR = StreamEventKind('EXPR') |
359 """Stream event kind representing a Python expression.""" | |
360 | |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
361 INCLUDE = StreamEventKind('INCLUDE') |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
362 """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
|
363 |
427 | 364 SUB = StreamEventKind('SUB') |
365 """Stream event kind representing a nested stream to which one or more | |
366 directives should be applied. | |
367 """ | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
368 |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
590
diff
changeset
|
369 serializer = None |
636
e0f12a6f3612
Follow-up to [751]: applying the optimization to text templates was actually slowing them down, so only do it for markup templates.
cmlenz
parents:
635
diff
changeset
|
370 _number_conv = unicode # function used to convert numbers to event data |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
590
diff
changeset
|
371 |
714
7e6496bde18a
The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents:
700
diff
changeset
|
372 def __init__(self, source, filepath=None, filename=None, loader=None, |
606
9ada030ad986
Changed the default error handling mode to "strict".
cmlenz
parents:
605
diff
changeset
|
373 encoding=None, lookup='strict', allow_exec=True): |
427 | 374 """Initialize a template from either a string, a file-like object, or |
375 an already parsed markup stream. | |
376 | |
377 :param source: a string, file-like object, or markup stream to read the | |
378 template from | |
714
7e6496bde18a
The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents:
700
diff
changeset
|
379 :param filepath: the absolute path to the template file |
7e6496bde18a
The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents:
700
diff
changeset
|
380 :param filename: the path to the template file relative to the search |
7e6496bde18a
The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents:
700
diff
changeset
|
381 path |
492 | 382 :param loader: the `TemplateLoader` to use for loading included |
383 templates | |
427 | 384 :param encoding: the encoding of the `source` |
606
9ada030ad986
Changed the default error handling mode to "strict".
cmlenz
parents:
605
diff
changeset
|
385 :param lookup: the variable lookup mechanism; either "strict" (the |
9ada030ad986
Changed the default error handling mode to "strict".
cmlenz
parents:
605
diff
changeset
|
386 default), "lenient", 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
|
387 :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
|
388 allowed |
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
389 |
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
390 :note: Changed in 0.5: Added the `allow_exec` argument |
427 | 391 """ |
714
7e6496bde18a
The `Template` class and its subclasses, as well as the interpolation API, now take an `filepath` parameter instead of `basedir`. Closes #207. Thanks to Waldemar Kornewald for the patch.
cmlenz
parents:
700
diff
changeset
|
392 self.filepath = filepath or filename |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
393 self.filename = filename |
363
caf7b68ab5dc
Parse template includes at parse time to avoid some runtime overhead.
cmlenz
parents:
362
diff
changeset
|
394 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
|
395 self.lookup = lookup |
545
6e21c89d9255
Support for Python code blocks in templates can now be disabled. Closes #123.
cmlenz
parents:
492
diff
changeset
|
396 self.allow_exec = allow_exec |
715 | 397 self._init_filters() |
876
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
398 self._init_loader() |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
399 self._prepared = False |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
400 |
935 | 401 if not isinstance(source, Stream) and not hasattr(source, 'read'): |
402 if isinstance(source, unicode): | |
403 source = StringIO(source) | |
404 else: | |
405 source = BytesIO(source) | |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
406 try: |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
407 self._stream = self._parse(source, encoding) |
434
e065d7906b68
* Better method to propogate the full path to the template file on parse errors. Supersedes r513.
cmlenz
parents:
427
diff
changeset
|
408 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
|
409 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
|
410 |
715 | 411 def __getstate__(self): |
412 state = self.__dict__.copy() | |
413 state['filters'] = [] | |
414 return state | |
415 | |
416 def __setstate__(self, state): | |
417 self.__dict__ = state | |
418 self._init_filters() | |
419 | |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
420 def __repr__(self): |
860
61d37796da98
A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents:
855
diff
changeset
|
421 return '<%s "%s">' % (type(self).__name__, self.filename) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
422 |
715 | 423 def _init_filters(self): |
876
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
424 self.filters = [self._flatten, self._include] |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
425 |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
426 def _init_loader(self): |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
427 if self.loader is None: |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
428 from genshi.template.loader import TemplateLoader |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
429 if self.filename: |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
430 if self.filepath != self.filename: |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
431 basedir = os.path.normpath(self.filepath)[:-len( |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
432 os.path.normpath(self.filename)) |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
433 ] |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
434 else: |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
435 basedir = os.path.dirname(self.filename) |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
436 else: |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
437 basedir = '.' |
52d7d6b7b6c1
Templates instantiated without a loader now get an implicit loader based on their file path, or the current directory as a fallback. Closes #320.
cmlenz
parents:
860
diff
changeset
|
438 self.loader = TemplateLoader([os.path.abspath(basedir)]) |
715 | 439 |
822
ce5ad2d540b3
Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents:
817
diff
changeset
|
440 @property |
ce5ad2d540b3
Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents:
817
diff
changeset
|
441 def stream(self): |
790
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
442 if not self._prepared: |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
443 self._stream = list(self._prepare(self._stream)) |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
444 self._prepared = True |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
445 return self._stream |
1b6968d31089
Merged the custom-directives branch back into trunk.
cmlenz
parents:
750
diff
changeset
|
446 |
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
|
447 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
|
448 """Parse the template. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
449 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
450 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
|
451 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
|
452 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
|
453 data) and directives or expressions. |
427 | 454 |
455 :param source: a file-like object containing the XML source of the | |
456 template, or an XML event stream | |
457 :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
|
458 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
459 raise NotImplementedError |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
460 |
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
|
461 def _prepare(self, stream): |
427 | 462 """Call the `attach` method of every directive found in the template. |
463 | |
464 :param stream: the event stream of the template | |
465 """ | |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
466 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
|
467 |
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
|
468 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
|
469 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
|
470 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
|
471 substream = data[1] |
847
4f9e5e6f1aab
Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents:
843
diff
changeset
|
472 for _, cls, value, namespaces, pos in sorted(data[0]): |
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
|
473 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
|
474 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
|
475 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
|
476 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
|
477 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
|
478 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
|
479 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
|
480 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
|
481 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
|
482 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
|
483 else: |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
484 if kind is INCLUDE: |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
485 href, cls, fallback = data |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
486 if isinstance(href, basestring) and \ |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
487 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
|
488 # 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
|
489 # 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
|
490 # 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
|
491 try: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
492 tmpl = self.loader.load(href, relative_to=pos[0], |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
493 cls=cls or self.__class__) |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
494 for event in tmpl.stream: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
495 yield event |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
496 except TemplateNotFound: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
497 if fallback is None: |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
498 raise |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
499 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
|
500 yield event |
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
501 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
|
502 elif fallback: |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
503 # Otherwise the include is performed at run time |
639
b0cdc457dde9
Fix for XInclude fallbacks when auto-reloading is enabled. Closes #147. Thanks to rintaro@cpan.org for reporting the issue and providing a patch and test case!
cmlenz
parents:
636
diff
changeset
|
504 data = href, cls, list(self._prepare(fallback)) |
548
c2e039c7e439
Implement static includes, which improves performance a bit when auto reloading is disabled.
cmlenz
parents:
545
diff
changeset
|
505 |
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
|
506 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
|
507 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
508 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
|
509 """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
|
510 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
511 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
|
512 data. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
513 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
514 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
|
515 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
|
516 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
|
517 |
427 | 518 :return: a markup event stream representing the result of applying |
519 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
|
520 """ |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
521 vars = {} |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
522 if args: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
523 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
|
524 ctxt = args[0] |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
525 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
|
526 ctxt = Context(**kwargs) |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
527 else: |
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
528 vars = kwargs |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
529 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
|
530 else: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
531 ctxt = Context(**kwargs) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
532 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
533 stream = self.stream |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
534 for filter_ in self.filters: |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
535 stream = filter_(iter(stream), ctxt, **vars) |
605
bc5faca93699
Text templates now default to rendering as plain text; it is no longer necessary to explicitly specify the "text" method to the `render()` or `serialize()` method of the generated markup stream. See tickets #62 and #118.
cmlenz
parents:
590
diff
changeset
|
536 return Stream(stream, self.serializer) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
537 |
813
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
790
diff
changeset
|
538 def _flatten(self, stream, ctxt, **vars): |
636
e0f12a6f3612
Follow-up to [751]: applying the optimization to text templates was actually slowing them down, so only do it for markup templates.
cmlenz
parents:
635
diff
changeset
|
539 number_conv = self._number_conv |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
540 stack = [] |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
541 push = stack.append |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
542 pop = stack.pop |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
543 stream = iter(stream) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
544 |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
545 while 1: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
546 for kind, data, pos in stream: |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
547 |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
548 if kind is START and data[1]: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
549 # Attributes may still contain expressions in start tags at |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
550 # this point, so do some evaluation |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
551 tag, attrs = data |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
552 new_attrs = [] |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
553 for name, value in attrs: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
554 if type(value) is list: # this is an interpolated string |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
555 values = [event[1] |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
556 for event in self._flatten(value, ctxt, **vars) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
557 if event[0] is TEXT and event[1] is not None |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
558 ] |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
559 if not values: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
560 continue |
855 | 561 value = ''.join(values) |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
562 new_attrs.append((name, value)) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
563 yield kind, (tag, Attrs(new_attrs)), pos |
813
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
790
diff
changeset
|
564 |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
565 elif kind is EXPR: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
566 result = _eval_expr(data, ctxt, vars) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
567 if result is not None: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
568 # First check for a string, otherwise the iterable test |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
569 # below succeeds, and the string will be chopped up into |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
570 # individual characters |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
571 if isinstance(result, basestring): |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
572 yield TEXT, result, pos |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
573 elif isinstance(result, (int, float, long)): |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
574 yield TEXT, number_conv(result), pos |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
575 elif hasattr(result, '__iter__'): |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
576 push(stream) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
577 stream = _ensure(result) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
578 break |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
579 else: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
580 yield TEXT, unicode(result), pos |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
581 |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
582 elif kind is SUB: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
583 # This event is a list of directives and a list of nested |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
584 # events to which those directives should be applied |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
585 push(stream) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
586 stream = _apply_directives(data[1], data[0], ctxt, vars) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
587 break |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
588 |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
589 elif kind is EXEC: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
590 _exec_suite(data, ctxt, vars) |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
591 |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
592 else: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
593 yield kind, data, pos |
813
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
790
diff
changeset
|
594 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
595 else: |
843
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
596 if not stack: |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
597 break |
004f81b59d97
Refactored the template flattening method to be less recursive.
cmlenz
parents:
827
diff
changeset
|
598 stream = pop() |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
599 |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
600 def _include(self, stream, ctxt, **vars): |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
601 """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
|
602 template files. |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
603 """ |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
604 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
|
605 |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
606 for event in stream: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
607 if event[0] is INCLUDE: |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
608 href, cls, fallback = event[1] |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
609 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
|
610 parts = [] |
813
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
790
diff
changeset
|
611 for subkind, subdata, subpos in self._flatten(href, ctxt, |
3047d5d83ccc
Merge the internal template filters `_eval` and `_exec` into the `_flatten` function for slightly better performance.
cmlenz
parents:
790
diff
changeset
|
612 **vars): |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
613 if subkind is TEXT: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
614 parts.append(subdata) |
855 | 615 href = ''.join([x for x in parts if x is not None]) |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
616 try: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
617 tmpl = self.loader.load(href, relative_to=event[2][0], |
610
6a37018199fd
* XInclude elements in markup templates now support the `parse` attribute; when set to "xml" (the default), the include is processed as before, but when set to "text", the included template is parsed as a text template using the new syntax (ticket #101).
cmlenz
parents:
609
diff
changeset
|
618 cls=cls or self.__class__) |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
619 for event in tmpl.generate(ctxt, **vars): |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
620 yield event |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
621 except TemplateNotFound: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
622 if fallback is None: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
623 raise |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
624 for filter_ in self.filters: |
700
8d079cee6822
Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents:
639
diff
changeset
|
625 fallback = filter_(iter(fallback), ctxt, **vars) |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
626 for event in fallback: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
627 yield event |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
628 else: |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
629 yield event |
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
630 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
631 |
609
237050080827
Add support for Python code blocks in text templates using the new syntax.
cmlenz
parents:
606
diff
changeset
|
632 EXEC = Template.EXEC |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
633 EXPR = Template.EXPR |
475
bb939ed3058c
Added include directive for text templates (#115). Thanks to Alastair for the original patch.
cmlenz
parents:
442
diff
changeset
|
634 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
|
635 SUB = Template.SUB |