annotate genshi/template/eval.py @ 733:43147cbc9ea3 trunk

Update to r855 for Python 2.3 support. Fixes #221 (hopefully).
author athomas
date Wed, 04 Jun 2008 05:01:16 +0000
parents 01bdf155db95
children a1e8b24bc1bb
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 #
719
4bc6741b2811 Fix copyright years.
cmlenz
parents: 716
diff changeset
3 # Copyright (C) 2006-2008 Edgewall Software
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
4 # All rights reserved.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
5 #
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
6 # This software is licensed as described in the file COPYING, which
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
7 # you should have received as part of this distribution. The terms
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
8 # are also available at http://genshi.edgewall.org/wiki/License.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
9 #
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
10 # This software consists of voluntary contributions made by many
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
11 # individuals. For the exact contribution history, see the revision
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
12 # history and logs, available at http://genshi.edgewall.org/log/.
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
13
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
14 """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:
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
23 from sets import ImmutableSet as frozenset
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
24 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
25 import sys
601
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
26 from textwrap import dedent
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
27
401
68772732c896 Make the `Markup` class available by default in template expressions. Closes #67.
cmlenz
parents: 396
diff changeset
28 from genshi.core import Markup
418
c478a6fa9e77 Make expression error handling more strict. Closes #88.
cmlenz
parents: 408
diff changeset
29 from genshi.template.base import TemplateRuntimeError
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
30 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
31
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
32 __all__ = ['Code', 'Expression', 'Suite', 'LenientLookup', 'StrictLookup',
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
33 'Undefined', 'UndefinedError']
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
34 __docformat__ = 'restructuredtext en'
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
35
731
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
36 # Check for a Python 2.4 bug in the eval loop
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
37 try:
733
43147cbc9ea3 Update to r855 for Python 2.3 support. Fixes #221 (hopefully).
athomas
parents: 731
diff changeset
38 class _FakeMapping(dict):
731
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
39 __getitem__ = __setitem__ = lambda *a: None
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
40 exec 'from sys import *' in {}, _FakeMapping()
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
41 except SystemError:
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
42 has_star_import_bug = True
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
43 else:
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
44 has_star_import_bug = False
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
45 del _FakeMapping
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
46
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
47 def _star_import_patch(mapping, modname):
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
48 """This function is used as helper if a Python version with a broken
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
49 star-import opcode is in use.
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
50 """
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
51 module = __import__(modname, None, None, ['__all__'])
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
52 if hasattr(module, '__all__'):
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
53 members = module.__all__
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
54 else:
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
55 members = [x for x in module.__dict__ if not x.startswith('_')]
733
43147cbc9ea3 Update to r855 for Python 2.3 support. Fixes #221 (hopefully).
athomas
parents: 731
diff changeset
56 mapping.update([(name, getattr(module, name)) for name in members])
731
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
57
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
58
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
59 class Code(object):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
60 """Abstract base class for the `Expression` and `Suite` classes."""
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
61 __slots__ = ['source', 'code', 'ast', '_globals']
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
62
606
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 604
diff changeset
63 def __init__(self, source, filename=None, lineno=-1, lookup='strict',
604
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
64 xform=None):
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
65 """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
66
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
67 :param source: either a string containing the source code, or an AST
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
68 node
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
69 :param filename: the (preferably absolute) name of the file containing
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
70 the code
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
71 :param lineno: the number of the line on which the code was found
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
72 :param lookup: the lookup class that defines how variables are looked
606
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 604
diff changeset
73 up in the context; can be either "strict" (the default),
37ff75bb4301 Changed the default error handling mode to "strict".
cmlenz
parents: 604
diff changeset
74 "lenient", or a custom lookup class
604
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
75 :param xform: the AST transformer that should be applied to the code;
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
76 if `None`, the appropriate transformation is chosen
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
77 depending on the mode
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
78 """
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
79 if isinstance(source, basestring):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
80 self.source = source
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
81 node = _parse(source, mode=self.mode)
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
82 else:
601
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
83 assert isinstance(source, ast.Node), \
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
84 'Expected string or AST node, but got %r' % source
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
85 self.source = '?'
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
86 if self.mode == 'eval':
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
87 node = ast.Expression(source)
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
88 else:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
89 node = ast.Module(None, source)
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
90
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
91 self.ast = node
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
92 self.code = _compile(node, self.source, mode=self.mode,
604
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
93 filename=filename, lineno=lineno, xform=xform)
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
94 if lookup is None:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
95 lookup = LenientLookup
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
96 elif isinstance(lookup, basestring):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
97 lookup = {'lenient': LenientLookup, 'strict': StrictLookup}[lookup]
654
23b5138fd835 Fix thread-safety problem in template code evaluation. Closes #158. Thanks to Christian Boos for the patch.
cmlenz
parents: 606
diff changeset
98 self._globals = lookup.globals
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
99
715
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
100 def __getstate__(self):
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
101 state = {'source': self.source, 'ast': self.ast,
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
102 'lookup': self._globals.im_self}
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
103 c = self.code
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
104 state['code'] = (c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code,
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
105 c.co_consts, c.co_names, c.co_varnames, c.co_filename,
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
106 c.co_name, c.co_firstlineno, c.co_lnotab, (), ())
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
107 return state
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
108
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
109 def __setstate__(self, state):
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
110 self.source = state['source']
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
111 self.ast = state['ast']
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
112 self.code = new.code(0, *state['code'])
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
113 self._globals = state['lookup'].globals
b5bd8c109209 Enable pickling of `Template` and `Code` objects.
cmlenz
parents: 702
diff changeset
114
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
115 def __eq__(self, other):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
116 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
117
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
118 def __hash__(self):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
119 return hash(self.code)
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
120
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
121 def __ne__(self, other):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
122 return not self == other
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
123
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
124 def __repr__(self):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
125 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
126
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
127
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
128 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
129 """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
130
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
131 >>> 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
132 >>> 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
133 'Foo'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
134
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
135 >>> 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
136 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
137 >>> 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
138 3
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
139 >>> 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
140 'thing'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
141
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
142 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
143 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
144
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
145 >>> 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
146 'thing'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
147
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
148 This also works the other way around: item access can be used to access
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
149 any object attribute:
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
150
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
151 >>> class MyClass(object):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
152 ... myattr = 'Bar'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
153 >>> 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
154 >>> 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
155 'Bar'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
156 >>> 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
157 'Bar'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
158 >>> 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
159 'Bar'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
160
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
161 All of the standard Python operators are available to template expressions.
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
162 Built-in functions such as ``len()`` are also available in template
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
163 expressions:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
164
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
165 >>> 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
166 >>> 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
167 3
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
168 """
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
169 __slots__ = []
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
170 mode = 'eval'
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
171
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
172 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
173 """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
174
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
175 :param data: a mapping containing the data to evaluate against
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
176 :return: the result of the evaluation
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
177 """
418
c478a6fa9e77 Make expression error handling more strict. Closes #88.
cmlenz
parents: 408
diff changeset
178 __traceback_hide__ = 'before_and_this'
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
179 _globals = self._globals(data)
682
0653f6c1ffdf Assigning to a variable named `data` in a Python code block no longer breaks context lookup. We now use the name `__data__` for internal data, hoping that that name is not as commonly used in templates.
cmlenz
parents: 654
diff changeset
180 return eval(self.code, _globals, {'__data__': data})
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
181
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
182
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
183 class Suite(Code):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
184 """Executes Python statements used in templates.
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
185
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
186 >>> data = dict(test='Foo', items=[1, 2, 3], dict={'some': 'thing'})
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
187 >>> Suite("foo = dict['some']").execute(data)
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
188 >>> data['foo']
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
189 'thing'
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
190 """
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
191 __slots__ = []
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
192 mode = 'exec'
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
193
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
194 def execute(self, data):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
195 """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
196
425
073640758a42 Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents: 418
diff changeset
197 :param data: a mapping containing the data to execute in
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
198 """
418
c478a6fa9e77 Make expression error handling more strict. Closes #88.
cmlenz
parents: 408
diff changeset
199 __traceback_hide__ = 'before_and_this'
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
200 _globals = self._globals(data)
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
201 exec self.code in _globals, data
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
202
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
203
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
204 UNDEFINED = object()
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
205
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
206
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
207 class UndefinedError(TemplateRuntimeError):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
208 """Exception thrown when a template expression attempts to access a variable
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
209 not defined in the context.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
210
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
211 :see: `LenientLookup`, `StrictLookup`
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
212 """
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
213 def __init__(self, name, owner=UNDEFINED):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
214 if owner is not UNDEFINED:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
215 message = '%s has no member named "%s"' % (repr(owner), name)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
216 else:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
217 message = '"%s" not defined' % name
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
218 TemplateRuntimeError.__init__(self, message)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
219
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
220
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
221 class Undefined(object):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
222 """Represents a reference to an undefined variable.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
223
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
224 Unlike the Python runtime, template expressions can refer to an undefined
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
225 variable without causing a `NameError` to be raised. The result will be an
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
226 instance of the `Undefined` class, which is treated the same as ``False`` in
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
227 conditions, but raise an exception on any other operation:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
228
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
229 >>> foo = Undefined('foo')
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
230 >>> bool(foo)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
231 False
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
232 >>> list(foo)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
233 []
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
234 >>> print foo
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
235 undefined
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
236
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
237 However, calling an undefined variable, or trying to access an attribute
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
238 of that variable, will raise an exception that includes the name used to
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
239 reference that undefined variable.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
240
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
241 >>> foo('bar')
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
242 Traceback (most recent call last):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
243 ...
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
244 UndefinedError: "foo" not defined
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
245
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
246 >>> foo.bar
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
247 Traceback (most recent call last):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
248 ...
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
249 UndefinedError: "foo" not defined
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
250
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
251 :see: `LenientLookup`
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
252 """
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
253 __slots__ = ['_name', '_owner']
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
254
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
255 def __init__(self, name, owner=UNDEFINED):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
256 """Initialize the object.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
257
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
258 :param name: the name of the reference
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
259 :param owner: the owning object, if the variable is accessed as a member
418
c478a6fa9e77 Make expression error handling more strict. Closes #88.
cmlenz
parents: 408
diff changeset
260 """
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
261 self._name = name
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
262 self._owner = owner
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
263
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
264 def __iter__(self):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
265 return iter([])
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
266
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
267 def __nonzero__(self):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
268 return False
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
269
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
270 def __repr__(self):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
271 return '<%s %r>' % (self.__class__.__name__, self._name)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
272
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
273 def __str__(self):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
274 return 'undefined'
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
275
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
276 def _die(self, *args, **kwargs):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
277 """Raise an `UndefinedError`."""
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
278 __traceback_hide__ = True
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
279 raise UndefinedError(self._name, self._owner)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
280 __call__ = __getattr__ = __getitem__ = _die
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
281
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
282
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
283 class LookupBase(object):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
284 """Abstract base class for variable lookup implementations."""
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
285
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
286 def globals(cls, data):
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
287 """Construct the globals dictionary to use as the execution context for
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
288 the expression or suite.
418
c478a6fa9e77 Make expression error handling more strict. Closes #88.
cmlenz
parents: 408
diff changeset
289 """
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
290 return {
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
291 '__data__': data,
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
292 '_lookup_name': cls.lookup_name,
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
293 '_lookup_attr': cls.lookup_attr,
579
2f7f6b70d5b9 Fix for augmented assignments to local variables. Thanks to Erik Bray for reporting the problem.
cmlenz
parents: 569
diff changeset
294 '_lookup_item': cls.lookup_item,
731
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
295 '_star_import_patch': _star_import_patch,
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
296 'UndefinedError': UndefinedError,
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
297 }
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
298 globals = classmethod(globals)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
299
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
300 def lookup_name(cls, data, name):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
301 __traceback_hide__ = True
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
302 val = data.get(name, UNDEFINED)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
303 if val is UNDEFINED:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
304 val = BUILTINS.get(name, val)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
305 if val is UNDEFINED:
569
c17342ef9efb Attribute access in template expressions no longer silently ignores exceptions other than `AttributeError` raised in the attribute accessor.
cmlenz
parents: 568
diff changeset
306 val = cls.undefined(name)
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
307 return val
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
308 lookup_name = classmethod(lookup_name)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
309
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
310 def lookup_attr(cls, obj, key):
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
311 __traceback_hide__ = True
702
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
312 try:
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
313 val = getattr(obj, key)
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
314 except AttributeError:
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
315 if hasattr(obj.__class__, key):
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
316 raise
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
317 else:
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
318 try:
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
319 val = obj[key]
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
320 except (KeyError, TypeError):
e5b0d9d6b406 Improve error reporting when accessing an attribute in a Python expression raises an `AttributeError`. Closes #191. Thanks to Michele Cella for the patch!
cmlenz
parents: 691
diff changeset
321 val = cls.undefined(key, owner=obj)
569
c17342ef9efb Attribute access in template expressions no longer silently ignores exceptions other than `AttributeError` raised in the attribute accessor.
cmlenz
parents: 568
diff changeset
322 return val
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
323 lookup_attr = classmethod(lookup_attr)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
324
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
325 def lookup_item(cls, obj, key):
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
326 __traceback_hide__ = True
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
327 if len(key) == 1:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
328 key = key[0]
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
329 try:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
330 return obj[key]
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
331 except (AttributeError, KeyError, IndexError, TypeError), e:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
332 if isinstance(key, basestring):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
333 val = getattr(obj, key, UNDEFINED)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
334 if val is UNDEFINED:
569
c17342ef9efb Attribute access in template expressions no longer silently ignores exceptions other than `AttributeError` raised in the attribute accessor.
cmlenz
parents: 568
diff changeset
335 val = cls.undefined(key, owner=obj)
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
336 return val
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
337 raise
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
338 lookup_item = classmethod(lookup_item)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
339
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
340 def undefined(cls, key, owner=UNDEFINED):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
341 """Can be overridden by subclasses to specify behavior when undefined
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
342 variables are accessed.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
343
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
344 :param key: the name of the variable
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
345 :param owner: the owning object, if the variable is accessed as a member
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
346 """
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
347 raise NotImplementedError
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
348 undefined = classmethod(undefined)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
349
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
350
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
351 class LenientLookup(LookupBase):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
352 """Default variable lookup mechanism for expressions.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
353
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
354 When an undefined variable is referenced using this lookup style, the
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
355 reference evaluates to an instance of the `Undefined` class:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
356
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
357 >>> expr = Expression('nothing', lookup='lenient')
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
358 >>> undef = expr.evaluate({})
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
359 >>> undef
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
360 <Undefined 'nothing'>
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
361
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
362 The same will happen when a non-existing attribute or item is accessed on
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
363 an existing object:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
364
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
365 >>> expr = Expression('something.nil', lookup='lenient')
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
366 >>> expr.evaluate({'something': dict()})
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
367 <Undefined 'nil'>
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
368
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
369 See the documentation of the `Undefined` class for details on the behavior
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
370 of such objects.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
371
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
372 :see: `StrictLookup`
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
373 """
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
374 def undefined(cls, key, owner=UNDEFINED):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
375 """Return an ``Undefined`` object."""
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
376 __traceback_hide__ = True
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
377 return Undefined(key, owner=owner)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
378 undefined = classmethod(undefined)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
379
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
380
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
381 class StrictLookup(LookupBase):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
382 """Strict variable lookup mechanism for expressions.
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
383
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
384 Referencing an undefined variable using this lookup style will immediately
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
385 raise an ``UndefinedError``:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
386
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
387 >>> expr = Expression('nothing', lookup='strict')
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
388 >>> expr.evaluate({})
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
389 Traceback (most recent call last):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
390 ...
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
391 UndefinedError: "nothing" not defined
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
392
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
393 The same happens when a non-existing attribute or item is accessed on an
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
394 existing object:
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
395
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
396 >>> expr = Expression('something.nil', lookup='strict')
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
397 >>> expr.evaluate({'something': dict()})
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
398 Traceback (most recent call last):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
399 ...
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
400 UndefinedError: {} has no member named "nil"
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
401 """
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
402 def undefined(cls, key, owner=UNDEFINED):
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
403 """Raise an ``UndefinedError`` immediately."""
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
404 __traceback_hide__ = True
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
405 raise UndefinedError(key, owner=owner)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
406 undefined = classmethod(undefined)
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
407
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
408
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
409 def _parse(source, mode='eval'):
601
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
410 source = source.strip()
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
411 if mode == 'exec':
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
412 lines = [line.expandtabs() for line in source.splitlines()]
716
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
413 if lines:
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
414 first = lines[0]
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
415 rest = dedent('\n'.join(lines[1:])).rstrip()
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
416 if first.rstrip().endswith(':') and not rest[0].isspace():
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
417 rest = '\n'.join([' %s' % line for line in rest.splitlines()])
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
418 source = '\n'.join([first, rest])
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
419 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
420 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
421 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
422
604
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
423 def _compile(node, source=None, mode='eval', filename=None, lineno=-1,
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
424 xform=None):
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
425 if xform is None:
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
426 xform = {'eval': ExpressionASTTransformer}.get(mode,
416e46209da1 Fix bug that slipped into [717]: the code of a `py:with` directive was not being compiled with AST transformations applied.
cmlenz
parents: 601
diff changeset
427 TemplateASTTransformer)
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
428 tree = xform().visit(node)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
429 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
430 # 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
431 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
432 elif not filename:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
433 filename = '<string>'
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
434 tree.filename = filename
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
435 if lineno <= 0:
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
436 lineno = 1
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
437
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
438 if mode == 'eval':
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
439 gen = ExpressionCodeGenerator(tree)
601
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
440 name = '<Expression %r>' % (source or '?')
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
441 else:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
442 gen = ModuleCodeGenerator(tree)
601
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
443 lines = source.splitlines()
716
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
444 if not lines:
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
445 extract = ''
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
446 else:
eee7483041dd fix ticket [209] - make sure py:with is valid, and add a test to make sure empty py:for is invalid
aflett
parents: 715
diff changeset
447 extract = lines[0]
601
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
448 if len(lines) > 1:
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
449 extract += ' ...'
59fbd7586454 Simplify implementation of `py:with` directive by compiling to a `Suite`, instead of manually breaking up the statement and compiling each part to an `Expression`. Also, the first line of code in a `Suite` is now stored as the "function name" of the bytecode, so that it shows up in tracebacks.
cmlenz
parents: 586
diff changeset
450 name = '<Suite %r>' % (extract)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
451 gen.optimized = True
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
452 code = gen.getCode()
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
453
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
454 # 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
455 # 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
456 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
457 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
458 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
459 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
460
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
461 BUILTINS = __builtin__.__dict__.copy()
442
97544725bb7f Back out [510] and instead implement configurable error handling modes. The default is the old 0.3.x behaviour, but more strict error handling is available as an option.
cmlenz
parents: 438
diff changeset
462 BUILTINS.update({'Markup': Markup, 'Undefined': Undefined})
563
9d1c5c290254 Built-in Python constants (such as `None`) in expressions are used directly instead of being looked up from the context.
cmlenz
parents: 473
diff changeset
463 CONSTANTS = frozenset(['False', 'True', 'None', 'NotImplemented', 'Ellipsis'])
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
464
564
aeb89e9730df Alias `__contains__` to `has_key` in `Context` class for code outside of Genshi that may expect that for some wild reason.
cmlenz
parents: 563
diff changeset
465
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
466 class ASTTransformer(object):
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
467 """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
468
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
469 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
470 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
471 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
472
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
473 def visit(self, node):
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
474 if node is None:
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
475 return None
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
476 if type(node) is tuple:
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
477 return tuple([self.visit(n) for n in node])
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
478 visitor = getattr(self, 'visit%s' % node.__class__.__name__,
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
479 self._visitDefault)
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
480 return visitor(node)
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
481
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
482 def _clone(self, node, *args):
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
483 lineno = getattr(node, 'lineno', None)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
484 node = node.__class__(*args)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
485 if lineno is not None:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
486 node.lineno = lineno
684
17f9061d0f74 Fix one Python 2.3 compatibility in the expression evaluation code. See #177. One more to go, though.
cmlenz
parents: 682
diff changeset
487 if isinstance(node, (ast.Class, ast.Function, ast.Lambda)) or \
17f9061d0f74 Fix one Python 2.3 compatibility in the expression evaluation code. See #177. One more to go, though.
cmlenz
parents: 682
diff changeset
488 sys.version_info > (2, 4) and isinstance(node, ast.GenExpr):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
489 node.filename = '<string>' # workaround for bug in pycodegen
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
490 return node
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
491
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
492 def _visitDefault(self, node):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
493 return node
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
494
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
495 def visitExpression(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
496 return self._clone(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
497
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
498 def visitModule(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
499 return self._clone(node, node.doc, self.visit(node.node))
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
500
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
501 def visitStmt(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
502 return self._clone(node, [self.visit(x) for x in node.nodes])
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
503
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
504 # 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
505
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
506 def visitCallFunc(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
507 return self._clone(node, self.visit(node.node),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
508 [self.visit(x) for x in node.args],
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
509 node.star_args and self.visit(node.star_args) or None,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
510 node.dstar_args and self.visit(node.dstar_args) or None
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
511 )
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
512
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
513 def visitClass(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
514 return self._clone(node, node.name, [self.visit(x) for x in node.bases],
568
461d9d0e85a4 AST transformer needs to also handle the class body.
cmlenz
parents: 565
diff changeset
515 node.doc, self.visit(node.code)
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
516 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
517
731
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
518 def visitFrom(self, node):
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
519 if not has_star_import_bug or node.names != [('*', None)]:
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
520 # This is a Python 2.4 bug. Only if we have a broken Python
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
521 # version we have to apply the hack
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
522 return node
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
523 return ast.Discard(ast.CallFunc(
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
524 ast.Name('_star_import_patch'),
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
525 [ast.Name('__data__'), ast.Const(node.modname)], None, None
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
526 ), lineno=node.lineno)
01bdf155db95 Workaround for a Python 2.4 bug that broke star imports in template code blocks. Closes #221. Many thanks to Armin Ronacher for the patch.
cmlenz
parents: 719
diff changeset
527
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
528 def visitFunction(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
529 args = []
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
530 if hasattr(node, 'decorators'):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
531 args.append(self.visit(node.decorators))
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
532 return self._clone(node, *args + [
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
533 node.name,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
534 node.argnames,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
535 [self.visit(x) for x in node.defaults],
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
536 node.flags,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
537 node.doc,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
538 self.visit(node.code)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
539 ])
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
540
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
541 def visitGetattr(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
542 return self._clone(node, self.visit(node.expr), node.attrname)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
543
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
544 def visitLambda(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
545 node = self._clone(node, node.argnames,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
546 [self.visit(x) for x in node.defaults], node.flags,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
547 self.visit(node.code)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
548 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
549 return node
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
550
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
551 def visitSubscript(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
552 return self._clone(node, self.visit(node.expr), node.flags,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
553 [self.visit(x) for x in node.subs]
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
554 )
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
555
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
556 # Statements
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
557
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
558 def visitAssert(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
559 return self._clone(node, self.visit(node.test), self.visit(node.fail))
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
560
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
561 def visitAssign(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
562 return self._clone(node, [self.visit(x) for x in node.nodes],
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
563 self.visit(node.expr)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
564 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
565
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
566 def visitAssAttr(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
567 return self._clone(node, self.visit(node.expr), node.attrname,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
568 node.flags
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
569 )
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
570
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
571 def visitAugAssign(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
572 return self._clone(node, self.visit(node.node), node.op,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
573 self.visit(node.expr)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
574 )
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
575
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
576 def visitDecorators(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
577 return self._clone(node, [self.visit(x) for x in node.nodes])
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
578
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
579 def visitExec(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
580 return self._clone(node, self.visit(node.expr), self.visit(node.locals),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
581 self.visit(node.globals)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
582 )
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
583
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
584 def visitFor(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
585 return self._clone(node, self.visit(node.assign), self.visit(node.list),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
586 self.visit(node.body), self.visit(node.else_)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
587 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
588
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
589 def visitIf(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
590 return self._clone(node, [self.visit(x) for x in node.tests],
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
591 self.visit(node.else_)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
592 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
593
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
594 def _visitPrint(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
595 return self._clone(node, [self.visit(x) for x in node.nodes],
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
596 self.visit(node.dest)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
597 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
598 visitPrint = visitPrintnl = _visitPrint
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
599
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
600 def visitRaise(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
601 return self._clone(node, self.visit(node.expr1), self.visit(node.expr2),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
602 self.visit(node.expr3)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
603 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
604
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
605 def visitReturn(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
606 return self._clone(node, self.visit(node.value))
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
607
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
608 def visitTryExcept(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
609 return self._clone(node, self.visit(node.body), self.visit(node.handlers),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
610 self.visit(node.else_)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
611 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
612
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
613 def visitTryFinally(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
614 return self._clone(node, self.visit(node.body), self.visit(node.final))
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
615
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
616 def visitWhile(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
617 return self._clone(node, self.visit(node.test), self.visit(node.body),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
618 self.visit(node.else_)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
619 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
620
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
621 def visitWith(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
622 return self._clone(node, self.visit(node.expr),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
623 [self.visit(x) for x in node.vars], self.visit(node.body)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
624 )
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
625
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
626 def visitYield(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
627 return self._clone(node, self.visit(node.value))
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
628
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
629 # Operators
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
630
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
631 def _visitBoolOp(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
632 return self._clone(node, [self.visit(x) for x in node.nodes])
396
7016f404b915 add visitor for xor operator
mgood
parents: 393
diff changeset
633 visitAnd = visitOr = visitBitand = visitBitor = visitBitxor = _visitBoolOp
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
634 visitAssTuple = visitAssList = _visitBoolOp
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
635
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
636 def _visitBinOp(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
637 return self._clone(node,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
638 (self.visit(node.left), self.visit(node.right))
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
639 )
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
640 visitAdd = visitSub = _visitBinOp
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
641 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
642 visitLeftShift = visitRightShift = _visitBinOp
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
643
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
644 def visitCompare(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
645 return self._clone(node, self.visit(node.expr),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
646 [(op, self.visit(n)) for op, n in node.ops]
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
647 )
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
648
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
649 def _visitUnaryOp(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
650 return self._clone(node, 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
651 visitUnaryAdd = visitUnarySub = visitNot = visitInvert = _visitUnaryOp
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
652 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
653
393
1dc3d3df4a85 add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents: 382
diff changeset
654 def visitIfExp(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
655 return self._clone(node, self.visit(node.test), self.visit(node.then),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
656 self.visit(node.else_)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
657 )
393
1dc3d3df4a85 add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents: 382
diff changeset
658
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
659 # 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
660
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
661 def visitDict(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
662 return self._clone(node,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
663 [(self.visit(k), self.visit(v)) for k, v in node.items]
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
664 )
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
665
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
666 def visitGenExpr(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
667 return self._clone(node, 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
668
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
669 def visitGenExprFor(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
670 return self._clone(node, self.visit(node.assign), self.visit(node.iter),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
671 [self.visit(x) for x in node.ifs]
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
672 )
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
673
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
674 def visitGenExprIf(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
675 return self._clone(node, 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
676
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
677 def visitGenExprInner(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
678 quals = [self.visit(x) for x in node.quals]
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
679 return self._clone(node, self.visit(node.expr), quals)
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
680
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
681 def visitKeyword(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
682 return self._clone(node, node.name, 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
683
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
684 def visitList(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
685 return self._clone(node, [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
686
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
687 def visitListComp(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
688 quals = [self.visit(x) for x in node.quals]
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
689 return self._clone(node, self.visit(node.expr), quals)
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
690
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
691 def visitListCompFor(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
692 return self._clone(node, self.visit(node.assign), self.visit(node.list),
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
693 [self.visit(x) for x in node.ifs]
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
694 )
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
695
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
696 def visitListCompIf(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
697 return self._clone(node, self.visit(node.test))
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
698
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
699 def visitSlice(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
700 return self._clone(node, self.visit(node.expr), node.flags,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
701 node.lower and self.visit(node.lower) or None,
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
702 node.upper and self.visit(node.upper) or None
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
703 )
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
704
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
705 def visitSliceobj(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
706 return self._clone(node, [self.visit(x) for x in node.nodes])
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
707
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
708 def visitTuple(self, node):
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
709 return self._clone(node, [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
710
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
711
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
712 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
713 """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
714 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
715 """
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
716
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
717 def __init__(self):
586
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
718 self.locals = [CONSTANTS]
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
719
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
720 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
721 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
722 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
723 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
724 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
725 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
726 return node
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
727
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
728 def visitAssName(self, node):
586
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
729 if len(self.locals) > 1:
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
730 self.locals[-1].add(node.name)
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
731 return node
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
732
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
733 def visitAugAssign(self, node):
579
2f7f6b70d5b9 Fix for augmented assignments to local variables. Thanks to Erik Bray for reporting the problem.
cmlenz
parents: 569
diff changeset
734 if isinstance(node.node, ast.Name) \
582
0dc024715f93 Follow-up fix to [693:694]. Again, thanks to Erik Bray for reporting.
cmlenz
parents: 579
diff changeset
735 and node.node.name not in flatten(self.locals):
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
736 name = node.node.name
682
0653f6c1ffdf Assigning to a variable named `data` in a Python code block no longer breaks context lookup. We now use the name `__data__` for internal data, hoping that that name is not as commonly used in templates.
cmlenz
parents: 654
diff changeset
737 node.node = ast.Subscript(ast.Name('__data__'), 'OP_APPLY',
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
738 [ast.Const(name)])
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
739 node.expr = self.visit(node.expr)
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
740 return ast.If([
682
0653f6c1ffdf Assigning to a variable named `data` in a Python code block no longer breaks context lookup. We now use the name `__data__` for internal data, hoping that that name is not as commonly used in templates.
cmlenz
parents: 654
diff changeset
741 (ast.Compare(ast.Const(name), [('in', ast.Name('__data__'))]),
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
742 ast.Stmt([node]))],
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
743 ast.Stmt([ast.Raise(ast.CallFunc(ast.Name('UndefinedError'),
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
744 [ast.Const(name)]),
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
745 None, None)]))
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
746 else:
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
747 return ASTTransformer.visitAugAssign(self, node)
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
748
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
749 def visitClass(self, node):
586
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
750 if len(self.locals) > 1:
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
751 self.locals[-1].add(node.name)
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
752 self.locals.append(set())
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
753 try:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
754 return ASTTransformer.visitClass(self, node)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
755 finally:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
756 self.locals.pop()
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
757
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
758 def visitFor(self, node):
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
759 self.locals.append(set())
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
760 try:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
761 return ASTTransformer.visitFor(self, node)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
762 finally:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
763 self.locals.pop()
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
764
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
765 def visitFunction(self, node):
586
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
766 if len(self.locals) > 1:
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
767 self.locals[-1].add(node.name)
405
5340931530e2 Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents: 401
diff changeset
768 self.locals.append(set(node.argnames))
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
769 try:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
770 return ASTTransformer.visitFunction(self, node)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
771 finally:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
772 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
773
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
774 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
775 self.locals.append(set())
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
776 try:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
777 return ASTTransformer.visitGenExpr(self, node)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
778 finally:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
779 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
780
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
781 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
782 self.locals.append(set(flatten(node.argnames)))
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
783 try:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
784 return ASTTransformer.visitLambda(self, node)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
785 finally:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
786 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
787
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
788 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
789 self.locals.append(set())
565
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
790 try:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
791 return ASTTransformer.visitListComp(self, node)
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
792 finally:
53b37e4f2921 * The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents: 564
diff changeset
793 self.locals.pop()
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
794
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
795 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
796 # 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
797 # generator expression, leave it alone
586
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
798 if node.name not in flatten(self.locals):
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
799 # Otherwise, translate the name ref into a context lookup
682
0653f6c1ffdf Assigning to a variable named `data` in a Python code block no longer breaks context lookup. We now use the name `__data__` for internal data, hoping that that name is not as commonly used in templates.
cmlenz
parents: 654
diff changeset
800 func_args = [ast.Name('__data__'), ast.Const(node.name)]
586
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
801 node = ast.CallFunc(ast.Name('_lookup_name'), func_args)
3670ea49c65a Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents: 582
diff changeset
802 return node
336
7763f7aec949 Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff changeset
803
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
804
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
805 class ExpressionASTTransformer(TemplateASTTransformer):
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
806 """Concrete AST transformer that implements the AST transformations needed
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
807 for code embedded in templates.
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
808 """
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
809
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
810 def visitGetattr(self, node):
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
811 return ast.CallFunc(ast.Name('_lookup_attr'), [
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
812 self.visit(node.expr),
473
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
813 ast.Const(node.attrname)
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
814 ])
4ed941aa0cbf Apply patch from #113, also closing #114.
cmlenz
parents: 442
diff changeset
815
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
816 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
817 return ast.CallFunc(ast.Name('_lookup_item'), [
691
2298d798513e Minor cleanup in eval module.
cmlenz
parents: 684
diff changeset
818 self.visit(node.expr),
357
62de137b9322 Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents: 343
diff changeset
819 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
820 ])
Copyright (C) 2012-2017 Edgewall Software