annotate genshi/template/base.py @ 590:880b1a75d046

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