annotate genshi/template/directives.py @ 1029:7d4414a4a5d0 trunk

Support slash escaped of CRLF newlines (fixes #569; patch from tetsuya.morimoto@gmail.com).
author hodgestar
date Wed, 19 Mar 2014 13:40:47 +0000
parents 59463031d904
children 51ab60299647
rev   line source
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
2 #
847
e16447a9605f Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents: 827
diff changeset
3 # Copyright (C) 2006-2009 Edgewall Software
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
4 # All rights reserved.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
5 #
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
9 #
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
13
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
14 """Implementation of the various template directives."""
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
15
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
16 from genshi.core import QName, Stream
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
17 from genshi.path import Path
400
e29a94b3ba0c Renamed `genshi.template.core` to `genshi.template.base`, mainly to avoid confusion with `genshi.core`.
cmlenz
parents: 380
diff changeset
18 from genshi.template.base import TemplateRuntimeError, TemplateSyntaxError, \
817
f2c58252daa3 Minor simplification in the expansion of dynamic attributes.
cmlenz
parents: 794
diff changeset
19 EXPR, _apply_directives, _eval_expr
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
20 from genshi.template.eval import Expression, ExpressionASTTransformer, \
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
21 _ast, _parse
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
22
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
23 __all__ = ['AttrsDirective', 'ChooseDirective', 'ContentDirective',
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
24 'DefDirective', 'ForDirective', 'IfDirective', 'MatchDirective',
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
25 'OtherwiseDirective', 'ReplaceDirective', 'StripDirective',
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
26 'WhenDirective', 'WithDirective']
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
27 __docformat__ = 'restructuredtext en'
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
29
362
fe40d34fb71d 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: 351
diff changeset
30 class DirectiveMeta(type):
fe40d34fb71d 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: 351
diff changeset
31 """Meta class for template directives."""
fe40d34fb71d 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: 351
diff changeset
32
fe40d34fb71d 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: 351
diff changeset
33 def __new__(cls, name, bases, d):
fe40d34fb71d 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: 351
diff changeset
34 d['tagname'] = name.lower().replace('directive', '')
fe40d34fb71d 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: 351
diff changeset
35 return type.__new__(cls, name, bases, d)
fe40d34fb71d 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: 351
diff changeset
36
fe40d34fb71d 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: 351
diff changeset
37
fe40d34fb71d 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: 351
diff changeset
38 class Directive(object):
fe40d34fb71d 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: 351
diff changeset
39 """Abstract base class for template directives.
fe40d34fb71d 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: 351
diff changeset
40
fe40d34fb71d 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: 351
diff changeset
41 A directive is basically a callable that takes three positional arguments:
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
42 ``ctxt`` is the template data context, ``stream`` is an iterable over the
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
43 events that the directive applies to, and ``directives`` is is a list of
362
fe40d34fb71d 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: 351
diff changeset
44 other directives on the same stream that need to be applied.
fe40d34fb71d 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: 351
diff changeset
45
fe40d34fb71d 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: 351
diff changeset
46 Directives can be "anonymous" or "registered". Registered directives can be
fe40d34fb71d 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: 351
diff changeset
47 applied by the template author using an XML attribute with the
fe40d34fb71d 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: 351
diff changeset
48 corresponding name in the template. Such directives should be subclasses of
fe40d34fb71d 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: 351
diff changeset
49 this base class that can be instantiated with the value of the directive
fe40d34fb71d 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: 351
diff changeset
50 attribute as parameter.
fe40d34fb71d 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: 351
diff changeset
51
fe40d34fb71d 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: 351
diff changeset
52 Anonymous directives are simply functions conforming to the protocol
fe40d34fb71d 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: 351
diff changeset
53 described above, and can only be applied programmatically (for example by
fe40d34fb71d 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: 351
diff changeset
54 template filters).
fe40d34fb71d 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: 351
diff changeset
55 """
fe40d34fb71d 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: 351
diff changeset
56 __metaclass__ = DirectiveMeta
fe40d34fb71d 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: 351
diff changeset
57 __slots__ = ['expr']
fe40d34fb71d 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: 351
diff changeset
58
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
59 def __init__(self, value, template=None, namespaces=None, lineno=-1,
362
fe40d34fb71d 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: 351
diff changeset
60 offset=-1):
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
61 self.expr = self._parse_expr(value, template, lineno, offset)
362
fe40d34fb71d 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: 351
diff changeset
62
822
70fddd2262f5 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
63 @classmethod
362
fe40d34fb71d 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: 351
diff changeset
64 def attach(cls, template, stream, value, namespaces, pos):
fe40d34fb71d 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: 351
diff changeset
65 """Called after the template stream has been completely parsed.
fe40d34fb71d 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: 351
diff changeset
66
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
67 :param template: the `Template` object
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
68 :param stream: the event stream associated with the directive
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
69 :param value: the argument value for the directive; if the directive was
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
70 specified as an element, this will be an `Attrs` instance
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
71 with all specified attributes, otherwise it will be a
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
72 `unicode` object with just the attribute value
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
73 :param namespaces: a mapping of namespace URIs to prefixes
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
74 :param pos: a ``(filename, lineno, offset)`` tuple describing the
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
75 location where the directive was found in the source
362
fe40d34fb71d 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: 351
diff changeset
76
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
77 This class method should return a ``(directive, stream)`` tuple. If
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
78 ``directive`` is not ``None``, it should be an instance of the `Directive`
362
fe40d34fb71d 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: 351
diff changeset
79 class, and gets added to the list of directives applied to the substream
fe40d34fb71d 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: 351
diff changeset
80 at runtime. `stream` is an event stream that replaces the original
fe40d34fb71d 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: 351
diff changeset
81 stream associated with the directive.
fe40d34fb71d 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: 351
diff changeset
82 """
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
83 return cls(value, template, namespaces, *pos[1:]), stream
362
fe40d34fb71d 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: 351
diff changeset
84
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
85 def __call__(self, stream, directives, ctxt, **vars):
362
fe40d34fb71d 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: 351
diff changeset
86 """Apply the directive to the given stream.
fe40d34fb71d 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: 351
diff changeset
87
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
88 :param stream: the event stream
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
89 :param directives: a list of the remaining directives that should
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
90 process the stream
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
91 :param ctxt: the context data
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
92 :param vars: additional variables that should be made available when
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
93 Python code is executed
362
fe40d34fb71d 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: 351
diff changeset
94 """
fe40d34fb71d 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: 351
diff changeset
95 raise NotImplementedError
fe40d34fb71d 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: 351
diff changeset
96
fe40d34fb71d 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: 351
diff changeset
97 def __repr__(self):
fe40d34fb71d 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: 351
diff changeset
98 expr = ''
380
bf2068f5ef74 Fail gracefully in `Directive.__repr__` if the `expr` attribute does not exist for some reason I don't really understand right now (see Trac ticket [http://trac.edgewall.org/ticket/4249 #4249]).
cmlenz
parents: 362
diff changeset
99 if getattr(self, 'expr', None) is not None:
362
fe40d34fb71d 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: 351
diff changeset
100 expr = ' "%s"' % self.expr.source
860
16d55698006a A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
101 return '<%s%s>' % (type(self).__name__, expr)
362
fe40d34fb71d 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: 351
diff changeset
102
822
70fddd2262f5 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
103 @classmethod
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
104 def _parse_expr(cls, expr, template, lineno=-1, offset=-1):
362
fe40d34fb71d 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: 351
diff changeset
105 """Parses the given expression, raising a useful error message when a
fe40d34fb71d 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: 351
diff changeset
106 syntax error is encountered.
fe40d34fb71d 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: 351
diff changeset
107 """
fe40d34fb71d 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: 351
diff changeset
108 try:
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
109 return expr and Expression(expr, template.filepath, lineno,
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
110 lookup=template.lookup) or None
362
fe40d34fb71d 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: 351
diff changeset
111 except SyntaxError, err:
fe40d34fb71d 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: 351
diff changeset
112 err.msg += ' in expression "%s" of "%s" directive' % (expr,
fe40d34fb71d 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: 351
diff changeset
113 cls.tagname)
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
114 raise TemplateSyntaxError(err, template.filepath, lineno,
362
fe40d34fb71d 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: 351
diff changeset
115 offset + (err.offset or 0))
fe40d34fb71d 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: 351
diff changeset
116
fe40d34fb71d 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: 351
diff changeset
117
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
118 def _assignment(ast):
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
119 """Takes the AST representation of an assignment, and returns a
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
120 function that applies the assignment of a given value to a dictionary.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
121 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
122 def _names(node):
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
123 if isinstance(node, _ast.Tuple):
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
124 return tuple([_names(child) for child in node.elts])
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
125 elif isinstance(node, _ast.Name):
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
126 return node.id
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
127 def _assign(data, value, names=_names(ast)):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
128 if type(names) is tuple:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
129 for idx in range(len(names)):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
130 _assign(data, value[idx], names[idx])
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
131 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
132 data[names] = value
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
133 return _assign
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
134
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
135
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
136 class AttrsDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
137 """Implementation of the ``py:attrs`` template directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
138
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
139 The value of the ``py:attrs`` attribute should be a dictionary or a sequence
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
140 of ``(name, value)`` tuples. The items in that dictionary or sequence are
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
141 added as attributes to the element:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
142
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
143 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
144 >>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
145 ... <li py:attrs="foo">Bar</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
146 ... </ul>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
147 >>> print(tmpl.generate(foo={'class': 'collapse'}))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
148 <ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
149 <li class="collapse">Bar</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
150 </ul>
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
151 >>> print(tmpl.generate(foo=[('class', 'collapse')]))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
152 <ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
153 <li class="collapse">Bar</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
154 </ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
155
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
156 If the value evaluates to ``None`` (or any other non-truth value), no
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
157 attributes are added:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
158
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
159 >>> print(tmpl.generate(foo=None))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
160 <ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
161 <li>Bar</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
162 </ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
163 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
164 __slots__ = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
165
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
166 def __call__(self, stream, directives, ctxt, **vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
167 def _generate():
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
168 kind, (tag, attrib), pos = stream.next()
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
169 attrs = _eval_expr(self.expr, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
170 if attrs:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
171 if isinstance(attrs, Stream):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
172 try:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
173 attrs = iter(attrs).next()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
174 except StopIteration:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
175 attrs = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
176 elif not isinstance(attrs, list): # assume it's a dict
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
177 attrs = attrs.items()
904
82b9b3afe0b8 The `|` operator on `Attrs` objects now removes any existing attributes if the value is `None`.
cmlenz
parents: 860
diff changeset
178 attrib |= [
82b9b3afe0b8 The `|` operator on `Attrs` objects now removes any existing attributes if the value is `None`.
cmlenz
parents: 860
diff changeset
179 (QName(n), v is not None and unicode(v).strip() or None)
82b9b3afe0b8 The `|` operator on `Attrs` objects now removes any existing attributes if the value is `None`.
cmlenz
parents: 860
diff changeset
180 for n, v in attrs
82b9b3afe0b8 The `|` operator on `Attrs` objects now removes any existing attributes if the value is `None`.
cmlenz
parents: 860
diff changeset
181 ]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
182 yield kind, (tag, attrib), pos
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
183 for event in stream:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
184 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
185
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
186 return _apply_directives(_generate(), directives, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
187
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
188
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
189 class ContentDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
190 """Implementation of the ``py:content`` template directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
191
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
192 This directive replaces the content of the element with the result of
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
193 evaluating the value of the ``py:content`` attribute:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
194
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
195 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
196 >>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
197 ... <li py:content="bar">Hello</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
198 ... </ul>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
199 >>> print(tmpl.generate(bar='Bye'))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
200 <ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
201 <li>Bye</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
202 </ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
203 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
204 __slots__ = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
205
822
70fddd2262f5 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
206 @classmethod
362
fe40d34fb71d 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: 351
diff changeset
207 def attach(cls, template, stream, value, namespaces, pos):
657
54964f7d2253 Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
208 if type(value) is dict:
54964f7d2253 Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
209 raise TemplateSyntaxError('The content directive can not be used '
54964f7d2253 Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
210 'as an element', template.filepath,
54964f7d2253 Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
211 *pos[1:])
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
212 expr = cls._parse_expr(value, template, *pos[1:])
362
fe40d34fb71d 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: 351
diff changeset
213 return None, [stream[0], (EXPR, expr, pos), stream[-1]]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
214
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
215
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
216 class DefDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
217 """Implementation of the ``py:def`` template directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
218
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
219 This directive can be used to create "Named Template Functions", which
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
220 are template snippets that are not actually output during normal
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
221 processing, but rather can be expanded from expressions in other places
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
222 in the template.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
223
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
224 A named template function can be used just like a normal Python function
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
225 from template expressions:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
226
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
227 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
228 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
229 ... <p py:def="echo(greeting, name='world')" class="message">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
230 ... ${greeting}, ${name}!
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
231 ... </p>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
232 ... ${echo('Hi', name='you')}
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
233 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
234 >>> print(tmpl.generate(bar='Bye'))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
235 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
236 <p class="message">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
237 Hi, you!
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
238 </p>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
239 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
240
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
241 If a function does not require parameters, the parenthesis can be omitted
343
35189e960252 Remove automatic calling of expression evaluation results if they are callable. See [http://groups.google.com/group/genshi/browse_thread/thread/f515986760918d41 this mailing list thread].
cmlenz
parents: 336
diff changeset
242 in the definition:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
243
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
244 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
245 ... <p py:def="helloworld" class="message">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
246 ... Hello, world!
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
247 ... </p>
343
35189e960252 Remove automatic calling of expression evaluation results if they are callable. See [http://groups.google.com/group/genshi/browse_thread/thread/f515986760918d41 this mailing list thread].
cmlenz
parents: 336
diff changeset
248 ... ${helloworld()}
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
249 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
250 >>> print(tmpl.generate(bar='Bye'))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
251 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
252 <p class="message">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
253 Hello, world!
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
254 </p>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
255 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
256 """
479
94191f4233f3 Apply patch for #116.
cmlenz
parents: 442
diff changeset
257 __slots__ = ['name', 'args', 'star_args', 'dstar_args', 'defaults']
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
258
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
259 def __init__(self, args, template, namespaces=None, lineno=-1, offset=-1):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
260 Directive.__init__(self, None, template, namespaces, lineno, offset)
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
261 ast = _parse(args).body
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
262 self.args = []
479
94191f4233f3 Apply patch for #116.
cmlenz
parents: 442
diff changeset
263 self.star_args = None
94191f4233f3 Apply patch for #116.
cmlenz
parents: 442
diff changeset
264 self.dstar_args = None
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
265 self.defaults = {}
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
266 if isinstance(ast, _ast.Call):
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
267 self.name = ast.func.id
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
268 for arg in ast.args:
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
269 # only names
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
270 self.args.append(arg.id)
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
271 for kwd in ast.keywords:
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
272 self.args.append(kwd.arg)
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
273 exp = Expression(kwd.value, template.filepath,
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
274 lineno, lookup=template.lookup)
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
275 self.defaults[kwd.arg] = exp
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
276 if getattr(ast, 'starargs', None):
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
277 self.star_args = ast.starargs.id
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
278 if getattr(ast, 'kwargs', None):
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
279 self.dstar_args = ast.kwargs.id
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
280 else:
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
281 self.name = ast.id
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
282
822
70fddd2262f5 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
283 @classmethod
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
284 def attach(cls, template, stream, value, namespaces, pos):
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
285 if type(value) is dict:
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
286 value = value.get('function')
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
287 return super(DefDirective, cls).attach(template, stream, value,
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
288 namespaces, pos)
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
289
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
290 def __call__(self, stream, directives, ctxt, **vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
291 stream = list(stream)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
292
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
293 def function(*args, **kwargs):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
294 scope = {}
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
295 args = list(args) # make mutable
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
296 for name in self.args:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
297 if args:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
298 scope[name] = args.pop(0)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
299 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
300 if name in kwargs:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
301 val = kwargs.pop(name)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
302 else:
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
303 val = _eval_expr(self.defaults.get(name), ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
304 scope[name] = val
479
94191f4233f3 Apply patch for #116.
cmlenz
parents: 442
diff changeset
305 if not self.star_args is None:
94191f4233f3 Apply patch for #116.
cmlenz
parents: 442
diff changeset
306 scope[self.star_args] = args
94191f4233f3 Apply patch for #116.
cmlenz
parents: 442
diff changeset
307 if not self.dstar_args is None:
94191f4233f3 Apply patch for #116.
cmlenz
parents: 442
diff changeset
308 scope[self.dstar_args] = kwargs
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
309 ctxt.push(scope)
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
310 for event in _apply_directives(stream, directives, ctxt, vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
311 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
312 ctxt.pop()
750
52219748e5c1 Remove some cruft for supporting Python 2.3.
cmlenz
parents: 719
diff changeset
313 function.__name__ = self.name
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
314
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
315 # Store the function reference in the bottom context frame so that it
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
316 # doesn't get popped off before processing the template has finished
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
317 # FIXME: this makes context data mutable as a side-effect
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
318 ctxt.frames[-1][self.name] = function
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
319
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
320 return []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
321
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
322 def __repr__(self):
860
16d55698006a A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
323 return '<%s "%s">' % (type(self).__name__, self.name)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
324
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
325
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
326 class ForDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
327 """Implementation of the ``py:for`` template directive for repeating an
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
328 element based on an iterable in the context data.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
329
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
330 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
331 >>> tmpl = MarkupTemplate('''<ul xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
332 ... <li py:for="item in items">${item}</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
333 ... </ul>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
334 >>> print(tmpl.generate(items=[1, 2, 3]))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
335 <ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
336 <li>1</li><li>2</li><li>3</li>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
337 </ul>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
338 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
339 __slots__ = ['assign', 'filename']
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
340
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
341 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
342 if ' in ' not in value:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
343 raise TemplateSyntaxError('"in" keyword missing in "for" directive',
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
344 template.filepath, lineno, offset)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
345 assign, value = value.split(' in ', 1)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
346 ast = _parse(assign, 'exec')
640
ec86c89da78d Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
347 value = 'iter(%s)' % value.strip()
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
348 self.assign = _assignment(ast.body[0].value)
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
349 self.filename = template.filepath
640
ec86c89da78d Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
350 Directive.__init__(self, value, template, namespaces, lineno, offset)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
351
822
70fddd2262f5 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
352 @classmethod
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
353 def attach(cls, template, stream, value, namespaces, pos):
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
354 if type(value) is dict:
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
355 value = value.get('each')
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
356 return super(ForDirective, cls).attach(template, stream, value,
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
357 namespaces, pos)
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
358
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
359 def __call__(self, stream, directives, ctxt, **vars):
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
360 iterable = _eval_expr(self.expr, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
361 if iterable is None:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
362 return
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
363
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
364 assign = self.assign
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
365 scope = {}
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
366 stream = list(stream)
640
ec86c89da78d Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
367 for item in iterable:
ec86c89da78d Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
368 assign(scope, item)
ec86c89da78d Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
369 ctxt.push(scope)
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
370 for event in _apply_directives(stream, directives, ctxt, vars):
640
ec86c89da78d Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
371 yield event
ec86c89da78d Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
372 ctxt.pop()
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
373
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
374 def __repr__(self):
860
16d55698006a A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
375 return '<%s>' % type(self).__name__
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
376
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
377
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
378 class IfDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
379 """Implementation of the ``py:if`` template directive for conditionally
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
380 excluding elements from being output.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
381
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
382 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
383 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
384 ... <b py:if="foo">${bar}</b>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
385 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
386 >>> print(tmpl.generate(foo=True, bar='Hello'))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
387 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
388 <b>Hello</b>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
389 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
390 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
391 __slots__ = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
392
822
70fddd2262f5 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
393 @classmethod
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
394 def attach(cls, template, stream, value, namespaces, pos):
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
395 if type(value) is dict:
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
396 value = value.get('test')
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
397 return super(IfDirective, cls).attach(template, stream, value,
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
398 namespaces, pos)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
399
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
400 def __call__(self, stream, directives, ctxt, **vars):
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
401 value = _eval_expr(self.expr, ctxt, vars)
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
402 if value:
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
403 return _apply_directives(stream, directives, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
404 return []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
405
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
406
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
407 class MatchDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
408 """Implementation of the ``py:match`` template directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
409
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
410 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
411 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
412 ... <span py:match="greeting">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
413 ... Hello ${select('@name')}
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
414 ... </span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
415 ... <greeting name="Dude" />
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
416 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
417 >>> print(tmpl.generate())
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
418 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
419 <span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
420 Hello Dude
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
421 </span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
422 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
423 """
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
424 __slots__ = ['path', 'namespaces', 'hints']
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
425
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
426 def __init__(self, value, template, hints=None, namespaces=None,
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
427 lineno=-1, offset=-1):
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
428 Directive.__init__(self, None, template, namespaces, lineno, offset)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
429 self.path = Path(value, template.filepath, lineno)
362
fe40d34fb71d 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: 351
diff changeset
430 self.namespaces = namespaces or {}
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
431 self.hints = hints or ()
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
432
822
70fddd2262f5 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
433 @classmethod
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
434 def attach(cls, template, stream, value, namespaces, pos):
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
435 hints = []
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
436 if type(value) is dict:
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
437 if value.get('buffer', '').lower() == 'false':
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
438 hints.append('not_buffered')
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
439 if value.get('once', '').lower() == 'true':
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
440 hints.append('match_once')
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
441 if value.get('recursive', '').lower() == 'false':
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
442 hints.append('not_recursive')
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
443 value = value.get('path')
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
444 return cls(value, template, frozenset(hints), namespaces, *pos[1:]), \
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
445 stream
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
446
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
447 def __call__(self, stream, directives, ctxt, **vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
448 ctxt._match_templates.append((self.path.test(ignore_context=True),
602
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
449 self.path, list(stream), self.hints,
d7b957e92ea9 Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
450 self.namespaces, directives))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
451 return []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
452
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
453 def __repr__(self):
860
16d55698006a A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
454 return '<%s "%s">' % (type(self).__name__, self.path.source)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
455
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
456
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
457 class ReplaceDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
458 """Implementation of the ``py:replace`` template directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
459
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
460 This directive replaces the element with the result of evaluating the
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
461 value of the ``py:replace`` attribute:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
462
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
463 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
464 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
465 ... <span py:replace="bar">Hello</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
466 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
467 >>> print(tmpl.generate(bar='Bye'))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
468 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
469 Bye
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
470 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
471
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
472 This directive is equivalent to ``py:content`` combined with ``py:strip``,
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
473 providing a less verbose way to achieve the same effect:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
474
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
475 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
476 ... <span py:content="bar" py:strip="">Hello</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
477 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
478 >>> print(tmpl.generate(bar='Bye'))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
479 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
480 Bye
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
481 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
482 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
483 __slots__ = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
484
822
70fddd2262f5 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
485 @classmethod
362
fe40d34fb71d 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: 351
diff changeset
486 def attach(cls, template, stream, value, namespaces, pos):
657
54964f7d2253 Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
487 if type(value) is dict:
54964f7d2253 Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
488 value = value.get('value')
436
57e8bd746717 Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
489 if not value:
57e8bd746717 Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
490 raise TemplateSyntaxError('missing value for "replace" directive',
57e8bd746717 Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
491 template.filepath, *pos[1:])
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
492 expr = cls._parse_expr(value, template, *pos[1:])
362
fe40d34fb71d 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: 351
diff changeset
493 return None, [(EXPR, expr, pos)]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
494
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
495
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
496 class StripDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
497 """Implementation of the ``py:strip`` template directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
498
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
499 When the value of the ``py:strip`` attribute evaluates to ``True``, the
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
500 element is stripped from the output
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
501
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
502 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
503 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
504 ... <div py:strip="True"><b>foo</b></div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
505 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
506 >>> print(tmpl.generate())
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
507 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
508 <b>foo</b>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
509 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
510
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
511 Leaving the attribute value empty is equivalent to a truth value.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
512
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
513 This directive is particulary interesting for named template functions or
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
514 match templates that do not generate a top-level element:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
515
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
516 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
517 ... <div py:def="echo(what)" py:strip="">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
518 ... <b>${what}</b>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
519 ... </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
520 ... ${echo('foo')}
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
521 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
522 >>> print(tmpl.generate())
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
523 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
524 <b>foo</b>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
525 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
526 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
527 __slots__ = []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
528
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
529 def __call__(self, stream, directives, ctxt, **vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
530 def _generate():
847
e16447a9605f Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents: 827
diff changeset
531 if not self.expr or _eval_expr(self.expr, ctxt, vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
532 stream.next() # skip start tag
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
533 previous = stream.next()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
534 for event in stream:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
535 yield previous
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
536 previous = event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
537 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
538 for event in stream:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
539 yield event
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
540 return _apply_directives(_generate(), directives, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
541
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
542
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
543 class ChooseDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
544 """Implementation of the ``py:choose`` directive for conditionally selecting
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
545 one of several body elements to display.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
546
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
547 If the ``py:choose`` expression is empty the expressions of nested
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
548 ``py:when`` directives are tested for truth. The first true ``py:when``
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
549 body is output. If no ``py:when`` directive is matched then the fallback
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
550 directive ``py:otherwise`` will be used.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
551
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
552 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
553 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/"
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
554 ... py:choose="">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
555 ... <span py:when="0 == 1">0</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
556 ... <span py:when="1 == 1">1</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
557 ... <span py:otherwise="">2</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
558 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
559 >>> print(tmpl.generate())
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
560 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
561 <span>1</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
562 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
563
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
564 If the ``py:choose`` directive contains an expression, the nested
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
565 ``py:when`` directives are tested for equality to the ``py:choose``
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
566 expression:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
567
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
568 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/"
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
569 ... py:choose="2">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
570 ... <span py:when="1">1</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
571 ... <span py:when="2">2</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
572 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
573 >>> print(tmpl.generate())
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
574 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
575 <span>2</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
576 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
577
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
578 Behavior is undefined if a ``py:choose`` block contains content outside a
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
579 ``py:when`` or ``py:otherwise`` block. Behavior is also undefined if a
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
580 ``py:otherwise`` occurs before ``py:when`` blocks.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
581 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
582 __slots__ = ['matched', 'value']
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
583
822
70fddd2262f5 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
584 @classmethod
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
585 def attach(cls, template, stream, value, namespaces, pos):
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
586 if type(value) is dict:
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
587 value = value.get('test')
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
588 return super(ChooseDirective, cls).attach(template, stream, value,
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
589 namespaces, pos)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
590
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
591 def __call__(self, stream, directives, ctxt, **vars):
562
b3dc05d88751 In the py:choose stack, store the information of whether a test expression has been supplied separate from the result of its evaluation.
cmlenz
parents: 553
diff changeset
592 info = [False, bool(self.expr), None]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
593 if self.expr:
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
594 info[2] = _eval_expr(self.expr, ctxt, vars)
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
595 ctxt._choice_stack.append(info)
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
596 for event in _apply_directives(stream, directives, ctxt, vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
597 yield event
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
598 ctxt._choice_stack.pop()
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
599
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
600
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
601 class WhenDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
602 """Implementation of the ``py:when`` directive for nesting in a parent with
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
603 the ``py:choose`` directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
604
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
605 See the documentation of the `ChooseDirective` for usage.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
606 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
607 __slots__ = ['filename']
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
608
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
609 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
610 Directive.__init__(self, value, template, namespaces, lineno, offset)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
611 self.filename = template.filepath
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
612
822
70fddd2262f5 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
613 @classmethod
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
614 def attach(cls, template, stream, value, namespaces, pos):
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
615 if type(value) is dict:
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
616 value = value.get('test')
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
617 return super(WhenDirective, cls).attach(template, stream, value,
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
618 namespaces, pos)
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
619
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
620 def __call__(self, stream, directives, ctxt, **vars):
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
621 info = ctxt._choice_stack and ctxt._choice_stack[-1]
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
622 if not info:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
623 raise TemplateRuntimeError('"when" directives can only be used '
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
624 'inside a "choose" directive',
935
59463031d904 Merge r1143 from py3k:
hodgestar
parents: 904
diff changeset
625 self.filename, *(stream.next())[2][1:])
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
626 if info[0]:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
627 return []
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
628 if not self.expr and not info[1]:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
629 raise TemplateRuntimeError('either "choose" or "when" directive '
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
630 'must have a test expression',
935
59463031d904 Merge r1143 from py3k:
hodgestar
parents: 904
diff changeset
631 self.filename, *(stream.next())[2][1:])
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
632 if info[1]:
562
b3dc05d88751 In the py:choose stack, store the information of whether a test expression has been supplied separate from the result of its evaluation.
cmlenz
parents: 553
diff changeset
633 value = info[2]
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
634 if self.expr:
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
635 matched = value == _eval_expr(self.expr, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
636 else:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
637 matched = bool(value)
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
638 else:
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
639 matched = bool(_eval_expr(self.expr, ctxt, vars))
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
640 info[0] = matched
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
641 if not matched:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
642 return []
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
643
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
644 return _apply_directives(stream, directives, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
645
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
646
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
647 class OtherwiseDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
648 """Implementation of the ``py:otherwise`` directive for nesting in a parent
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
649 with the ``py:choose`` directive.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
650
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
651 See the documentation of `ChooseDirective` for usage.
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
652 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
653 __slots__ = ['filename']
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
654
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
655 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
656 Directive.__init__(self, None, template, namespaces, lineno, offset)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
657 self.filename = template.filepath
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
658
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
659 def __call__(self, stream, directives, ctxt, **vars):
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
660 info = ctxt._choice_stack and ctxt._choice_stack[-1]
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
661 if not info:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
662 raise TemplateRuntimeError('an "otherwise" directive can only be '
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
663 'used inside a "choose" directive',
935
59463031d904 Merge r1143 from py3k:
hodgestar
parents: 904
diff changeset
664 self.filename, *(stream.next())[2][1:])
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
665 if info[0]:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
666 return []
553
489a47873950 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
667 info[0] = True
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
668
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
669 return _apply_directives(stream, directives, ctxt, vars)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
670
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
671
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
672 class WithDirective(Directive):
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
673 """Implementation of the ``py:with`` template directive, which allows
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
674 shorthand access to variables and expressions.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
675
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
676 >>> from genshi.template import MarkupTemplate
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
677 >>> tmpl = MarkupTemplate('''<div xmlns:py="http://genshi.edgewall.org/">
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
678 ... <span py:with="y=7; z=x+10">$x $y $z</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
679 ... </div>''')
853
f33ecf3c319e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
680 >>> print(tmpl.generate(x=42))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
681 <div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
682 <span>42 7 52</span>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
683 </div>
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
684 """
710
0af8f63514b8 Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
685 __slots__ = ['vars']
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
686
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
687 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
688 Directive.__init__(self, None, template, namespaces, lineno, offset)
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
689 self.vars = []
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
690 value = value.strip()
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
691 try:
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
692 ast = _parse(value, 'exec')
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
693 for node in ast.body:
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
694 if not isinstance(node, _ast.Assign):
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
695 raise TemplateSyntaxError('only assignment allowed in '
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
696 'value of the "with" directive',
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
697 template.filepath, lineno, offset)
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
698 self.vars.append(([_assignment(n) for n in node.targets],
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
699 Expression(node.value, template.filepath,
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
700 lineno, lookup=template.lookup)))
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
701 except SyntaxError, err:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
702 err.msg += ' in expression "%s" of "%s" directive' % (value,
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
703 self.tagname)
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
704 raise TemplateSyntaxError(err, template.filepath, lineno,
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
705 offset + (err.offset or 0))
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
706
822
70fddd2262f5 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
707 @classmethod
552
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
708 def attach(cls, template, stream, value, namespaces, pos):
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
709 if type(value) is dict:
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
710 value = value.get('vars')
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
711 return super(WithDirective, cls).attach(template, stream, value,
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
712 namespaces, pos)
b59d99d2f631 For directives used as elements, pass all attributes without a namespace to the directive class. This enables adding optional extra attributes to directives.
cmlenz
parents: 479
diff changeset
713
700
08f22328303d Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
714 def __call__(self, stream, directives, ctxt, **vars):
710
0af8f63514b8 Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
715 frame = {}
0af8f63514b8 Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
716 ctxt.push(frame)
794
f9e23d472a6e Merged AST branch back into trunk. Most of this code was written by Marcin Kurczych for his Google Summer of Code 2008 project. The merge of this branch means that Genshi now uses the native `_ast` module on Python >= 2.5, and an emulation thereof on Python 2.4. This replaces the usage of the `compiler` package, which was deprecated in Python 2.6 and removed in Python 3.0. Another effect is that Genshi now runs on Google AppEngine (although performance is bad due to the lack of template caching).
cmlenz
parents: 750
diff changeset
717 for targets, expr in self.vars:
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
718 value = _eval_expr(expr, ctxt, vars)
710
0af8f63514b8 Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
719 for assign in targets:
0af8f63514b8 Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
720 assign(frame, value)
827
bebc68529176 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
721 for event in _apply_directives(stream, directives, ctxt, vars):
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
722 yield event
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
723 ctxt.pop()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
724
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
725 def __repr__(self):
860
16d55698006a A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
726 return '<%s>' % (type(self).__name__)
Copyright (C) 2012-2017 Edgewall Software