annotate genshi/template/directives.py @ 711:0cc3f1eabe13 experimental-match-fastpaths

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