Mercurial > genshi > mirror
annotate genshi/template/directives.py @ 704:422d0607ba85 experimental-match-fastpaths
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.
Also fixes a bug where we could get duplicate match indexes when a new match is created while evaluating an existing match
Also, try to be lazy about creating the first MatchSet so that we don't hurt bigtable performance (i.e. when there are no py:matches in play at all)
author | aflett |
---|---|
date | Fri, 04 Apr 2008 16:57:27 +0000 |
parents | af57b12e3dd2 |
children | 2a7a19861a89 |
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 | 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 | 17 try: |
18 frozenset | |
19 except NameError: | |
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 | 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 | 214 if type(value) is dict: |
215 raise TemplateSyntaxError('The content directive can not be used ' | |
216 'as an element', template.filepath, | |
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 | 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 | 270 self.star_args = None |
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 | 284 if ast.star_args: |
285 self.star_args = ast.star_args.name | |
286 if ast.dstar_args: | |
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 | 313 if not self.star_args is None: |
314 scope[self.star_args] = args | |
315 if not self.dstar_args is None: | |
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 | 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 | 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 | 379 for item in iterable: |
380 assign(scope, item) | |
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 | 383 yield event |
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 | 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 | 438 def __init__(self, value, template, hints=None, namespaces=None, |
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 | 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 | 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 | 450 if value.get('once', '').lower() == 'true': |
451 hints.append('match_once') | |
452 if value.get('recursive', '').lower() == 'false': | |
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 | 455 return cls(value, template, frozenset(hints), namespaces, *pos[1:]), \ |
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): |
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
|
460 if ctx._match_set is None: |
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
|
461 # lazily create MatchSet so that it doesn't burden the |
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
|
462 # _match filter when there are no py:matches defined. |
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
|
463 ctx._match_set = MatchSet() |
687
3d7288f373bd
land first cut at fast-path matching - needs some cleanup
aflett
parents:
684
diff
changeset
|
464 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
|
465 self.path, list(stream), self.hints, |
3d7288f373bd
land first cut at fast-path matching - needs some cleanup
aflett
parents:
684
diff
changeset
|
466 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
|
467 return [] |
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 def __repr__(self): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
470 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
|
471 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
472 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
473 class ReplaceDirective(Directive): |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
474 """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
|
475 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
476 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
|
477 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
|
478 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
479 >>> 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
|
480 >>> 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
|
481 ... <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
|
482 ... </div>''') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
483 >>> 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
|
484 <div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
485 Bye |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
486 </div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
487 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
488 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
|
489 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
|
490 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
491 >>> 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
|
492 ... <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
|
493 ... </div>''') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
494 >>> 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
|
495 <div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
496 Bye |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
497 </div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
498 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
499 __slots__ = [] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
500 |
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
|
501 def attach(cls, template, stream, value, namespaces, pos): |
657 | 502 if type(value) is dict: |
503 value = value.get('value') | |
436
57e8bd746717
Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents:
425
diff
changeset
|
504 if not value: |
57e8bd746717
Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents:
425
diff
changeset
|
505 raise TemplateSyntaxError('missing value for "replace" directive', |
57e8bd746717
Raise syntax error on empty value for `py:replace` directive.
cmlenz
parents:
425
diff
changeset
|
506 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
|
507 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
|
508 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
|
509 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
|
510 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
511 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
512 class StripDirective(Directive): |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
513 """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
|
514 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
515 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
|
516 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
|
517 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
518 >>> 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
|
519 >>> 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
|
520 ... <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
|
521 ... </div>''') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
522 >>> print tmpl.generate() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
523 <div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
524 <b>foo</b> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
525 </div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
526 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
527 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
|
528 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
529 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
|
530 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
|
531 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
532 >>> 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
|
533 ... <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
|
534 ... <b>${what}</b> |
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 ... ${echo('foo')} |
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 >>> print tmpl.generate() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
539 <div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
540 <b>foo</b> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
541 </div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
542 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
543 __slots__ = [] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
544 |
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
|
545 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
|
546 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
|
547 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
|
548 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
|
549 previous = stream.next() |
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 previous |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
552 previous = event |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
553 else: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
554 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
|
555 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
|
556 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
|
557 |
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
|
558 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
|
559 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
|
560 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
|
561 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
|
562 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
|
563 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
|
564 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
565 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
566 class ChooseDirective(Directive): |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
567 """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
|
568 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
|
569 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
570 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
|
571 ``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
|
572 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
|
573 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
|
574 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
575 >>> 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
|
576 >>> 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
|
577 ... py:choose=""> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
578 ... <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
|
579 ... <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
|
580 ... <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
|
581 ... </div>''') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
582 >>> print tmpl.generate() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
583 <div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
584 <span>1</span> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
585 </div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
586 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
587 If the ``py:choose`` directive contains an expression, the nested |
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
588 ``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
|
589 expression: |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
590 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
591 >>> 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
|
592 ... py:choose="2"> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
593 ... <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
|
594 ... <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
|
595 ... </div>''') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
596 >>> print tmpl.generate() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
597 <div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
598 <span>2</span> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
599 </div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
600 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
601 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
|
602 ``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
|
603 ``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
|
604 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
605 __slots__ = ['matched', 'value'] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
606 |
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
|
607 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
|
608 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
|
609 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
|
610 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
|
611 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
|
612 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
|
613 |
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
|
614 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
|
615 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
|
616 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
|
617 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
|
618 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
|
619 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
|
620 yield event |
553
489a47873950
Store state information for py:choose outside of the regular context data.
cmlenz
parents:
552
diff
changeset
|
621 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
|
622 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
623 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
624 class WhenDirective(Directive): |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
625 """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
|
626 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
|
627 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
628 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
|
629 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
630 __slots__ = ['filename'] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
631 |
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
|
632 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
|
633 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
|
634 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
|
635 |
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
|
636 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
|
637 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
|
638 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
|
639 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
|
640 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
|
641 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
|
642 |
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
|
643 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
|
644 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
|
645 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
|
646 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
|
647 '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
|
648 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
|
649 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
|
650 return [] |
553
489a47873950
Store state information for py:choose outside of the regular context data.
cmlenz
parents:
552
diff
changeset
|
651 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
|
652 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
|
653 '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
|
654 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
|
655 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
|
656 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
|
657 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
|
658 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
|
659 else: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
660 matched = bool(value) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
661 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
|
662 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
|
663 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
|
664 if not matched: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
665 return [] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
666 |
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
|
667 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
|
668 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
669 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
670 class OtherwiseDirective(Directive): |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
671 """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
|
672 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
|
673 |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
674 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
|
675 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
676 __slots__ = ['filename'] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
677 |
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
|
678 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
|
679 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
|
680 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
|
681 |
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
|
682 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
|
683 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
|
684 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
|
685 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
|
686 '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
|
687 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
|
688 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
|
689 return [] |
553
489a47873950
Store state information for py:choose outside of the regular context data.
cmlenz
parents:
552
diff
changeset
|
690 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
|
691 |
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
|
692 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
|
693 |
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 class WithDirective(Directive): |
425
073640758a42
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
422
diff
changeset
|
696 """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
|
697 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
|
698 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
699 >>> 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
|
700 >>> 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
|
701 ... <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
|
702 ... </div>''') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
703 >>> 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
|
704 <div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
705 <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
|
706 </div> |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
707 """ |
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
|
708 __slots__ = ['suite'] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
709 |
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
|
710 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
|
711 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
|
712 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
|
713 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
|
714 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
|
715 xform=ExpressionASTTransformer) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
716 except SyntaxError, err: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
717 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
|
718 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
|
719 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
|
720 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
|
721 |
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
|
722 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
|
723 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
|
724 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
|
725 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
|
726 '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
|
727 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
|
728 |
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
|
729 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
|
730 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
|
731 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
|
732 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
|
733 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
|
734 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
|
735 |
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
|
736 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
|
737 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
|
738 _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
|
739 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
|
740 yield event |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
741 ctxt.pop() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
742 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
743 def __repr__(self): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
744 return '<%s>' % (self.__class__.__name__) |