annotate genshi/template/directives.py @ 879:27d210790d27

Looks like the 'decorators' field in the AST was renamed to 'decorator_list' in Python 2.6, so look for both. See #379.
author cmlenz
date Thu, 15 Apr 2010 21:38:21 +0000
parents 61d37796da98
children 2772fa7c10a3
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()
345
8e75b83d3e71 Make `Attrs` instances immutable.
cmlenz
parents: 343
diff changeset
178 attrib -= [name for name, val in attrs if val is None]
403
32b283e1d310 Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents: 400
diff changeset
179 attrib |= [(QName(name), unicode(val).strip()) for name, val
32b283e1d310 Remove some magic/overhead from `Attrs` creation and manipulation by not automatically wrapping attribute names in `QName`.
cmlenz
parents: 400
diff changeset
180 in attrs if val is not None]
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
181 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
182 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
183 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
184
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
185 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
186
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 class ContentDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
189 """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
190
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
191 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
192 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
193
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
194 >>> 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
195 >>> 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
196 ... <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
197 ... </ul>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
198 >>> 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
199 <ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
200 <li>Bye</li>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
201 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
202 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
203 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
204
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
205 @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
206 def attach(cls, template, stream, value, namespaces, pos):
657
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
207 if type(value) is dict:
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
208 raise TemplateSyntaxError('The content directive can not be used '
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
209 'as an element', template.filepath,
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
210 *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
211 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
212 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
213
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 class DefDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
216 """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
217
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
218 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
219 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
220 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
221 in the template.
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
222
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
223 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
224 from template expressions:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
225
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
226 >>> 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
227 >>> 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
228 ... <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
229 ... ${greeting}, ${name}!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
230 ... </p>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
231 ... ${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
232 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
233 >>> 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
234 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
235 <p class="message">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
236 Hi, you!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
237 </p>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
238 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
239
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
240 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
241 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
242
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
243 >>> 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
244 ... <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
245 ... Hello, world!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
246 ... </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
247 ... ${helloworld()}
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
248 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
249 >>> 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
250 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
251 <p class="message">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
252 Hello, world!
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
253 </p>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
254 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
255 """
479
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
256 __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
257
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
258 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
259 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
260 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
261 self.args = []
479
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
262 self.star_args = None
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
263 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
264 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
265 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
266 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
267 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
268 # 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
269 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
270 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
271 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
272 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
273 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
274 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
275 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
276 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
277 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
278 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
279 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
280 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
281
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
282 @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
283 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
284 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
285 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
286 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
287 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
288
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
289 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
290 stream = list(stream)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
291
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
292 def function(*args, **kwargs):
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
293 scope = {}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
294 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
295 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
296 if args:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
297 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
298 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
299 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
300 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
301 else:
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
302 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
303 scope[name] = val
479
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
304 if not self.star_args is None:
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
305 scope[self.star_args] = args
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
306 if not self.dstar_args is None:
9c83be4a0e4a Apply patch for #116.
cmlenz
parents: 442
diff changeset
307 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
308 ctxt.push(scope)
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
309 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
310 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
311 ctxt.pop()
750
d007a0d7ba81 Remove some cruft for supporting Python 2.3.
cmlenz
parents: 719
diff changeset
312 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
313
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
314 # 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
315 # 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
316 # 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
317 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
318
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
319 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
320
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
321 def __repr__(self):
860
61d37796da98 A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
322 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
323
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 class ForDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
326 """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
327 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
328
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
329 >>> 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
330 >>> 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
331 ... <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
332 ... </ul>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
333 >>> 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
334 <ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
335 <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
336 </ul>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
337 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
338 __slots__ = ['assign', 'filename']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
339
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
340 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
341 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
342 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
343 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
344 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
345 ast = _parse(assign, 'exec')
640
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
346 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
347 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
348 self.filename = template.filepath
640
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
349 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
350
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
351 @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
352 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
353 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
354 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
355 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
356 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
357
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
358 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
359 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
360 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
361 return
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
362
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
363 assign = self.assign
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
364 scope = {}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
365 stream = list(stream)
640
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
366 for item in iterable:
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
367 assign(scope, item)
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
368 ctxt.push(scope)
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
369 for event in _apply_directives(stream, directives, ctxt, vars):
640
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
370 yield event
0e278535c67c Don't mask errors in `py:for`.
cmlenz
parents: 604
diff changeset
371 ctxt.pop()
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
372
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
373 def __repr__(self):
860
61d37796da98 A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
374 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
375
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 class IfDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
378 """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
379 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
380
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
381 >>> 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
382 >>> 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
383 ... <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
384 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
385 >>> 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
386 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
387 <b>Hello</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
388 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
389 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
390 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
391
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
392 @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
393 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
394 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
395 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
396 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
397 namespaces, pos)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
398
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
399 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
400 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
401 if value:
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
402 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
403 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
404
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 class MatchDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
407 """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
408
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
409 >>> 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
410 >>> 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
411 ... <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
412 ... Hello ${select('@name')}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
413 ... </span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
414 ... <greeting name="Dude" />
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
415 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
416 >>> 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
417 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
418 <span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
419 Hello Dude
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
420 </span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
421 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
422 """
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
423 __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
424
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
425 def __init__(self, value, template, hints=None, namespaces=None,
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
426 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
427 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
428 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
429 self.namespaces = namespaces or {}
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
430 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
431
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
432 @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
433 def attach(cls, template, stream, value, namespaces, pos):
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
434 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
435 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
436 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
437 hints.append('not_buffered')
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
438 if value.get('once', '').lower() == 'true':
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
439 hints.append('match_once')
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
440 if value.get('recursive', '').lower() == 'false':
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
441 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
442 value = value.get('path')
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
443 return cls(value, template, frozenset(hints), namespaces, *pos[1:]), \
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
444 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
445
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
446 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
447 ctxt._match_templates.append((self.path.test(ignore_context=True),
602
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
448 self.path, list(stream), self.hints,
509b3a5e765e Add runtime optimization hints for match templates.
cmlenz
parents: 601
diff changeset
449 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
450 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
451
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
452 def __repr__(self):
860
61d37796da98 A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
453 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
454
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 class ReplaceDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
457 """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
458
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
459 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
460 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
461
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
462 >>> 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
463 >>> 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
464 ... <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
465 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
466 >>> 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
467 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
468 Bye
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
469 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
470
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
471 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
472 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
473
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
474 >>> 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
475 ... <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
476 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
477 >>> 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
478 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
479 Bye
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
480 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
481 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
482 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
483
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
484 @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
485 def attach(cls, template, stream, value, namespaces, pos):
657
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
486 if type(value) is dict:
69b3b6ca968b Allow use of py:replace as element. Closes #144.
cmlenz
parents: 640
diff changeset
487 value = value.get('value')
436
85ae2dee949b Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
488 if not value:
85ae2dee949b Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
489 raise TemplateSyntaxError('missing value for "replace" directive',
85ae2dee949b Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents: 425
diff changeset
490 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
491 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
492 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
493
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 class StripDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
496 """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
497
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
498 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
499 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
500
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
501 >>> 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
502 >>> 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
503 ... <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
504 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
505 >>> 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
506 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
507 <b>foo</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
508 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
509
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
510 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
511
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
512 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
513 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
514
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
515 >>> 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
516 ... <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
517 ... <b>${what}</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
518 ... </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
519 ... ${echo('foo')}
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
520 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
521 >>> 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
522 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
523 <b>foo</b>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
524 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
525 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
526 __slots__ = []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
527
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
528 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
529 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
530 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
531 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
532 previous = stream.next()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
533 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
534 yield previous
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
535 previous = event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
536 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
537 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
538 yield event
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
539 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
540
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 class ChooseDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
543 """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
544 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
545
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
546 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
547 ``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
548 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
549 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
550
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
551 >>> 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
552 >>> 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
553 ... py:choose="">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
554 ... <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
555 ... <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
556 ... <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
557 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
558 >>> 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
559 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
560 <span>1</span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
561 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
562
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
563 If the ``py:choose`` directive contains an expression, the nested
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
564 ``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
565 expression:
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
566
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
567 >>> 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
568 ... py:choose="2">
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
569 ... <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
570 ... <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
571 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
572 >>> 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
573 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
574 <span>2</span>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
575 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
576
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
577 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
578 ``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
579 ``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
580 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
581 __slots__ = ['matched', 'value']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
582
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
583 @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
584 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
585 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
586 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
587 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
588 namespaces, pos)
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
589
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
590 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
591 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
592 if self.expr:
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
593 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
594 ctxt._choice_stack.append(info)
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
595 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
596 yield event
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
597 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
598
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 class WhenDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
601 """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
602 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
603
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
604 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
605 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
606 __slots__ = ['filename']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
607
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
608 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
609 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
610 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
611
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
612 @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
613 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
614 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
615 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
616 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
617 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
618
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
619 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
620 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
621 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
622 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
623 'inside a "choose" directive',
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
624 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
625 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
626 return []
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
627 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
628 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
629 'must have a test expression',
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
630 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
631 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
632 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
633 if self.expr:
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
634 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
635 else:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
636 matched = bool(value)
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
637 else:
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
638 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
639 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
640 if not matched:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
641 return []
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
642
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
643 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
644
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 class OtherwiseDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
647 """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
648 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
649
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
650 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
651 """
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
652 __slots__ = ['filename']
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
653
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
654 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
655 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
656 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
657
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
658 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
659 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
660 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
661 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
662 'used inside a "choose" directive',
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
663 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
664 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
665 return []
553
887bbbfa4098 Store state information for py:choose outside of the regular context data.
cmlenz
parents: 552
diff changeset
666 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
667
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
668 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
669
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 class WithDirective(Directive):
425
5b248708bbed Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 422
diff changeset
672 """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
673 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
674
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
675 >>> 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
676 >>> 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
677 ... <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
678 ... </div>''')
853
4376010bb97e Convert a bunch of print statements to py3k compatible syntax.
cmlenz
parents: 847
diff changeset
679 >>> 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
680 <div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
681 <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
682 </div>
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
683 """
710
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
684 __slots__ = ['vars']
336
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
685
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
686 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
687 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
688 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
689 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
690 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
691 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
692 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
693 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
694 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
695 '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
696 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
697 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
698 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
699 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
700 except SyntaxError, err:
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
701 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
702 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
703 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
704 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
705
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
706 @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
707 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
708 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
709 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
710 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
711 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
712
700
8d079cee6822 Add option for unbuffered match template processing, which could cause excessive memory usage. Closes #190.
cmlenz
parents: 684
diff changeset
713 def __call__(self, stream, directives, ctxt, **vars):
710
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
714 frame = {}
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
715 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
716 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
717 value = _eval_expr(expr, ctxt, vars)
710
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
718 for assign in targets:
cd2d87ec371d Partially revert [717] to retain compatibility with Python 2.3.
cmlenz
parents: 700
diff changeset
719 assign(frame, value)
827
0319a8874510 Avoid varargs on internal functions in template processing for slightly better performance.
cmlenz
parents: 822
diff changeset
720 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
721 yield event
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
722 ctxt.pop()
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
723
5f2c7782cd8a Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
724 def __repr__(self):
860
61d37796da98 A bit of cleanup of the `Markup` Python implementation.
cmlenz
parents: 853
diff changeset
725 return '<%s>' % (type(self).__name__)
Copyright (C) 2012-2017 Edgewall Software