annotate genshi/template/directives.py @ 935:705727288d7e

Merge r1143 from py3k: add support for python 3 to remaining genshi.template components: * minor changes to track encoding=None API change in core genshi modules. * genshi/template/directives: * slightly odd syntax changes to make the 2to3 .next() fixer pick up *stream.next() * minor test fix for change in behaviour of division (/) in Python 3. * genshi/template/loader: * add 'b' to file modes to ensure it's loaded as bytes in Python 3. * use not isinstance(s, unicode) instead of isinstance(s, str) since the former is correctly converted by 2to3.
author hodgestar
date Fri, 18 Mar 2011 09:17:52 +0000
parents 2772fa7c10a3
children
rev   line source
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
1 # -*- coding: utf-8 -*-
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
2 #
847
4f9e5e6f1aab Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents: 827
diff changeset
3 # Copyright (C) 2006-2009 Edgewall Software
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
4 # All rights reserved.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
5 #
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
9 #
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
13
5f2c7782cd8a 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."""
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
15
552
5458a4e8814c 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
5f2c7782cd8a 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
8dd0d34a9fb7 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
f7a5336dd389 Minor simplification in the expansion of dynamic attributes.
cmlenz
parents: 794
diff changeset
19 EXPR, _apply_directives, _eval_expr
794
ada9d53ea751 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, \
ada9d53ea751 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
22
5f2c7782cd8a 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',
5f2c7782cd8a 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',
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
25 'OtherwiseDirective', 'ReplaceDirective', 'StripDirective',
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
26 'WhenDirective', 'WithDirective']
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
27 __docformat__ = 'restructuredtext en'
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
28
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
29
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
30 class DirectiveMeta(type):
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
31 """Meta class for template directives."""
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
32
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
33 def __new__(cls, name, bases, d):
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
34 d['tagname'] = name.lower().replace('directive', '')
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
35 return type.__new__(cls, name, bases, d)
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
36
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
37
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
38 class Directive(object):
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
39 """Abstract base class for template directives.
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
40
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
41 A directive is basically a callable that takes three positional arguments:
425
5b248708bbed 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
5b248708bbed 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
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
44 other directives on the same stream that need to be applied.
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
45
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
46 Directives can be "anonymous" or "registered". Registered directives can be
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
47 applied by the template author using an XML attribute with the
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
48 corresponding name in the template. Such directives should be subclasses of
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
49 this base class that can be instantiated with the value of the directive
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
50 attribute as parameter.
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
51
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
52 Anonymous directives are simply functions conforming to the protocol
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
53 described above, and can only be applied programmatically (for example by
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
54 template filters).
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
55 """
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
56 __metaclass__ = DirectiveMeta
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
57 __slots__ = ['expr']
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
58
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
59 def __init__(self, value, template=None, namespaces=None, lineno=-1,
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
60 offset=-1):
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
61 self.expr = self._parse_expr(value, template, lineno, offset)
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
62
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
63 @classmethod
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
64 def attach(cls, template, stream, value, namespaces, pos):
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
65 """Called after the template stream has been completely parsed.
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
66
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
67 :param template: the `Template` object
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
68 :param stream: the event stream associated with the directive
552
5458a4e8814c 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
5458a4e8814c 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
5458a4e8814c 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
5458a4e8814c 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
73 :param namespaces: a mapping of namespace URIs to prefixes
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
74 :param pos: a ``(filename, lineno, offset)`` tuple describing the
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
75 location where the directive was found in the source
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
76
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
77 This class method should return a ``(directive, stream)`` tuple. If
5b248708bbed 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
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
79 class, and gets added to the list of directives applied to the substream
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
80 at runtime. `stream` is an event stream that replaces the original
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
81 stream associated with the directive.
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
82 """
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
83 return cls(value, template, namespaces, *pos[1:]), stream
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
84
700
8d079cee6822 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
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
86 """Apply the directive to the given stream.
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
87
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
88 :param stream: the event stream
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
89 :param directives: a list of the remaining directives that should
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
90 process the stream
700
8d079cee6822 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
8d079cee6822 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
8d079cee6822 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
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
94 """
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
95 raise NotImplementedError
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
96
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
97 def __repr__(self):
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
98 expr = ''
380
7be2baffea5a 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
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
100 expr = ' "%s"' % self.expr.source
860
61d37796da98 A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
101 return '<%s%s>' % (type(self).__name__, expr)
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
102
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
103 @classmethod
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
104 def _parse_expr(cls, expr, template, lineno=-1, offset=-1):
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
105 """Parses the given expression, raising a useful error message when a
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
106 syntax error is encountered.
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
107 """
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
108 try:
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
109 return expr and Expression(expr, template.filepath, lineno,
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
110 lookup=template.lookup) or None
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
111 except SyntaxError, err:
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
112 err.msg += ' in expression "%s" of "%s" directive' % (expr,
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
113 cls.tagname)
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
114 raise TemplateSyntaxError(err, template.filepath, lineno,
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
115 offset + (err.offset or 0))
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
116
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
117
336
5f2c7782cd8a 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
ada9d53ea751 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
ada9d53ea751 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
121 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
122 def _names(node):
794
ada9d53ea751 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):
ada9d53ea751 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])
ada9d53ea751 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):
ada9d53ea751 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
5f2c7782cd8a 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)):
5f2c7782cd8a 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:
5f2c7782cd8a 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)):
5f2c7782cd8a 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])
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
131 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
132 data[names] = value
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
133 return _assign
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
134
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
135
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
137 """Implementation of the ``py:attrs`` template directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
138
425
5b248708bbed 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
5b248708bbed 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
142
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
146 ... </ul>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
147 >>> print(tmpl.generate(foo={'class': 'collapse'}))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
148 <ul>
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
150 </ul>
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
151 >>> print(tmpl.generate(foo=[('class', 'collapse')]))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
152 <ul>
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
154 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
155
425
5b248708bbed 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
157 attributes are added:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
158
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
159 >>> print(tmpl.generate(foo=None))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
160 <ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
161 <li>Bar</li>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
162 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
163 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
164 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
165
700
8d079cee6822 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
167 def _generate():
5f2c7782cd8a 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
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
170 if attrs:
5f2c7782cd8a 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):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
172 try:
5f2c7782cd8a 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()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
174 except StopIteration:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
175 attrs = []
5f2c7782cd8a 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
5f2c7782cd8a 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
2772fa7c10a3 The `|` operator on `Attrs` objects now removes any existing attributes if the value is `None`.
cmlenz
parents: 860
diff changeset
178 attrib |= [
2772fa7c10a3 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)
2772fa7c10a3 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
2772fa7c10a3 The `|` operator on `Attrs` objects now removes any existing attributes if the value is `None`.
cmlenz
parents: 860
diff changeset
181 ]
336
5f2c7782cd8a 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
184 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
185
827
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
187
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
188
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
190 """Implementation of the ``py:content`` template directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
191
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
192 This directive replaces the content of the element with the result of
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
193 evaluating the value of the ``py:content`` attribute:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
194
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
198 ... </ul>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
199 >>> print(tmpl.generate(bar='Bye'))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
200 <ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
201 <li>Bye</li>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
202 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
203 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
204 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
205
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
206 @classmethod
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
207 def attach(cls, template, stream, value, namespaces, pos):
657
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
208 if type(value) is dict:
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
209 raise TemplateSyntaxError('The content directive can not be used '
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
210 'as an element', template.filepath,
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
211 *pos[1:])
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
212 expr = cls._parse_expr(value, template, *pos[1:])
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
213 return None, [stream[0], (EXPR, expr, pos), stream[-1]]
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
214
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
215
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
216 class DefDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
217 """Implementation of the ``py:def`` template directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
218
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
222 in the template.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
223
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
225 from template expressions:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
226
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
230 ... ${greeting}, ${name}!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
231 ... </p>
5f2c7782cd8a 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')}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
233 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
234 >>> print(tmpl.generate(bar='Bye'))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
235 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
236 <p class="message">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
237 Hi, you!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
238 </p>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
239 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
240
5f2c7782cd8a 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
4ff2338e89cd 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
243
5f2c7782cd8a 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/">
5f2c7782cd8a 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">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
246 ... Hello, world!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
247 ... </p>
343
4ff2338e89cd 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
249 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
250 >>> print(tmpl.generate(bar='Bye'))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
251 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
252 <p class="message">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
253 Hello, world!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
254 </p>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
255 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
256 """
479
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
257 __slots__ = ['name', 'args', 'star_args', 'dstar_args', 'defaults']
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
258
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
259 def __init__(self, args, template, namespaces=None, lineno=-1, offset=-1):
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
260 Directive.__init__(self, None, template, namespaces, lineno, offset)
794
ada9d53ea751 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
262 self.args = []
479
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
263 self.star_args = None
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
264 self.dstar_args = None
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
265 self.defaults = {}
794
ada9d53ea751 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):
ada9d53ea751 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
5f2c7782cd8a 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
ada9d53ea751 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
ada9d53ea751 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)
ada9d53ea751 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:
ada9d53ea751 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)
ada9d53ea751 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,
ada9d53ea751 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)
ada9d53ea751 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
ada9d53ea751 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):
ada9d53ea751 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
ada9d53ea751 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):
ada9d53ea751 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
280 else:
794
ada9d53ea751 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
282
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
283 @classmethod
552
5458a4e8814c 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):
5458a4e8814c 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:
5458a4e8814c 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')
5458a4e8814c 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,
5458a4e8814c 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)
5458a4e8814c 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
8d079cee6822 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
291 stream = list(stream)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
292
5f2c7782cd8a 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):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
294 scope = {}
5f2c7782cd8a 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
297 if args:
5f2c7782cd8a 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)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
299 else:
5f2c7782cd8a 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:
5f2c7782cd8a 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)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
302 else:
827
0319a8874510 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
5f2c7782cd8a 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
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
305 if not self.star_args is None:
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
306 scope[self.star_args] = args
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
307 if not self.dstar_args is None:
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
308 scope[self.dstar_args] = kwargs
336
5f2c7782cd8a 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
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
311 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
312 ctxt.pop()
750
d007a0d7ba81 Remove some cruft for supporting Python 2.3.
cmlenz
parents: 719
diff changeset
313 function.__name__ = self.name
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
314
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
319
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
320 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
321
5f2c7782cd8a 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
61d37796da98 A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
323 return '<%s "%s">' % (type(self).__name__, self.name)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
324
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
325
5f2c7782cd8a 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
5b248708bbed 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
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
329
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
333 ... </ul>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
334 >>> print(tmpl.generate(items=[1, 2, 3]))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
335 <ul>
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
337 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
338 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
339 __slots__ = ['assign', 'filename']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
340
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
341 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
336
5f2c7782cd8a 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:
5f2c7782cd8a 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
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
344 template.filepath, lineno, offset)
336
5f2c7782cd8a 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)
5f2c7782cd8a 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
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
347 value = 'iter(%s)' % value.strip()
794
ada9d53ea751 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
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
349 self.filename = template.filepath
640
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
350 Directive.__init__(self, value, template, namespaces, lineno, offset)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
351
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
352 @classmethod
552
5458a4e8814c 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):
5458a4e8814c 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:
5458a4e8814c 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')
5458a4e8814c 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,
5458a4e8814c 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)
5458a4e8814c 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
8d079cee6822 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
0319a8874510 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
362 return
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
363
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
364 assign = self.assign
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
365 scope = {}
5f2c7782cd8a 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
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
367 for item in iterable:
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
368 assign(scope, item)
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
369 ctxt.push(scope)
827
0319a8874510 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
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
371 yield event
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
372 ctxt.pop()
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
373
5f2c7782cd8a 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
61d37796da98 A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
375 return '<%s>' % type(self).__name__
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
376
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
377
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
379 """Implementation of the ``py:if`` template directive for conditionally
336
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
381
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
385 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
386 >>> print(tmpl.generate(foo=True, bar='Hello'))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
387 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
388 <b>Hello</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
389 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
390 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
391 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
392
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
393 @classmethod
552
5458a4e8814c 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):
5458a4e8814c 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:
5458a4e8814c 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')
5458a4e8814c 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,
5458a4e8814c 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
399
700
8d079cee6822 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
0319a8874510 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
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
402 if value:
827
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
404 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
405
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
406
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
407 class MatchDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
408 """Implementation of the ``py:match`` template directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
409
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
413 ... Hello ${select('@name')}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
414 ... </span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
415 ... <greeting name="Dude" />
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
416 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
417 >>> print(tmpl.generate())
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
418 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
419 <span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
420 Hello Dude
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
421 </span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
422 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
423 """
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
424 __slots__ = ['path', 'namespaces', 'hints']
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
425
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
426 def __init__(self, value, template, hints=None, namespaces=None,
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
427 lineno=-1, offset=-1):
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
428 Directive.__init__(self, None, template, namespaces, lineno, offset)
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
429 self.path = Path(value, template.filepath, lineno)
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
430 self.namespaces = namespaces or {}
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
431 self.hints = hints or ()
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
432
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
433 @classmethod
552
5458a4e8814c 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
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
435 hints = []
552
5458a4e8814c 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
8d079cee6822 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':
8d079cee6822 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
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
439 if value.get('once', '').lower() == 'true':
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
440 hints.append('match_once')
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
441 if value.get('recursive', '').lower() == 'false':
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
442 hints.append('not_recursive')
552
5458a4e8814c 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
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
444 return cls(value, template, frozenset(hints), namespaces, *pos[1:]), \
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
445 stream
552
5458a4e8814c 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
8d079cee6822 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
5f2c7782cd8a 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
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
449 self.path, list(stream), self.hints,
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
450 self.namespaces, directives))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
451 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
452
5f2c7782cd8a 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
61d37796da98 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
455
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
456
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
458 """Implementation of the ``py:replace`` template directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
459
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
461 value of the ``py:replace`` attribute:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
462
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
466 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
467 >>> print(tmpl.generate(bar='Bye'))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
468 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
469 Bye
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
470 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
471
425
5b248708bbed 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
474
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
477 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
478 >>> print(tmpl.generate(bar='Bye'))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
479 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
480 Bye
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
481 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
482 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
483 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
484
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
485 @classmethod
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
486 def attach(cls, template, stream, value, namespaces, pos):
657
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
487 if type(value) is dict:
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
488 value = value.get('value')
436
85ae2dee949b Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
489 if not value:
85ae2dee949b Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
490 raise TemplateSyntaxError('missing value for "replace" directive',
85ae2dee949b Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
491 template.filepath, *pos[1:])
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
492 expr = cls._parse_expr(value, template, *pos[1:])
362
0910d5978f45 Follow-up to [431]: directives are no longer instantiated directly at parse time, but instead by the `attach()` method of the directive class (which replaces the `prepare()` method).
cmlenz
parents: 351
diff changeset
493 return None, [(EXPR, expr, pos)]
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
494
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
495
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
497 """Implementation of the ``py:strip`` template directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
498
425
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
500 element is stripped from the output
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
501
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
505 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
506 >>> print(tmpl.generate())
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
507 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
508 <b>foo</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
509 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
510
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
511 Leaving the attribute value empty is equivalent to a truth value.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
512
5f2c7782cd8a 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
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
515
5f2c7782cd8a 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/">
5f2c7782cd8a 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="">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
518 ... <b>${what}</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
519 ... </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
520 ... ${echo('foo')}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
521 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
522 >>> print(tmpl.generate())
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
523 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
524 <b>foo</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
525 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
526 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
527 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
528
700
8d079cee6822 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
530 def _generate():
847
4f9e5e6f1aab Backported a couple of templating core changes from the advanced-i18n branch, in particular considering the determination of directive ordering../set
cmlenz
parents: 827
diff changeset
531 if not self.expr or _eval_expr(self.expr, ctxt, vars):
336
5f2c7782cd8a 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
533 previous = stream.next()
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
535 yield previous
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
536 previous = event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
537 else:
5f2c7782cd8a 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:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
539 yield event
827
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
541
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
542
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
544 """Implementation of the ``py:choose`` directive for conditionally selecting
336
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
546
425
5b248708bbed 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
5b248708bbed 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``
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
550 directive ``py:otherwise`` will be used.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
551
5f2c7782cd8a 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
5f2c7782cd8a 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/"
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
554 ... py:choose="">
5f2c7782cd8a 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>
5f2c7782cd8a 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>
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
558 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
559 >>> print(tmpl.generate())
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
560 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
561 <span>1</span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
562 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
563
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
564 If the ``py:choose`` directive contains an expression, the nested
5b248708bbed 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``
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
566 expression:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
567
5f2c7782cd8a 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/"
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
569 ... py:choose="2">
5f2c7782cd8a 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>
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
572 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
573 >>> print(tmpl.generate())
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
574 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
575 <span>2</span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
576 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
577
425
5b248708bbed 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
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
580 ``py:otherwise`` occurs before ``py:when`` blocks.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
581 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
582 __slots__ = ['matched', 'value']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
583
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
584 @classmethod
552
5458a4e8814c 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):
5458a4e8814c 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:
5458a4e8814c 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')
5458a4e8814c 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,
5458a4e8814c 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
590
700
8d079cee6822 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
21f3c4bdd964 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
5f2c7782cd8a 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
0319a8874510 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
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
595 ctxt._choice_stack.append(info)
827
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
597 yield event
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
598 ctxt._choice_stack.pop()
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
599
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
600
5f2c7782cd8a 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
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
603 the ``py:choose`` directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
604
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
605 See the documentation of the `ChooseDirective` for usage.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
606 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
607 __slots__ = ['filename']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
608
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
609 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
610 Directive.__init__(self, value, template, namespaces, lineno, offset)
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
611 self.filename = template.filepath
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
612
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
613 @classmethod
552
5458a4e8814c 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):
5458a4e8814c 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:
5458a4e8814c 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')
5458a4e8814c 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,
5458a4e8814c 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)
5458a4e8814c 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
8d079cee6822 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
887bbbfa4098 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]
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
622 if not info:
336
5f2c7782cd8a 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 '
5f2c7782cd8a 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
705727288d7e Merge r1143 from py3k:
hodgestar
parents: 904
diff changeset
625 self.filename, *(stream.next())[2][1:])
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
626 if info[0]:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
627 return []
553
887bbbfa4098 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
5f2c7782cd8a 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 '
5f2c7782cd8a 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
705727288d7e Merge r1143 from py3k:
hodgestar
parents: 904
diff changeset
631 self.filename, *(stream.next())[2][1:])
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
632 if info[1]:
562
21f3c4bdd964 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
5f2c7782cd8a 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
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
636 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
637 matched = bool(value)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
638 else:
827
0319a8874510 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
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
640 info[0] = matched
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
641 if not matched:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
642 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
643
827
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
645
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
646
5f2c7782cd8a 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
5b248708bbed 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
649 with the ``py:choose`` directive.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
650
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
651 See the documentation of `ChooseDirective` for usage.
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
652 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
653 __slots__ = ['filename']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
654
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
655 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
656 Directive.__init__(self, None, template, namespaces, lineno, offset)
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
657 self.filename = template.filepath
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
658
700
8d079cee6822 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
887bbbfa4098 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]
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
661 if not info:
336
5f2c7782cd8a 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 '
5f2c7782cd8a 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
705727288d7e Merge r1143 from py3k:
hodgestar
parents: 904
diff changeset
664 self.filename, *(stream.next())[2][1:])
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
665 if info[0]:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
666 return []
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
667 info[0] = True
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
668
827
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
670
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
671
5f2c7782cd8a 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
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
673 """Implementation of the ``py:with`` template directive, which allows
336
5f2c7782cd8a 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.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
675
5f2c7782cd8a 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
5f2c7782cd8a 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/">
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
679 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
680 >>> print(tmpl.generate(x=42))
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
681 <div>
5f2c7782cd8a 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>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
683 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
684 """
710
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
685 __slots__ = ['vars']
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
686
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
687 def __init__(self, value, template, namespaces=None, lineno=-1, offset=-1):
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
688 Directive.__init__(self, None, template, namespaces, lineno, offset)
794
ada9d53ea751 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 = []
ada9d53ea751 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
691 try:
794
ada9d53ea751 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')
ada9d53ea751 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:
ada9d53ea751 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):
ada9d53ea751 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 '
ada9d53ea751 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',
ada9d53ea751 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)
ada9d53ea751 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],
ada9d53ea751 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,
ada9d53ea751 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
701 except SyntaxError, err:
5f2c7782cd8a 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,
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
703 self.tagname)
442
ff7c72b52fb2 Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 436
diff changeset
704 raise TemplateSyntaxError(err, template.filepath, lineno,
336
5f2c7782cd8a 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))
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
706
822
ce5ad2d540b3 Get rid of some Python 2.3 legacy that's no longer needed now that 2.4 is the baseline.
cmlenz
parents: 817
diff changeset
707 @classmethod
552
5458a4e8814c 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):
5458a4e8814c 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:
5458a4e8814c 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')
5458a4e8814c 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,
5458a4e8814c 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)
5458a4e8814c 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
8d079cee6822 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
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
715 frame = {}
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
716 ctxt.push(frame)
794
ada9d53ea751 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
0319a8874510 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
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
719 for assign in targets:
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
720 assign(frame, value)
827
0319a8874510 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
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
722 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
723 ctxt.pop()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
724
5f2c7782cd8a 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
61d37796da98 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