Mercurial > p > roundup > code
annotate roundup/cgi/PageTemplates/PythonExpr.py @ 5676:e70885fe72a4
issue2551026: template variable not defined even though it is.
Fix issue where variables defined in TAL expression are not
available in the scope of the definition. (Tom Ekberg (tekberg))
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Tue, 26 Mar 2019 17:31:28 -0400 |
| parents | f8673e720f30 |
| children | fed0f839c260 |
| rev | line source |
|---|---|
| 1049 | 1 ############################################################################## |
| 2 # | |
| 3 # Copyright (c) 2001 Zope Corporation and Contributors. All Rights Reserved. | |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
4 # |
| 1049 | 5 # This software is subject to the provisions of the Zope Public License, |
| 6 # Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. | |
| 7 # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED | |
| 8 # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
| 9 # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS | |
| 10 # FOR A PARTICULAR PURPOSE | |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
11 # |
|
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
12 ############################################################################## |
|
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
13 # Modified for Roundup: |
| 1049 | 14 # |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
15 # 1. more informative traceback info |
| 1049 | 16 |
| 17 """Generic Python Expression Handler | |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
18 """ |
|
1071
c08b3820edd1
Adhering to ZPL
Richard Jones <richard@users.sourceforge.net>
parents:
1065
diff
changeset
|
19 |
|
5676
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
20 import symtable |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
21 |
|
5388
d26921b851c3
Python 3 preparation: make relative imports explicit.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5384
diff
changeset
|
22 from .TALES import CompilerError |
| 1049 | 23 from sys import exc_info |
| 24 | |
| 25 class getSecurityManager: | |
| 26 '''Null security manager''' | |
| 27 def validate(self, *args, **kwargs): | |
| 28 return 1 | |
| 29 addContext = removeContext = validateValue = validate | |
| 30 | |
| 31 class PythonExpr: | |
| 32 def __init__(self, name, expr, engine): | |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
33 self.expr = expr = expr.strip().replace('\n', ' ') |
| 1049 | 34 try: |
| 35 d = {} | |
|
5676
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
36 self.f_code = 'def f():\n return %s\n' % expr.strip() |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
37 exec(self.f_code, d) |
| 1049 | 38 self._f = d['f'] |
| 39 except: | |
|
5378
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
4570
diff
changeset
|
40 raise CompilerError(('Python expression error:\n' |
|
35ea9b1efc14
Python 3 preparation: "raise" syntax.
Joseph Myers <jsm@polyomino.org.uk>
parents:
4570
diff
changeset
|
41 '%s: %s') % exc_info()[:2]) |
| 1049 | 42 self._get_used_names() |
| 43 | |
| 44 def _get_used_names(self): | |
| 45 self._f_varnames = vnames = [] | |
|
5676
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
46 for vname in self._get_from_symtab(): |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
47 if vname[0] not in '$_.': |
| 1049 | 48 vnames.append(vname) |
| 49 | |
|
5676
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
50 def _get_from_symtab(self): |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
51 """ |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
52 Get the variables used in the 'f' function. |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
53 """ |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
54 variables = set() |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
55 table = symtable.symtable(self.f_code, "<string>", "exec") |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
56 if table.has_children(): |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
57 variables.update(self._walk_children(table)) |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
58 return variables |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
59 |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
60 def _walk_children(self, sym): |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
61 """ |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
62 Get the variables at this level. Recurse to get them all. |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
63 """ |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
64 variables = set() |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
65 for child in sym.get_children(): |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
66 variables.update(set(child.get_identifiers())) |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
67 if child.has_children(): |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
68 variables.update(self._walk_children(child)) |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
69 return variables |
|
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
70 |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
71 def _bind_used_names(self, econtext, _marker=[]): |
| 1049 | 72 # Bind template variables |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
73 names = {'CONTEXTS': econtext.contexts} |
|
5676
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
74 variables = econtext.vars |
|
1257
93b80ad11ca8
merged Zope Collector #372 fix from ZPT CVS trunk
Richard Jones <richard@users.sourceforge.net>
parents:
1071
diff
changeset
|
75 getType = econtext.getCompiler().getTypes().get |
| 1049 | 76 for vname in self._f_varnames: |
|
5676
e70885fe72a4
issue2551026: template variable not defined even though it is.
John Rouillard <rouilj@ieee.org>
parents:
5389
diff
changeset
|
77 val = variables.get(vname, _marker) |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
78 if val is _marker: |
| 1049 | 79 has = val = getType(vname) |
| 80 if has: | |
| 81 val = ExprTypeProxy(vname, val, econtext) | |
|
2349
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
82 names[vname] = val |
|
b43efe461b3e
update PageTemplates to latest Zope codebase
Richard Jones <richard@users.sourceforge.net>
parents:
2005
diff
changeset
|
83 else: |
| 1049 | 84 names[vname] = val |
| 85 return names | |
| 86 | |
| 87 def __call__(self, econtext): | |
|
1065
0f9aa62917bd
much nicer error messages when there's a templating error
Richard Jones <richard@users.sourceforge.net>
parents:
1049
diff
changeset
|
88 __traceback_info__ = 'python expression "%s"'%self.expr |
| 1049 | 89 f = self._f |
|
5389
f8673e720f30
Python 3 preparation: update function attribute names.
Joseph Myers <jsm@polyomino.org.uk>
parents:
5388
diff
changeset
|
90 f.__globals__.update(self._bind_used_names(econtext)) |
| 1049 | 91 return f() |
| 92 | |
| 93 def __str__(self): | |
| 94 return 'Python expression "%s"' % self.expr | |
| 95 def __repr__(self): | |
| 96 return '<PythonExpr %s>' % self.expr | |
| 97 | |
| 98 class ExprTypeProxy: | |
| 99 '''Class that proxies access to an expression type handler''' | |
| 100 def __init__(self, name, handler, econtext): | |
| 101 self._name = name | |
| 102 self._handler = handler | |
| 103 self._econtext = econtext | |
| 104 def __call__(self, text): | |
| 105 return self._handler(self._name, text, | |
|
1257
93b80ad11ca8
merged Zope Collector #372 fix from ZPT CVS trunk
Richard Jones <richard@users.sourceforge.net>
parents:
1071
diff
changeset
|
106 self._econtext.getCompiler())(self._econtext) |
| 1049 | 107 |
