Mercurial > genshi > genshi-test
annotate genshi/template/eval.py @ 798:c690de5abafd stable-0.5.x
Ported [914], [970], and [971] to 0.5.x branch.
author | cmlenz |
---|---|
date | Thu, 15 Jan 2009 23:50:09 +0000 |
parents | b40efce75bcd |
children | cce33406c1cf |
rev | line source |
---|---|
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
1 # -*- coding: utf-8 -*- |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
2 # |
719 | 3 # Copyright (C) 2006-2008 Edgewall Software |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
4 # All rights reserved. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
5 # |
5f2c7782cd8a
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 |
5f2c7782cd8a
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 |
5f2c7782cd8a
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. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
9 # |
5f2c7782cd8a
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 |
5f2c7782cd8a
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 |
5f2c7782cd8a
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/. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
13 |
5f2c7782cd8a
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.""" |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
15 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
16 import __builtin__ |
5f2c7782cd8a
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
bd5da099c113
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
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
19 import new |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
20 try: |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
21 set |
c5684b65c9b7
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
aa8e85a4085e
* 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
c5684b65c9b7
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 |
601
9ae986bcba9a
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
|
25 from textwrap import dedent |
798 | 26 from types import CodeType |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
27 |
401
9582328f82e5
Make the `Markup` class available by default in template expressions. Closes #67.
cmlenz
parents:
396
diff
changeset
|
28 from genshi.core import Markup |
418
878ffab274a6
Make expression error handling more strict. Closes #88.
cmlenz
parents:
408
diff
changeset
|
29 from genshi.template.base import TemplateRuntimeError |
357
c5684b65c9b7
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
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
31 |
442
ff7c72b52fb2
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', |
ff7c72b52fb2
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
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
34 __docformat__ = 'restructuredtext en' |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
35 |
731
6514d9889ac8
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 |
739 | 37 has_star_import_bug = False |
731
6514d9889ac8
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
|
38 try: |
736 | 39 class _FakeMapping(object): |
731
6514d9889ac8
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 __getitem__ = __setitem__ = lambda *a: None |
6514d9889ac8
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 exec 'from sys import *' in {}, _FakeMapping() |
739 | 42 except SystemError: |
731
6514d9889ac8
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 has_star_import_bug = True |
739 | 44 except TypeError: |
45 pass # Python 2.3 | |
731
6514d9889ac8
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 del _FakeMapping |
6514d9889ac8
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 |
6514d9889ac8
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 def _star_import_patch(mapping, modname): |
6514d9889ac8
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 """This function is used as helper if a Python version with a broken |
6514d9889ac8
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 star-import opcode is in use. |
6514d9889ac8
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 """ |
6514d9889ac8
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 module = __import__(modname, None, None, ['__all__']) |
6514d9889ac8
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 if hasattr(module, '__all__'): |
6514d9889ac8
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 members = module.__all__ |
6514d9889ac8
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 else: |
6514d9889ac8
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
|
56 members = [x for x in module.__dict__ if not x.startswith('_')] |
733
bc5d0850dfaf
Update to r855 for Python 2.3 support. Fixes #221 (hopefully).
athomas
parents:
731
diff
changeset
|
57 mapping.update([(name, getattr(module, name)) for name in members]) |
731
6514d9889ac8
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
|
58 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
59 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
60 class Code(object): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
61 """Abstract base class for the `Expression` and `Suite` classes.""" |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
62 __slots__ = ['source', 'code', 'ast', '_globals'] |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
63 |
606
9ada030ad986
Changed the default error handling mode to "strict".
cmlenz
parents:
604
diff
changeset
|
64 def __init__(self, source, filename=None, lineno=-1, lookup='strict', |
604
6d1fa718794f
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
|
65 xform=None): |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
66 """Create the code object, either from a string, or from an AST node. |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
67 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
68 :param source: either a string containing the source code, or an AST |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
69 node |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
70 :param filename: the (preferably absolute) name of the file containing |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
71 the code |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
72 :param lineno: the number of the line on which the code was found |
442
ff7c72b52fb2
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
|
73 :param lookup: the lookup class that defines how variables are looked |
606
9ada030ad986
Changed the default error handling mode to "strict".
cmlenz
parents:
604
diff
changeset
|
74 up in the context; can be either "strict" (the default), |
9ada030ad986
Changed the default error handling mode to "strict".
cmlenz
parents:
604
diff
changeset
|
75 "lenient", or a custom lookup class |
604
6d1fa718794f
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 :param xform: the AST transformer that should be applied to the code; |
6d1fa718794f
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 if `None`, the appropriate transformation is chosen |
6d1fa718794f
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
|
78 depending on the mode |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
79 """ |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
80 if isinstance(source, basestring): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
81 self.source = source |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
82 node = _parse(source, mode=self.mode) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
83 else: |
601
9ae986bcba9a
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 assert isinstance(source, ast.Node), \ |
9ae986bcba9a
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
|
85 'Expected string or AST node, but got %r' % source |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
86 self.source = '?' |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
87 if self.mode == 'eval': |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
88 node = ast.Expression(source) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
89 else: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
90 node = ast.Module(None, source) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
91 |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
92 self.ast = node |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
93 self.code = _compile(node, self.source, mode=self.mode, |
604
6d1fa718794f
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
|
94 filename=filename, lineno=lineno, xform=xform) |
442
ff7c72b52fb2
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 if lookup is None: |
ff7c72b52fb2
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 lookup = LenientLookup |
ff7c72b52fb2
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 elif isinstance(lookup, basestring): |
ff7c72b52fb2
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
|
98 lookup = {'lenient': LenientLookup, 'strict': StrictLookup}[lookup] |
654
12f3a60d5528
Fix thread-safety problem in template code evaluation. Closes #158. Thanks to Christian Boos for the patch.
cmlenz
parents:
606
diff
changeset
|
99 self._globals = lookup.globals |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
100 |
715 | 101 def __getstate__(self): |
102 state = {'source': self.source, 'ast': self.ast, | |
103 'lookup': self._globals.im_self} | |
104 c = self.code | |
105 state['code'] = (c.co_nlocals, c.co_stacksize, c.co_flags, c.co_code, | |
106 c.co_consts, c.co_names, c.co_varnames, c.co_filename, | |
107 c.co_name, c.co_firstlineno, c.co_lnotab, (), ()) | |
108 return state | |
109 | |
110 def __setstate__(self, state): | |
111 self.source = state['source'] | |
112 self.ast = state['ast'] | |
113 self.code = new.code(0, *state['code']) | |
114 self._globals = state['lookup'].globals | |
115 | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
116 def __eq__(self, other): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
117 return (type(other) == type(self)) and (self.code == other.code) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
118 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
119 def __hash__(self): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
120 return hash(self.code) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
121 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
122 def __ne__(self, other): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
123 return not self == other |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
124 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
125 def __repr__(self): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
126 return '%s(%r)' % (self.__class__.__name__, self.source) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
127 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
128 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
129 class Expression(Code): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
130 """Evaluates Python expressions used in templates. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
131 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
132 >>> data = dict(test='Foo', items=[1, 2, 3], dict={'some': 'thing'}) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
133 >>> Expression('test').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
134 'Foo' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
135 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
136 >>> Expression('items[0]').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
137 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
138 >>> Expression('items[-1]').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
139 3 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
140 >>> Expression('dict["some"]').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
141 'thing' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
142 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
143 Similar to e.g. Javascript, expressions in templates can use the dot |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
144 notation for attribute access to access items in mappings: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
145 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
146 >>> Expression('dict.some').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
147 'thing' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
148 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
149 This also works the other way around: item access can be used to access |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
150 any object attribute: |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
151 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
152 >>> class MyClass(object): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
153 ... myattr = 'Bar' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
154 >>> data = dict(mine=MyClass(), key='myattr') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
155 >>> Expression('mine.myattr').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
156 'Bar' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
157 >>> Expression('mine["myattr"]').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
158 'Bar' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
159 >>> Expression('mine[key]').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
160 'Bar' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
161 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
162 All of the standard Python operators are available to template expressions. |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
163 Built-in functions such as ``len()`` are also available in template |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
164 expressions: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
165 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
166 >>> data = dict(items=[1, 2, 3]) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
167 >>> Expression('len(items)').evaluate(data) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
168 3 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
169 """ |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
170 __slots__ = [] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
171 mode = 'eval' |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
172 |
343
4ff2338e89cd
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
|
173 def evaluate(self, data): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
174 """Evaluate the expression against the given data dictionary. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
175 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
176 :param data: a mapping containing the data to evaluate against |
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
177 :return: the result of the evaluation |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
178 """ |
418
878ffab274a6
Make expression error handling more strict. Closes #88.
cmlenz
parents:
408
diff
changeset
|
179 __traceback_hide__ = 'before_and_this' |
691 | 180 _globals = self._globals(data) |
682
75795aadf920
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
|
181 return eval(self.code, _globals, {'__data__': data}) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
182 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
183 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
184 class Suite(Code): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
185 """Executes Python statements used in templates. |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
186 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
187 >>> data = dict(test='Foo', items=[1, 2, 3], dict={'some': 'thing'}) |
473 | 188 >>> Suite("foo = dict['some']").execute(data) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
189 >>> data['foo'] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
190 'thing' |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
191 """ |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
192 __slots__ = [] |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
193 mode = 'exec' |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
194 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
195 def execute(self, data): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
196 """Execute the suite in the given data dictionary. |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
197 |
425
5b248708bbed
Try to use proper reStructuredText for docstrings throughout.
cmlenz
parents:
418
diff
changeset
|
198 :param data: a mapping containing the data to execute in |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
199 """ |
418
878ffab274a6
Make expression error handling more strict. Closes #88.
cmlenz
parents:
408
diff
changeset
|
200 __traceback_hide__ = 'before_and_this' |
691 | 201 _globals = self._globals(data) |
442
ff7c72b52fb2
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
|
202 exec self.code in _globals, data |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
203 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
204 |
442
ff7c72b52fb2
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 UNDEFINED = object() |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 class UndefinedError(TemplateRuntimeError): |
ff7c72b52fb2
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 """Exception thrown when a template expression attempts to access a variable |
ff7c72b52fb2
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 not defined in the context. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 :see: `LenientLookup`, `StrictLookup` |
ff7c72b52fb2
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 """ |
ff7c72b52fb2
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 def __init__(self, name, owner=UNDEFINED): |
ff7c72b52fb2
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 if owner is not UNDEFINED: |
ff7c72b52fb2
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 message = '%s has no member named "%s"' % (repr(owner), name) |
ff7c72b52fb2
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 else: |
ff7c72b52fb2
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 message = '"%s" not defined' % name |
ff7c72b52fb2
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 TemplateRuntimeError.__init__(self, message) |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 class Undefined(object): |
ff7c72b52fb2
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 """Represents a reference to an undefined variable. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 Unlike the Python runtime, template expressions can refer to an undefined |
ff7c72b52fb2
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 variable without causing a `NameError` to be raised. The result will be an |
ff7c72b52fb2
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 instance of the `Undefined` class, which is treated the same as ``False`` in |
ff7c72b52fb2
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 conditions, but raise an exception on any other operation: |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 >>> foo = Undefined('foo') |
ff7c72b52fb2
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 >>> bool(foo) |
ff7c72b52fb2
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 False |
ff7c72b52fb2
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 >>> list(foo) |
ff7c72b52fb2
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 [] |
ff7c72b52fb2
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 >>> print foo |
ff7c72b52fb2
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 undefined |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 However, calling an undefined variable, or trying to access an attribute |
ff7c72b52fb2
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 of that variable, will raise an exception that includes the name used to |
ff7c72b52fb2
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 reference that undefined variable. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 >>> foo('bar') |
ff7c72b52fb2
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 Traceback (most recent call last): |
ff7c72b52fb2
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 ... |
ff7c72b52fb2
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 UndefinedError: "foo" not defined |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 >>> foo.bar |
ff7c72b52fb2
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 Traceback (most recent call last): |
ff7c72b52fb2
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 ... |
ff7c72b52fb2
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 UndefinedError: "foo" not defined |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 :see: `LenientLookup` |
ff7c72b52fb2
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 """ |
ff7c72b52fb2
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 __slots__ = ['_name', '_owner'] |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 def __init__(self, name, owner=UNDEFINED): |
ff7c72b52fb2
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 """Initialize the object. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 name: the name of the reference |
ff7c72b52fb2
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
|
260 :param owner: the owning object, if the variable is accessed as a member |
418
878ffab274a6
Make expression error handling more strict. Closes #88.
cmlenz
parents:
408
diff
changeset
|
261 """ |
442
ff7c72b52fb2
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._name = name |
ff7c72b52fb2
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
|
263 self._owner = owner |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
264 |
442
ff7c72b52fb2
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 def __iter__(self): |
ff7c72b52fb2
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 return iter([]) |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 def __nonzero__(self): |
ff7c72b52fb2
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 return False |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 def __repr__(self): |
ff7c72b52fb2
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 return '<%s %r>' % (self.__class__.__name__, self._name) |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 def __str__(self): |
ff7c72b52fb2
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 return 'undefined' |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 def _die(self, *args, **kwargs): |
ff7c72b52fb2
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 """Raise an `UndefinedError`.""" |
ff7c72b52fb2
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 __traceback_hide__ = True |
ff7c72b52fb2
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 raise UndefinedError(self._name, self._owner) |
ff7c72b52fb2
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 __call__ = __getattr__ = __getitem__ = _die |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 class LookupBase(object): |
ff7c72b52fb2
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 """Abstract base class for variable lookup implementations.""" |
ff7c72b52fb2
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
|
286 |
691 | 287 def globals(cls, data): |
442
ff7c72b52fb2
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 """Construct the globals dictionary to use as the execution context for |
ff7c72b52fb2
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
|
289 the expression or suite. |
418
878ffab274a6
Make expression error handling more strict. Closes #88.
cmlenz
parents:
408
diff
changeset
|
290 """ |
442
ff7c72b52fb2
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
|
291 return { |
691 | 292 '__data__': data, |
442
ff7c72b52fb2
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_name': cls.lookup_name, |
ff7c72b52fb2
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
|
294 '_lookup_attr': cls.lookup_attr, |
579
71e3205925e6
Fix for augmented assignments to local variables. Thanks to Erik Bray for reporting the problem.
cmlenz
parents:
569
diff
changeset
|
295 '_lookup_item': cls.lookup_item, |
731
6514d9889ac8
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
|
296 '_star_import_patch': _star_import_patch, |
691 | 297 'UndefinedError': UndefinedError, |
442
ff7c72b52fb2
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 } |
ff7c72b52fb2
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 globals = classmethod(globals) |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 def lookup_name(cls, data, name): |
ff7c72b52fb2
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 __traceback_hide__ = True |
ff7c72b52fb2
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 val = data.get(name, UNDEFINED) |
ff7c72b52fb2
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 if val is UNDEFINED: |
ff7c72b52fb2
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 val = BUILTINS.get(name, val) |
ff7c72b52fb2
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
|
306 if val is UNDEFINED: |
569
4cbd8031ed76
Attribute access in template expressions no longer silently ignores exceptions other than `AttributeError` raised in the attribute accessor.
cmlenz
parents:
568
diff
changeset
|
307 val = cls.undefined(name) |
442
ff7c72b52fb2
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 return val |
ff7c72b52fb2
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 lookup_name = classmethod(lookup_name) |
ff7c72b52fb2
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
|
310 |
691 | 311 def lookup_attr(cls, obj, key): |
442
ff7c72b52fb2
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
|
312 __traceback_hide__ = True |
702
ebae1774d188
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 try: |
ebae1774d188
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 val = getattr(obj, key) |
ebae1774d188
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 except AttributeError: |
ebae1774d188
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 if hasattr(obj.__class__, key): |
ebae1774d188
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 raise |
ebae1774d188
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 else: |
ebae1774d188
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 try: |
ebae1774d188
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 val = obj[key] |
ebae1774d188
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 except (KeyError, TypeError): |
ebae1774d188
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
|
322 val = cls.undefined(key, owner=obj) |
569
4cbd8031ed76
Attribute access in template expressions no longer silently ignores exceptions other than `AttributeError` raised in the attribute accessor.
cmlenz
parents:
568
diff
changeset
|
323 return val |
442
ff7c72b52fb2
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 lookup_attr = classmethod(lookup_attr) |
ff7c72b52fb2
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
|
325 |
691 | 326 def lookup_item(cls, obj, key): |
442
ff7c72b52fb2
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 __traceback_hide__ = True |
ff7c72b52fb2
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 if len(key) == 1: |
ff7c72b52fb2
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 key = key[0] |
ff7c72b52fb2
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 try: |
ff7c72b52fb2
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 return obj[key] |
ff7c72b52fb2
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 except (AttributeError, KeyError, IndexError, TypeError), e: |
ff7c72b52fb2
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 if isinstance(key, basestring): |
ff7c72b52fb2
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 val = getattr(obj, key, UNDEFINED) |
ff7c72b52fb2
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
|
335 if val is UNDEFINED: |
569
4cbd8031ed76
Attribute access in template expressions no longer silently ignores exceptions other than `AttributeError` raised in the attribute accessor.
cmlenz
parents:
568
diff
changeset
|
336 val = cls.undefined(key, owner=obj) |
442
ff7c72b52fb2
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 return val |
ff7c72b52fb2
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 raise |
ff7c72b52fb2
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 lookup_item = classmethod(lookup_item) |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 def undefined(cls, key, owner=UNDEFINED): |
ff7c72b52fb2
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 """Can be overridden by subclasses to specify behavior when undefined |
ff7c72b52fb2
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 variables are accessed. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 key: the name of the variable |
ff7c72b52fb2
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 :param owner: the owning object, if the variable is accessed as a member |
ff7c72b52fb2
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 """ |
ff7c72b52fb2
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 raise NotImplementedError |
ff7c72b52fb2
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 undefined = classmethod(undefined) |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 class LenientLookup(LookupBase): |
ff7c72b52fb2
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 """Default variable lookup mechanism for expressions. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 When an undefined variable is referenced using this lookup style, the |
ff7c72b52fb2
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 reference evaluates to an instance of the `Undefined` class: |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 >>> expr = Expression('nothing', lookup='lenient') |
ff7c72b52fb2
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 = expr.evaluate({}) |
ff7c72b52fb2
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 >>> undef |
ff7c72b52fb2
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 <Undefined 'nothing'> |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 The same will happen when a non-existing attribute or item is accessed on |
ff7c72b52fb2
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 an existing object: |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 = Expression('something.nil', lookup='lenient') |
ff7c72b52fb2
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 >>> expr.evaluate({'something': dict()}) |
ff7c72b52fb2
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 <Undefined 'nil'> |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 See the documentation of the `Undefined` class for details on the behavior |
ff7c72b52fb2
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 of such objects. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 :see: `StrictLookup` |
ff7c72b52fb2
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 """ |
ff7c72b52fb2
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 def undefined(cls, key, owner=UNDEFINED): |
ff7c72b52fb2
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 """Return an ``Undefined`` object.""" |
ff7c72b52fb2
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 __traceback_hide__ = True |
ff7c72b52fb2
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 return Undefined(key, owner=owner) |
ff7c72b52fb2
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 undefined = classmethod(undefined) |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 class StrictLookup(LookupBase): |
ff7c72b52fb2
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 """Strict variable lookup mechanism for expressions. |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 Referencing an undefined variable using this lookup style will immediately |
ff7c72b52fb2
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 raise an ``UndefinedError``: |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 = Expression('nothing', lookup='strict') |
ff7c72b52fb2
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 >>> expr.evaluate({}) |
ff7c72b52fb2
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 Traceback (most recent call last): |
ff7c72b52fb2
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 ... |
ff7c72b52fb2
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 UndefinedError: "nothing" not defined |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 The same happens when a non-existing attribute or item is accessed on an |
ff7c72b52fb2
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 existing object: |
ff7c72b52fb2
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 |
ff7c72b52fb2
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 = Expression('something.nil', lookup='strict') |
ff7c72b52fb2
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 >>> expr.evaluate({'something': dict()}) |
ff7c72b52fb2
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 Traceback (most recent call last): |
ff7c72b52fb2
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 ... |
ff7c72b52fb2
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 UndefinedError: {} has no member named "nil" |
ff7c72b52fb2
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 """ |
ff7c72b52fb2
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 def undefined(cls, key, owner=UNDEFINED): |
ff7c72b52fb2
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 """Raise an ``UndefinedError`` immediately.""" |
ff7c72b52fb2
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 __traceback_hide__ = True |
ff7c72b52fb2
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 raise UndefinedError(key, owner=owner) |
ff7c72b52fb2
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 undefined = classmethod(undefined) |
ff7c72b52fb2
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
|
408 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
409 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
410 def _parse(source, mode='eval'): |
601
9ae986bcba9a
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 source = source.strip() |
9ae986bcba9a
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 if mode == 'exec': |
9ae986bcba9a
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
|
413 lines = [line.expandtabs() for line in source.splitlines()] |
716
fe05ebf91775
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 if lines: |
fe05ebf91775
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 first = lines[0] |
fe05ebf91775
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 rest = dedent('\n'.join(lines[1:])).rstrip() |
fe05ebf91775
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 if first.rstrip().endswith(':') and not rest[0].isspace(): |
fe05ebf91775
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 rest = '\n'.join([' %s' % line for line in rest.splitlines()]) |
fe05ebf91775
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
|
419 source = '\n'.join([first, rest]) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
420 if isinstance(source, unicode): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
421 source = '\xef\xbb\xbf' + source.encode('utf-8') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
422 return parse(source, mode) |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
423 |
604
6d1fa718794f
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 def _compile(node, source=None, mode='eval', filename=None, lineno=-1, |
6d1fa718794f
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 xform=None): |
6d1fa718794f
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 if xform is None: |
6d1fa718794f
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 xform = {'eval': ExpressionASTTransformer}.get(mode, |
6d1fa718794f
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
|
428 TemplateASTTransformer) |
473 | 429 tree = xform().visit(node) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
430 if isinstance(filename, unicode): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
431 # unicode file names not allowed for code objects |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
432 filename = filename.encode('utf-8', 'replace') |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
433 elif not filename: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
434 filename = '<string>' |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
435 tree.filename = filename |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
436 if lineno <= 0: |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
437 lineno = 1 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
438 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
439 if mode == 'eval': |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
440 gen = ExpressionCodeGenerator(tree) |
601
9ae986bcba9a
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
|
441 name = '<Expression %r>' % (source or '?') |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
442 else: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
443 gen = ModuleCodeGenerator(tree) |
601
9ae986bcba9a
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
|
444 lines = source.splitlines() |
716
fe05ebf91775
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 if not lines: |
fe05ebf91775
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 extract = '' |
fe05ebf91775
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 else: |
fe05ebf91775
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
|
448 extract = lines[0] |
601
9ae986bcba9a
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 if len(lines) > 1: |
9ae986bcba9a
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 extract += ' ...' |
9ae986bcba9a
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
|
451 name = '<Suite %r>' % (extract) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
452 gen.optimized = True |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
453 code = gen.getCode() |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
454 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
455 # We'd like to just set co_firstlineno, but it's readonly. So we need to |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
456 # clone the code object while adjusting the line number |
798 | 457 return CodeType(0, code.co_nlocals, code.co_stacksize, |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
458 code.co_flags | 0x0040, code.co_code, code.co_consts, |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
459 code.co_names, code.co_varnames, filename, name, lineno, |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
460 code.co_lnotab, (), ()) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
461 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
462 BUILTINS = __builtin__.__dict__.copy() |
442
ff7c72b52fb2
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
|
463 BUILTINS.update({'Markup': Markup, 'Undefined': Undefined}) |
563
80fb59bd2342
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
|
464 CONSTANTS = frozenset(['False', 'True', 'None', 'NotImplemented', 'Ellipsis']) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
465 |
564
b3b07279b86c
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
|
466 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
467 class ASTTransformer(object): |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
468 """General purpose base class for AST transformations. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
469 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
470 Every visitor method can be overridden to return an AST node that has been |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
471 altered or replaced in some way. |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
472 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
473 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
474 def visit(self, node): |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
475 if node is None: |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
476 return None |
473 | 477 if type(node) is tuple: |
478 return tuple([self.visit(n) for n in node]) | |
479 visitor = getattr(self, 'visit%s' % node.__class__.__name__, | |
480 self._visitDefault) | |
481 return visitor(node) | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
482 |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
483 def _clone(self, node, *args): |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
484 lineno = getattr(node, 'lineno', None) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
485 node = node.__class__(*args) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
486 if lineno is not None: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
487 node.lineno = lineno |
684
2a52ea05fe9f
Fix one Python 2.3 compatibility in the expression evaluation code. See #177. One more to go, though.
cmlenz
parents:
682
diff
changeset
|
488 if isinstance(node, (ast.Class, ast.Function, ast.Lambda)) or \ |
736 | 489 hasattr(ast, 'GenExpr') and isinstance(node, ast.GenExpr): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
490 node.filename = '<string>' # workaround for bug in pycodegen |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
491 return node |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
492 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
493 def _visitDefault(self, node): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
494 return node |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
495 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
496 def visitExpression(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
497 return self._clone(node, self.visit(node.node)) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
498 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
499 def visitModule(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
500 return self._clone(node, node.doc, self.visit(node.node)) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
501 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
502 def visitStmt(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
503 return self._clone(node, [self.visit(x) for x in node.nodes]) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
504 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
505 # Classes, Functions & Accessors |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
506 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
507 def visitCallFunc(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
508 return self._clone(node, self.visit(node.node), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
509 [self.visit(x) for x in node.args], |
aa8e85a4085e
* 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.star_args and self.visit(node.star_args) or None, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
511 node.dstar_args and self.visit(node.dstar_args) or None |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
512 ) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
513 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
514 def visitClass(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
515 return self._clone(node, node.name, [self.visit(x) for x in node.bases], |
568
8f0d601afc0c
AST transformer needs to also handle the class body.
cmlenz
parents:
565
diff
changeset
|
516 node.doc, self.visit(node.code) |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
517 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
518 |
731
6514d9889ac8
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 def visitFrom(self, node): |
6514d9889ac8
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 if not has_star_import_bug or node.names != [('*', None)]: |
6514d9889ac8
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 # This is a Python 2.4 bug. Only if we have a broken Python |
6514d9889ac8
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 # version we have to apply the hack |
6514d9889ac8
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 node |
739 | 524 new_node = ast.Discard(ast.CallFunc( |
731
6514d9889ac8
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('_star_import_patch'), |
6514d9889ac8
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 [ast.Name('__data__'), ast.Const(node.modname)], None, None |
739 | 527 )) |
528 if hasattr(node, 'lineno'): # No lineno in Python 2.3 | |
529 new_node.lineno = node.lineno | |
530 return new_node | |
731
6514d9889ac8
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
|
531 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
532 def visitFunction(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
533 args = [] |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
534 if hasattr(node, 'decorators'): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
535 args.append(self.visit(node.decorators)) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
536 return self._clone(node, *args + [ |
aa8e85a4085e
* 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.name, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
538 node.argnames, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
539 [self.visit(x) for x in node.defaults], |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
540 node.flags, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
541 node.doc, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
542 self.visit(node.code) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
543 ]) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
544 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
545 def visitGetattr(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
546 return self._clone(node, self.visit(node.expr), node.attrname) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
547 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
548 def visitLambda(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
549 node = self._clone(node, node.argnames, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
550 [self.visit(x) for x in node.defaults], node.flags, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
551 self.visit(node.code) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
552 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
553 return node |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
554 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
555 def visitSubscript(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
556 return self._clone(node, self.visit(node.expr), node.flags, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
557 [self.visit(x) for x in node.subs] |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
558 ) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
559 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
560 # Statements |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
561 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
562 def visitAssert(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
563 return self._clone(node, self.visit(node.test), self.visit(node.fail)) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
564 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
565 def visitAssign(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
566 return self._clone(node, [self.visit(x) for x in node.nodes], |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
567 self.visit(node.expr) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
568 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
569 |
473 | 570 def visitAssAttr(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
571 return self._clone(node, self.visit(node.expr), node.attrname, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
572 node.flags |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
573 ) |
473 | 574 |
575 def visitAugAssign(self, node): | |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
576 return self._clone(node, self.visit(node.node), node.op, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
577 self.visit(node.expr) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
578 ) |
473 | 579 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
580 def visitDecorators(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
581 return self._clone(node, [self.visit(x) for x in node.nodes]) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
582 |
473 | 583 def visitExec(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
584 return self._clone(node, self.visit(node.expr), self.visit(node.locals), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
585 self.visit(node.globals) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
586 ) |
473 | 587 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
588 def visitFor(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
589 return self._clone(node, self.visit(node.assign), self.visit(node.list), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
590 self.visit(node.body), self.visit(node.else_) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
591 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
592 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
593 def visitIf(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
594 return self._clone(node, [self.visit(x) for x in node.tests], |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
595 self.visit(node.else_) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
596 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
597 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
598 def _visitPrint(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
599 return self._clone(node, [self.visit(x) for x in node.nodes], |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
600 self.visit(node.dest) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
601 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
602 visitPrint = visitPrintnl = _visitPrint |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
603 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
604 def visitRaise(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
605 return self._clone(node, self.visit(node.expr1), self.visit(node.expr2), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
606 self.visit(node.expr3) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
607 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
608 |
473 | 609 def visitReturn(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
610 return self._clone(node, self.visit(node.value)) |
473 | 611 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
612 def visitTryExcept(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
613 return self._clone(node, self.visit(node.body), self.visit(node.handlers), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
614 self.visit(node.else_) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
615 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
616 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
617 def visitTryFinally(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
618 return self._clone(node, self.visit(node.body), self.visit(node.final)) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
619 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
620 def visitWhile(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
621 return self._clone(node, self.visit(node.test), self.visit(node.body), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
622 self.visit(node.else_) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
623 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
624 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
625 def visitWith(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
626 return self._clone(node, self.visit(node.expr), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
627 [self.visit(x) for x in node.vars], self.visit(node.body) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
628 ) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
629 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
630 def visitYield(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
631 return self._clone(node, self.visit(node.value)) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
632 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
633 # Operators |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
634 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
635 def _visitBoolOp(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
636 return self._clone(node, [self.visit(x) for x in node.nodes]) |
396 | 637 visitAnd = visitOr = visitBitand = visitBitor = visitBitxor = _visitBoolOp |
473 | 638 visitAssTuple = visitAssList = _visitBoolOp |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
639 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
640 def _visitBinOp(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
641 return self._clone(node, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
642 (self.visit(node.left), self.visit(node.right)) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
643 ) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
644 visitAdd = visitSub = _visitBinOp |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
645 visitDiv = visitFloorDiv = visitMod = visitMul = visitPower = _visitBinOp |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
646 visitLeftShift = visitRightShift = _visitBinOp |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
647 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
648 def visitCompare(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
649 return self._clone(node, self.visit(node.expr), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
650 [(op, self.visit(n)) for op, n in node.ops] |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
651 ) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
652 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
653 def _visitUnaryOp(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
654 return self._clone(node, self.visit(node.expr)) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
655 visitUnaryAdd = visitUnarySub = visitNot = visitInvert = _visitUnaryOp |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
656 visitBackquote = visitDiscard = _visitUnaryOp |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
657 |
393
a056613621ab
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
658 def visitIfExp(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
659 return self._clone(node, self.visit(node.test), self.visit(node.then), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
660 self.visit(node.else_) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
661 ) |
393
a056613621ab
add support for Python 2.5 conditional expressions (fixes #74)
mgood
parents:
382
diff
changeset
|
662 |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
663 # Identifiers, Literals and Comprehensions |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
664 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
665 def visitDict(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
666 return self._clone(node, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
667 [(self.visit(k), self.visit(v)) for k, v in node.items] |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
668 ) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
669 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
670 def visitGenExpr(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
671 return self._clone(node, self.visit(node.code)) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
672 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
673 def visitGenExprFor(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
674 return self._clone(node, self.visit(node.assign), self.visit(node.iter), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
675 [self.visit(x) for x in node.ifs] |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
676 ) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
677 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
678 def visitGenExprIf(self, node): |
565
aa8e85a4085e
* 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.test)) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
680 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
681 def visitGenExprInner(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
682 quals = [self.visit(x) for x in node.quals] |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
683 return self._clone(node, self.visit(node.expr), quals) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
684 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
685 def visitKeyword(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
686 return self._clone(node, node.name, self.visit(node.expr)) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
687 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
688 def visitList(self, node): |
565
aa8e85a4085e
* 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(n) for n in node.nodes]) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
690 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
691 def visitListComp(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
692 quals = [self.visit(x) for x in node.quals] |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
693 return self._clone(node, self.visit(node.expr), quals) |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
694 |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
695 def visitListCompFor(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
696 return self._clone(node, self.visit(node.assign), self.visit(node.list), |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
697 [self.visit(x) for x in node.ifs] |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
698 ) |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
699 |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
700 def visitListCompIf(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
701 return self._clone(node, self.visit(node.test)) |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
702 |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
703 def visitSlice(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
704 return self._clone(node, self.visit(node.expr), node.flags, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
705 node.lower and self.visit(node.lower) or None, |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
706 node.upper and self.visit(node.upper) or None |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
707 ) |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
708 |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
709 def visitSliceobj(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
710 return self._clone(node, [self.visit(x) for x in node.nodes]) |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
711 |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
712 def visitTuple(self, node): |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
713 return self._clone(node, [self.visit(n) for n in node.nodes]) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
714 |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
715 |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
716 class TemplateASTTransformer(ASTTransformer): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
717 """Concrete AST transformer that implements the AST transformations needed |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
718 for code embedded in templates. |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
719 """ |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
720 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
721 def __init__(self): |
586
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
722 self.locals = [CONSTANTS] |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
723 |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
724 def visitConst(self, node): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
725 if isinstance(node.value, str): |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
726 try: # If the string is ASCII, return a `str` object |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
727 node.value.decode('ascii') |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
728 except ValueError: # Otherwise return a `unicode` object |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
729 return ast.Const(node.value.decode('utf-8')) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
730 return node |
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
731 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
732 def visitAssName(self, node): |
586
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
733 if len(self.locals) > 1: |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
734 self.locals[-1].add(node.name) |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
735 return node |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
736 |
473 | 737 def visitAugAssign(self, node): |
579
71e3205925e6
Fix for augmented assignments to local variables. Thanks to Erik Bray for reporting the problem.
cmlenz
parents:
569
diff
changeset
|
738 if isinstance(node.node, ast.Name) \ |
582
b21da79c9bde
Follow-up fix to [693:694]. Again, thanks to Erik Bray for reporting.
cmlenz
parents:
579
diff
changeset
|
739 and node.node.name not in flatten(self.locals): |
473 | 740 name = node.node.name |
682
75795aadf920
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 node.node = ast.Subscript(ast.Name('__data__'), 'OP_APPLY', |
473 | 742 [ast.Const(name)]) |
743 node.expr = self.visit(node.expr) | |
744 return ast.If([ | |
682
75795aadf920
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
|
745 (ast.Compare(ast.Const(name), [('in', ast.Name('__data__'))]), |
473 | 746 ast.Stmt([node]))], |
747 ast.Stmt([ast.Raise(ast.CallFunc(ast.Name('UndefinedError'), | |
748 [ast.Const(name)]), | |
749 None, None)])) | |
750 else: | |
751 return ASTTransformer.visitAugAssign(self, node) | |
752 | |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
753 def visitClass(self, node): |
586
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
754 if len(self.locals) > 1: |
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
755 self.locals[-1].add(node.name) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
756 self.locals.append(set()) |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
757 try: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
758 return ASTTransformer.visitClass(self, node) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
759 finally: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
760 self.locals.pop() |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
761 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
762 def visitFor(self, node): |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
763 self.locals.append(set()) |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
764 try: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
765 return ASTTransformer.visitFor(self, node) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
766 finally: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
767 self.locals.pop() |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
768 |
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
769 def visitFunction(self, node): |
586
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
770 if len(self.locals) > 1: |
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
771 self.locals[-1].add(node.name) |
405
bd5da099c113
Support for Python code blocks using the `<?python ?>` processing instruction. Closes #84.
cmlenz
parents:
401
diff
changeset
|
772 self.locals.append(set(node.argnames)) |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
773 try: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
774 return ASTTransformer.visitFunction(self, node) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
775 finally: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
776 self.locals.pop() |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
777 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
778 def visitGenExpr(self, node): |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
779 self.locals.append(set()) |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
780 try: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
781 return ASTTransformer.visitGenExpr(self, node) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
782 finally: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
783 self.locals.pop() |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
784 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
785 def visitLambda(self, node): |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
786 self.locals.append(set(flatten(node.argnames))) |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
787 try: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
788 return ASTTransformer.visitLambda(self, node) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
789 finally: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
790 self.locals.pop() |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
791 |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
792 def visitListComp(self, node): |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
793 self.locals.append(set()) |
565
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
794 try: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
795 return ASTTransformer.visitListComp(self, node) |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
796 finally: |
aa8e85a4085e
* The I18n extractor now handles gettext function calls that use non-string parameters as well as keyword arguments.
cmlenz
parents:
564
diff
changeset
|
797 self.locals.pop() |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
798 |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
799 def visitName(self, node): |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
800 # If the name refers to a local inside a lambda, list comprehension, or |
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
801 # generator expression, leave it alone |
586
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
802 if node.name not in flatten(self.locals): |
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
803 # Otherwise, translate the name ref into a context lookup |
682
75795aadf920
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
|
804 func_args = [ast.Name('__data__'), ast.Const(node.name)] |
586
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
805 node = ast.CallFunc(ast.Name('_lookup_name'), func_args) |
5413c9d95db1
Fixes for nonlocal variable access in code blocks, as well as nested function and class definitions.
cmlenz
parents:
582
diff
changeset
|
806 return node |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
807 |
473 | 808 |
809 class ExpressionASTTransformer(TemplateASTTransformer): | |
810 """Concrete AST transformer that implements the AST transformations needed | |
811 for code embedded in templates. | |
812 """ | |
813 | |
814 def visitGetattr(self, node): | |
815 return ast.CallFunc(ast.Name('_lookup_attr'), [ | |
691 | 816 self.visit(node.expr), |
473 | 817 ast.Const(node.attrname) |
818 ]) | |
819 | |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
820 def visitSubscript(self, node): |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
821 return ast.CallFunc(ast.Name('_lookup_item'), [ |
691 | 822 self.visit(node.expr), |
357
c5684b65c9b7
Improve the way locals (in list comprehensions, lambdas and generator expressions) are handled in template expressions.
cmlenz
parents:
343
diff
changeset
|
823 ast.Tuple([self.visit(sub) for sub in node.subs]) |
336
5f2c7782cd8a
Refactoring: `genshi.template` is now a package, it was getting way to crowded in that file.
cmlenz
parents:
diff
changeset
|
824 ]) |