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
7016f404b915 add visitor for xor operator
mgood
parents: 393
diff changeset
425 visitAnd = visitOr = visitBitand = visitBitor = visitBitxor = _visitBoolOp
7016f404b915 add visitor for xor operator
mgood
parents: 393
diff changeset
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 ])
Copyright (C) 2012-2017 Edgewall Software