[Zope3-checkins] SVN: Zope3/trunk/ Merge from 3.3 branch:
Philipp von Weitershausen
philikon at philikon.de
Thu May 25 15:28:48 EDT 2006
Log message for revision 68283:
Merge from 3.3 branch:
------------------------------------------------------------------------
r68278 | philikon | 2006-05-25 19:49:12 +0200 (Thu, 25 May 2006) | 2 lines
Do not blindly call exception classes or arbitrary objects inserted here.
------------------------------------------------------------------------
r68279 | philikon | 2006-05-25 19:50:09 +0200 (Thu, 25 May 2006) | 3 lines
Fix http://www.zope.org/Collectors/Zope3-dev/635:
TALES PathExpr doesn't calls old style classes
------------------------------------------------------------------------
r68280 | philikon | 2006-05-25 19:51:17 +0200 (Thu, 25 May 2006) | 2 lines
Note recent change
------------------------------------------------------------------------
r68281 | philikon | 2006-05-25 20:08:02 +0200 (Thu, 25 May 2006) | 5 lines
Fix http://www.zope.org/Collectors/Zope3-dev/638:
TALES PathExpr calls result of alternate subexpression
This corresponds to issue 538 in Zope 2 and r22855 in the Zope 2 trunk.
------------------------------------------------------------------------
r68282 | philikon | 2006-05-25 20:59:25 +0200 (Thu, 25 May 2006) | 3 lines
Fix http://www.zope.org/Collectors/Zope3-dev/636:
Default ITraverser can't traverse old style classes
Changed:
U Zope3/trunk/doc/CHANGES.txt
U Zope3/trunk/src/zope/app/debugskin/error_debug.pt
U Zope3/trunk/src/zope/tales/expressions.py
U Zope3/trunk/src/zope/tales/tests/test_expressions.py
U Zope3/trunk/src/zope/traversing/adapters.py
U Zope3/trunk/src/zope/traversing/tests/test_traverser.py
-=-
Modified: Zope3/trunk/doc/CHANGES.txt
===================================================================
--- Zope3/trunk/doc/CHANGES.txt 2006-05-25 18:59:25 UTC (rev 68282)
+++ Zope3/trunk/doc/CHANGES.txt 2006-05-25 19:28:47 UTC (rev 68283)
@@ -16,6 +16,14 @@
Bug fixes
+ - Fixed issue 636: Default ITraverser can't traverse old style
+ classes
+
+ - Fixed issue 638: TALES PathExpr calls result of alternate
+ subexpression
+
+ - Fixed issue 635: TALES PathExpr doesn't call old style classes
+
- Fixed issue 543: add 'decimal'-package to
zope/app/security/globalmodules.zcml
Modified: Zope3/trunk/src/zope/app/debugskin/error_debug.pt
===================================================================
--- Zope3/trunk/src/zope/app/debugskin/error_debug.pt 2006-05-25 18:59:25 UTC (rev 68282)
+++ Zope3/trunk/src/zope/app/debugskin/error_debug.pt 2006-05-25 19:28:47 UTC (rev 68283)
@@ -5,12 +5,12 @@
<h3 i18n:translate="">
Error type:
- <tal:span tal:replace="view/error_type" i18n:name="error_type"/>
+ <tal:span tal:replace="nocall:view/error_type" i18n:name="error_type"/>
</h3>
<h5 i18n:translate="">
Error object:
- <tal:span tal:replace="view/error_object" i18n:name="error_object"/>
+ <tal:span tal:replace="nocall:view/error_object" i18n:name="error_object"/>
</h5>
<pre class="traceback" style="font-size:small;">
@@ -21,4 +21,3 @@
</div>
</body>
</html>
-
Modified: Zope3/trunk/src/zope/tales/expressions.py
===================================================================
--- Zope3/trunk/src/zope/tales/expressions.py 2006-05-25 18:59:25 UTC (rev 68282)
+++ Zope3/trunk/src/zope/tales/expressions.py 2006-05-25 19:28:47 UTC (rev 68283)
@@ -15,7 +15,7 @@
$Id$
"""
-import re
+import re, types
from zope.interface import implements
from zope.tales.tales import _valid_name, _parse_expr, NAME_RE, Undefined
@@ -139,7 +139,6 @@
return ob
-
class PathExpr(object):
"""One or more subpath expressions, separated by '|'."""
implements(ITALESExpression)
@@ -156,6 +155,7 @@
def __init__(self, name, expr, engine, traverser=simpleTraverse):
self._s = expr
self._name = name
+ self._hybrid = False
paths = expr.split('|')
self._subexprs = []
add = self._subexprs.append
@@ -165,6 +165,7 @@
# This part is the start of another expression type,
# so glue it back together and compile it.
add(engine.compile('|'.join(paths[i:]).lstrip()))
+ self._hybrid = True
break
add(SubPathExpr(path, traverser, engine)._eval)
@@ -188,14 +189,25 @@
else:
break
else:
- # On the last subexpression allow exceptions through.
+ # On the last subexpression allow exceptions through, and
+ # don't autocall if the expression was not a subpath.
ob = self._subexprs[-1](econtext)
+ if self._hybrid:
+ return ob
if self._name == 'nocall':
return ob
- # Call the object if it is callable.
- if hasattr(ob, '__call__'):
+ # Call the object if it is callable. Note that checking for
+ # callable() isn't safe because the object might be security
+ # proxied (and security proxies report themselves callable, no
+ # matter what the underlying object is). We therefore check
+ # for the __call__ attribute, but not with hasattr as that
+ # eats babies, err, exceptions. In addition to that, we
+ # support calling old style classes which don't have a
+ # __call__.
+ if (getattr(ob, '__call__', _marker) is not _marker
+ or isinstance(ob, types.ClassType)):
return ob()
return ob
Modified: Zope3/trunk/src/zope/tales/tests/test_expressions.py
===================================================================
--- Zope3/trunk/src/zope/tales/tests/test_expressions.py 2006-05-25 18:59:25 UTC (rev 68282)
+++ Zope3/trunk/src/zope/tales/tests/test_expressions.py 2006-05-25 19:28:47 UTC (rev 68283)
@@ -114,6 +114,13 @@
'Dynamic name specified in first subpath element')
else:
self.fail('Engine accepted first subpath element as dynamic')
+
+ def testOldStyleClassIsCalled(self):
+ class AnOldStyleClass:
+ pass
+ self.context.vars['oldstyleclass'] = AnOldStyleClass
+ expr = self.engine.compile('oldstyleclass')
+ self.assert_(isinstance(expr(self.context), AnOldStyleClass))
def testString(self):
expr = self.engine.compile('string:Fred')
@@ -135,6 +142,11 @@
context=self.context
self.assertEqual(expr(context), 4)
+ def testPythonCallableIsntCalled(self):
+ self.context.vars['acallable'] = lambda: 23
+ expr = self.engine.compile('python: acallable')
+ self.assertEqual(expr(self.context), self.context.vars['acallable'])
+
def testPythonNewline(self):
expr = self.engine.compile('python: 2 \n+\n 2\n')
context=self.context
@@ -149,6 +161,20 @@
self.assertRaises(self.engine.getCompilerError(),
self.engine.compile, 'python: splat.0')
+ def testHybridPathExpressions(self):
+ def eval(expr):
+ e = self.engine.compile(expr)
+ return e(self.context)
+ self.context.vars['one'] = 1
+ self.context.vars['acallable'] = lambda: 23
+
+ self.assertEqual(eval('foo | python:1+1'), 2)
+ self.assertEqual(eval('foo | python:acallable'),
+ self.context.vars['acallable'])
+ self.assertEqual(eval('foo | string:x'), 'x')
+ self.assertEqual(eval('foo | string:$one'), '1')
+ self.assert_(eval('foo | exists:x'))
+
def testEmptyPathSegmentRaisesCompilerError(self):
CompilerError = self.engine.getCompilerError()
def check(expr):
Modified: Zope3/trunk/src/zope/traversing/adapters.py
===================================================================
--- Zope3/trunk/src/zope/traversing/adapters.py 2006-05-25 18:59:25 UTC (rev 68282)
+++ Zope3/trunk/src/zope/traversing/adapters.py 2006-05-25 19:28:47 UTC (rev 68283)
@@ -158,7 +158,8 @@
nm = name
if traversable is None:
- if obj.__class__ == dict:
+ # not all objects have __class__, for example old style classes
+ if getattr(obj, '__class__', None) == dict:
# Special-case dicts
return obj[name]
Modified: Zope3/trunk/src/zope/traversing/tests/test_traverser.py
===================================================================
--- Zope3/trunk/src/zope/traversing/tests/test_traverser.py 2006-05-25 18:59:25 UTC (rev 68282)
+++ Zope3/trunk/src/zope/traversing/tests/test_traverser.py 2006-05-25 19:28:47 UTC (rev 68283)
@@ -137,6 +137,15 @@
def testNotFoundNoDefault(self):
self.assertRaises(TraversalError, self.tr.traverse, 'foo')
+ def testTraverseOldStyleClass(self):
+ class AnOldStyleClass:
+ x = object()
+ container = {}
+ container['theclass'] = AnOldStyleClass
+
+ tr = Traverser(container)
+ self.assert_(tr.traverse('theclass/x') is AnOldStyleClass.x)
+
class RestrictedTraverseTests(PlacefulSetup, unittest.TestCase):
_oldPolicy = None
_deniedNames = ()
More information about the Zope3-Checkins
mailing list