Mercurial > genshi > mirror
annotate genshi/template/eval.py @ 405:5340931530e2 trunk
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
author | cmlenz |
---|---|
date | Wed, 21 Feb 2007 10:26:38 +0000 |
parents | 68772732c896 |
children | 01be13831f5e |
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 # |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
3 # Copyright (C) 2006 Edgewall Software |
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 """Support for "safe" evaluation of Python expressions.""" |
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 __builtin__ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
17 from compiler import ast, parse |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
18 from compiler.pycodegen import ExpressionCodeGenerator, ModuleCodeGenerator |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
19 import new |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
20 try: |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
21 set |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
22 except NameError: |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
23 from sets import Set as set |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
24 import sys |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
25 |
401
68772732c896
Make the `Markup` class available by default in template expressions. Closes #67.
cmlenz
parents:
396
diff
changeset
|
26 from genshi.core import Markup |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
27 from genshi.util import flatten |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
28 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
29 __all__ = ['Expression', 'Suite', 'Undefined'] |
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 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
32 class Code(object): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
33 """Abstract base class for the `Expression` and `Suite` classes.""" |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
34 __slots__ = ['source', 'code'] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
35 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
36 def __init__(self, source, filename=None, lineno=-1): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
37 """Create the code object, either from a string, or from an AST node. |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
38 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
39 @param source: either a string containing the source code, or an AST |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
40 node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
41 @param filename: the (preferably absolute) name of the file containing |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
42 the code |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
43 @param lineno: the number of the line on which the code was found |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
44 """ |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
45 if isinstance(source, basestring): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
46 self.source = source |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
47 node = _parse(source, mode=self.mode) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
48 else: |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
49 assert isinstance(source, ast.Node) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
50 self.source = '?' |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
51 if self.mode == 'eval': |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
52 node = ast.Expression(source) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
53 else: |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
54 node = ast.Module(None, source) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
55 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
56 self.code = _compile(node, self.source, mode=self.mode, |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
57 filename=filename, lineno=lineno) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
58 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
59 def __eq__(self, other): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
60 return (type(other) == type(self)) and (self.code == other.code) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
61 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
62 def __hash__(self): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
63 return hash(self.code) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
64 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
65 def __ne__(self, other): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
66 return not self == other |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
67 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
68 def __repr__(self): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
69 return '%s(%r)' % (self.__class__.__name__, self.source) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
70 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
71 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
72 class Expression(Code): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
73 """Evaluates Python expressions used in templates. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
74 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
75 >>> data = dict(test='Foo', items=[1, 2, 3], dict={'some': 'thing'}) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
76 >>> Expression('test').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
77 'Foo' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
78 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
79 >>> Expression('items[0]').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
80 1 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
81 >>> Expression('items[-1]').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
82 3 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
83 >>> Expression('dict["some"]').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
84 'thing' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
85 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
86 Similar to e.g. Javascript, expressions in templates can use the dot |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
87 notation for attribute access to access items in mappings: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
88 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
89 >>> Expression('dict.some').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
90 'thing' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
91 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
92 This also works the other way around: item access can be used to access |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
93 any object attribute (meaning there's no use for `getattr()` in templates): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
94 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
95 >>> class MyClass(object): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
96 ... myattr = 'Bar' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
97 >>> data = dict(mine=MyClass(), key='myattr') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
98 >>> Expression('mine.myattr').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
99 'Bar' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
100 >>> Expression('mine["myattr"]').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
101 'Bar' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
102 >>> Expression('mine[key]').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
103 'Bar' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
104 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
105 All of the standard Python operators are available to template expressions. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
106 Built-in functions such as `len()` are also available in template |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
107 expressions: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
108 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
109 >>> data = dict(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
|
110 >>> Expression('len(items)').evaluate(data) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
111 3 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
112 """ |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
113 __slots__ = [] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
114 mode = 'eval' |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
115 |
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:
340
diff
changeset
|
116 def evaluate(self, data): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
117 """Evaluate the expression against the given data dictionary. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
118 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
119 @param data: a mapping containing the data to evaluate against |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
120 @return: the result of the evaluation |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
121 """ |
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:
340
diff
changeset
|
122 return eval(self.code, {'data': data, |
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:
340
diff
changeset
|
123 '_lookup_name': _lookup_name, |
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:
340
diff
changeset
|
124 '_lookup_attr': _lookup_attr, |
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:
340
diff
changeset
|
125 '_lookup_item': _lookup_item}, |
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:
340
diff
changeset
|
126 {'data': data}) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
127 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
128 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
129 class Suite(Code): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
130 """Executes Python statements used in templates. |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
131 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
132 >>> data = dict(test='Foo', items=[1, 2, 3], dict={'some': 'thing'}) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
133 >>> Suite('foo = dict.some').execute(data) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
134 >>> data['foo'] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
135 'thing' |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
136 """ |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
137 __slots__ = [] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
138 mode = 'exec' |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
139 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
140 def execute(self, data): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
141 """Execute the suite in the given data dictionary. |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
142 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
143 @param data: a mapping containing the data to execute in |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
144 """ |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
145 exec self.code in {'data': data, |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
146 '_lookup_name': _lookup_name, |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
147 '_lookup_attr': _lookup_attr, |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
148 '_lookup_item': _lookup_item}, data |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
149 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
150 |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
151 class Undefined(object): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
152 """Represents a reference to an undefined variable. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
153 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
154 Unlike the Python runtime, template expressions can refer to an undefined |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
155 variable without causing a `NameError` to be raised. The result will be an |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
156 instance of the `Undefined´ class, which is treated the same as `False` in |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
157 conditions, and acts as an empty collection in iterations: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
158 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
159 >>> foo = Undefined('foo') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
160 >>> bool(foo) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
161 False |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
162 >>> list(foo) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
163 [] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
164 >>> print foo |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
165 undefined |
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 However, calling an undefined variable, or trying to access an attribute |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
168 of that variable, will raise an exception that includes the name used to |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
169 reference that undefined variable. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
170 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
171 >>> foo('bar') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
172 Traceback (most recent call last): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
173 ... |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
174 NameError: Variable "foo" is not defined |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
175 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
176 >>> foo.bar |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
177 Traceback (most recent call last): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
178 ... |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
179 NameError: Variable "foo" is not defined |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
180 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
181 __slots__ = ['_name'] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
182 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
183 def __init__(self, name): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
184 self._name = name |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
185 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
186 def __call__(self, *args, **kwargs): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
187 __traceback_hide__ = True |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
188 self.throw() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
189 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
190 def __getattr__(self, name): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
191 __traceback_hide__ = True |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
192 self.throw() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
193 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
194 def __iter__(self): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
195 return iter([]) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
196 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
197 def __nonzero__(self): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
198 return False |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
199 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
200 def __repr__(self): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
201 return 'undefined' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
202 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
203 def throw(self): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
204 __traceback_hide__ = True |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
205 raise NameError('Variable "%s" is not defined' % self._name) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
206 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
207 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
208 def _parse(source, mode='eval'): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
209 if isinstance(source, unicode): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
210 source = '\xef\xbb\xbf' + source.encode('utf-8') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
211 return parse(source, mode) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
212 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
213 def _compile(node, source=None, mode='eval', filename=None, lineno=-1): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
214 tree = TemplateASTTransformer().visit(node) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
215 if isinstance(filename, unicode): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
216 # unicode file names not allowed for code objects |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
217 filename = filename.encode('utf-8', 'replace') |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
218 elif not filename: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
219 filename = '<string>' |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
220 tree.filename = filename |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
221 if lineno <= 0: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
222 lineno = 1 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
223 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
224 if mode == 'eval': |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
225 gen = ExpressionCodeGenerator(tree) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
226 name = '<Expression %s>' % (repr(source or '?').replace("'", '"')) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
227 else: |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
228 gen = ModuleCodeGenerator(tree) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
229 name = '<Suite>' |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
230 gen.optimized = True |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
231 code = gen.getCode() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
232 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
233 # We'd like to just set co_firstlineno, but it's readonly. So we need to |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
234 # clone the code object while adjusting the line number |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
235 return new.code(0, code.co_nlocals, code.co_stacksize, |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
236 code.co_flags | 0x0040, code.co_code, code.co_consts, |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
237 code.co_names, code.co_varnames, filename, name, lineno, |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
238 code.co_lnotab, (), ()) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
239 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
240 BUILTINS = __builtin__.__dict__.copy() |
401
68772732c896
Make the `Markup` class available by default in template expressions. Closes #67.
cmlenz
parents:
396
diff
changeset
|
241 BUILTINS.update({'Markup': Markup, 'Undefined': Undefined}) |
382
2682dabbcd04
* Added documentation for the various stream event kinds.
cmlenz
parents:
357
diff
changeset
|
242 _UNDEF = Undefined(None) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
243 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
244 def _lookup_name(data, name): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
245 __traceback_hide__ = True |
382
2682dabbcd04
* Added documentation for the various stream event kinds.
cmlenz
parents:
357
diff
changeset
|
246 val = data.get(name, _UNDEF) |
2682dabbcd04
* Added documentation for the various stream event kinds.
cmlenz
parents:
357
diff
changeset
|
247 if val is _UNDEF: |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
248 val = BUILTINS.get(name, val) |
382
2682dabbcd04
* Added documentation for the various stream event kinds.
cmlenz
parents:
357
diff
changeset
|
249 if val is _UNDEF: |
2682dabbcd04
* Added documentation for the various stream event kinds.
cmlenz
parents:
357
diff
changeset
|
250 return Undefined(name) |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
251 return val |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
252 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
253 def _lookup_attr(data, obj, key): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
254 __traceback_hide__ = True |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
255 if type(obj) is Undefined: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
256 obj.throw() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
257 if hasattr(obj, key): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
258 return getattr(obj, key) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
259 try: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
260 return obj[key] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
261 except (KeyError, TypeError): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
262 return Undefined(key) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
263 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
264 def _lookup_item(data, obj, key): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
265 __traceback_hide__ = True |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
266 if type(obj) is Undefined: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
267 obj.throw() |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
268 if len(key) == 1: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
269 key = key[0] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
270 try: |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
271 return obj[key] |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
272 except (AttributeError, KeyError, IndexError, TypeError), e: |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
273 if isinstance(key, basestring): |
382
2682dabbcd04
* Added documentation for the various stream event kinds.
cmlenz
parents:
357
diff
changeset
|
274 val = getattr(obj, key, _UNDEF) |
2682dabbcd04
* Added documentation for the various stream event kinds.
cmlenz
parents:
357
diff
changeset
|
275 if val is _UNDEF: |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
276 val = Undefined(key) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
277 return val |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
278 raise |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
279 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
280 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
281 class ASTTransformer(object): |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
282 """General purpose base class for AST transformations. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
283 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
284 Every visitor method can be overridden to return an AST node that has been |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
285 altered or replaced in some way. |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
286 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
287 _visitors = {} |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
288 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
289 def visit(self, node): |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
290 if node is None: |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
291 return None |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
292 v = self._visitors.get(node.__class__) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
293 if not v: |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
294 v = getattr(self.__class__, 'visit%s' % node.__class__.__name__, |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
295 self.__class__._visitDefault) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
296 #self._visitors[node.__class__] = v |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
297 return v(self, node) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
298 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
299 def _visitDefault(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
300 return node |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
301 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
302 def visitExpression(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
303 node.node = self.visit(node.node) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
304 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
305 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
306 def visitModule(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
307 node.node = self.visit(node.node) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
308 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
309 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
310 def visitStmt(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
311 node.nodes = [self.visit(x) for x in node.nodes] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
312 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
313 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
314 # Classes, Functions & Accessors |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
315 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
316 def visitCallFunc(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
317 node.node = self.visit(node.node) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
318 node.args = [self.visit(x) for x in node.args] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
319 if node.star_args: |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
320 node.star_args = self.visit(node.star_args) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
321 if node.dstar_args: |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
322 node.dstar_args = self.visit(node.dstar_args) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
323 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
324 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
325 def visitClass(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
326 node.bases = [self.visit(x) for x in node.bases] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
327 node.code = self.visit(node.code) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
328 node.filename = '<string>' # workaround for bug in pycodegen |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
329 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
330 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
331 def visitFunction(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
332 if hasattr(node, 'decorators'): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
333 node.decorators = self.visit(node.decorators) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
334 node.defaults = [self.visit(x) for x in node.defaults] |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
335 node.code = self.visit(node.code) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
336 node.filename = '<string>' # workaround for bug in pycodegen |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
337 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
338 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
339 def visitGetattr(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
340 node.expr = self.visit(node.expr) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
341 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
342 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
343 def visitLambda(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
344 node.code = self.visit(node.code) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
345 node.filename = '<string>' # workaround for bug in pycodegen |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
346 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
347 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
348 def visitSubscript(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
349 node.expr = self.visit(node.expr) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
350 node.subs = [self.visit(x) for x in node.subs] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
351 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
352 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
353 # Statements |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
354 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
355 def visitAssert(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
356 node.test = self.visit(node.test) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
357 node.fail = self.visit(node.fail) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
358 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
359 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
360 def visitAssign(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
361 node.nodes = [self.visit(x) for x in node.nodes] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
362 node.expr = self.visit(node.expr) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
363 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
364 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
365 def visitDecorators(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
366 node.nodes = [self.visit(x) for x in node.nodes] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
367 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
368 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
369 def visitFor(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
370 node.assign = self.visit(node.assign) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
371 node.list = self.visit(node.list) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
372 node.body = self.visit(node.body) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
373 node.else_ = self.visit(node.else_) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
374 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
375 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
376 def visitIf(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
377 node.tests = [self.visit(x) for x in node.tests] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
378 node.else_ = self.visit(node.else_) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
379 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
380 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
381 def _visitPrint(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
382 node.nodes = [self.visit(x) for x in node.nodes] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
383 node.dest = self.visit(node.dest) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
384 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
385 visitPrint = visitPrintnl = _visitPrint |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
386 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
387 def visitRaise(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
388 node.expr1 = self.visit(node.expr1) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
389 node.expr2 = self.visit(node.expr2) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
390 node.expr3 = self.visit(node.expr3) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
391 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
392 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
393 def visitTryExcept(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
394 node.body = self.visit(node.body) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
395 node.handlers = self.visit(node.handlers) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
396 node.else_ = self.visit(node.else_) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
397 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
398 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
399 def visitTryFinally(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
400 node.body = self.visit(node.body) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
401 node.final = self.visit(node.final) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
402 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
403 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
404 def visitWhile(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
405 node.test = self.visit(node.test) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
406 node.body = self.visit(node.body) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
407 node.else_ = self.visit(node.else_) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
408 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
409 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
410 def visitWith(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
411 node.expr = self.visit(node.expr) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
412 node.vars = [self.visit(x) for x in node.vars] |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
413 node.body = self.visit(node.body) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
414 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
415 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
416 def visitYield(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
417 node.value = self.visit(node.value) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
418 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
419 |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
420 # Operators |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
421 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
422 def _visitBoolOp(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
423 node.nodes = [self.visit(x) for x in node.nodes] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
424 return node |
396 | 425 visitAnd = visitOr = visitBitand = visitBitor = visitBitxor = _visitBoolOp |
426 visitAssTuple = _visitBoolOp | |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
427 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
428 def _visitBinOp(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
429 node.left = self.visit(node.left) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
430 node.right = self.visit(node.right) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
431 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
432 visitAdd = visitSub = _visitBinOp |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
433 visitDiv = visitFloorDiv = visitMod = visitMul = visitPower = _visitBinOp |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
434 visitLeftShift = visitRightShift = _visitBinOp |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
435 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
436 def visitCompare(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
437 node.expr = self.visit(node.expr) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
438 node.ops = [(op, self.visit(n)) for op, n in node.ops] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
439 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
440 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
441 def _visitUnaryOp(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
442 node.expr = self.visit(node.expr) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
443 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
444 visitUnaryAdd = visitUnarySub = visitNot = visitInvert = _visitUnaryOp |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
445 visitBackquote = visitDiscard = _visitUnaryOp |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
446 |
393
1dc3d3df4a85
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
447 def visitIfExp(self, node): |
1dc3d3df4a85
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
448 node.test = self.visit(node.test) |
1dc3d3df4a85
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
449 node.then = self.visit(node.then) |
1dc3d3df4a85
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
450 node.else_ = self.visit(node.else_) |
1dc3d3df4a85
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
451 return node |
1dc3d3df4a85
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
452 |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
453 # Identifiers, Literals and Comprehensions |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
454 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
455 def visitDict(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
456 node.items = [(self.visit(k), |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
457 self.visit(v)) for k, v in node.items] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
458 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
459 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
460 def visitGenExpr(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
461 node.code = self.visit(node.code) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
462 node.filename = '<string>' # workaround for bug in pycodegen |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
463 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
464 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
465 def visitGenExprFor(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
466 node.assign = self.visit(node.assign) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
467 node.iter = self.visit(node.iter) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
468 node.ifs = [self.visit(x) for x in node.ifs] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
469 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
470 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
471 def visitGenExprIf(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
472 node.test = self.visit(node.test) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
473 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
474 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
475 def visitGenExprInner(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
476 node.quals = [self.visit(x) for x in node.quals] |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
477 node.expr = self.visit(node.expr) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
478 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
479 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
480 def visitKeyword(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
481 node.expr = self.visit(node.expr) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
482 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
483 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
484 def visitList(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
485 node.nodes = [self.visit(n) for n in node.nodes] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
486 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
487 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
488 def visitListComp(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
489 node.quals = [self.visit(x) for x in node.quals] |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
490 node.expr = self.visit(node.expr) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
491 return node |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
492 |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
493 def visitListCompFor(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
494 node.assign = self.visit(node.assign) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
495 node.list = self.visit(node.list) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
496 node.ifs = [self.visit(x) for x in node.ifs] |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
497 return node |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
498 |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
499 def visitListCompIf(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
500 node.test = self.visit(node.test) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
501 return node |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
502 |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
503 def visitSlice(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
504 node.expr = self.visit(node.expr) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
505 if node.lower is not None: |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
506 node.lower = self.visit(node.lower) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
507 if node.upper is not None: |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
508 node.upper = self.visit(node.upper) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
509 return node |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
510 |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
511 def visitSliceobj(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
512 node.nodes = [self.visit(x) for x in node.nodes] |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
513 return node |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
514 |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
515 def visitTuple(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
516 node.nodes = [self.visit(n) for n in node.nodes] |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
517 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
518 |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
519 |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
520 class TemplateASTTransformer(ASTTransformer): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
521 """Concrete AST transformer that implements the AST transformations needed |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
522 for code embedded in templates. |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
523 """ |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
524 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
525 def __init__(self): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
526 self.locals = [] |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
527 |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
528 def visitConst(self, node): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
529 if isinstance(node.value, str): |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
530 try: # If the string is ASCII, return a `str` object |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
531 node.value.decode('ascii') |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
532 except ValueError: # Otherwise return a `unicode` object |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
533 return ast.Const(node.value.decode('utf-8')) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
534 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
535 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
536 def visitAssName(self, node): |
405
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
537 if self.locals: |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
538 self.locals[-1].add(node.name) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
539 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
540 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
541 def visitClass(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
542 self.locals.append(set()) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
543 node = ASTTransformer.visitClass(self, node) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
544 self.locals.pop() |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
545 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
546 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
547 def visitFor(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
548 self.locals.append(set()) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
549 node = ASTTransformer.visitFor(self, node) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
550 self.locals.pop() |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
551 return node |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
552 |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
553 def visitFunction(self, node): |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
554 self.locals.append(set(node.argnames)) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
555 node = ASTTransformer.visitFunction(self, node) |
5340931530e2
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
556 self.locals.pop() |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
557 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
558 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
559 def visitGenExpr(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
560 self.locals.append(set()) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
561 node = ASTTransformer.visitGenExpr(self, node) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
562 self.locals.pop() |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
563 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
564 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
565 def visitGetattr(self, node): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
566 return ast.CallFunc(ast.Name('_lookup_attr'), [ |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
567 ast.Name('data'), self.visit(node.expr), |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
568 ast.Const(node.attrname) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
569 ]) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
570 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
571 def visitLambda(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
572 self.locals.append(set(flatten(node.argnames))) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
573 node = ASTTransformer.visitLambda(self, node) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
574 self.locals.pop() |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
575 return node |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
576 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
577 def visitListComp(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
578 self.locals.append(set()) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
579 node = ASTTransformer.visitListComp(self, node) |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
580 self.locals.pop() |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
581 return node |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
582 |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
583 def visitName(self, node): |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
584 # If the name refers to a local inside a lambda, list comprehension, or |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
585 # generator expression, leave it alone |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
586 for frame in self.locals: |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
587 if node.name in frame: |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
588 return node |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
589 # Otherwise, translate the name ref into a context lookup |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
590 func_args = [ast.Name('data'), ast.Const(node.name)] |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
591 return ast.CallFunc(ast.Name('_lookup_name'), func_args) |
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
592 |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
593 def visitSubscript(self, node): |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
594 return ast.CallFunc(ast.Name('_lookup_item'), [ |
357
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
595 ast.Name('data'), self.visit(node.expr), |
62de137b9322
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
596 ast.Tuple([self.visit(sub) for sub in node.subs]) |
336
7763f7aec949
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
597 ]) |