fix for #2235: ZCatalog triggering boolean evaluation of objects

parent 676715f2
...@@ -12,6 +12,11 @@ Zope Changes ...@@ -12,6 +12,11 @@ Zope Changes
- Collector #2213: Can't edit "old" ZopePageTemplate instances. - Collector #2213: Can't edit "old" ZopePageTemplate instances.
- Collector #2235: A number of ZCatalog methods were doing boolean
evaluation of objects that implemented __len__ instead of checking
them against None. Replaced a number of "if not obj" with
"if obj is None".
- Collector #2208: rewriting/setting the 'charset' part of the - Collector #2208: rewriting/setting the 'charset' part of the
content-type HTTP header will be done only for 'text/*' content-type HTTP header will be done only for 'text/*'
......
...@@ -221,7 +221,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -221,7 +221,7 @@ class ZCatalog(Folder, Persistent, Implicit):
for url in urls: for url in urls:
obj = self.resolve_path(url) obj = self.resolve_path(url)
if not obj and hasattr(self, 'REQUEST'): if obj is None and hasattr(self, 'REQUEST'):
obj = self.resolve_url(url, REQUEST) obj = self.resolve_url(url, REQUEST)
if obj is not None: if obj is not None:
self.catalog_object(obj, url) self.catalog_object(obj, url)
...@@ -289,7 +289,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -289,7 +289,7 @@ class ZCatalog(Folder, Persistent, Implicit):
p = paths[i] p = paths[i]
obj = self.resolve_path(p) obj = self.resolve_path(p)
if not obj: if obj is None:
obj = self.resolve_url(p, self.REQUEST) obj = self.resolve_url(p, self.REQUEST)
if obj is not None: if obj is not None:
try: try:
...@@ -587,8 +587,8 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -587,8 +587,8 @@ class ZCatalog(Folder, Persistent, Implicit):
def getobject(self, rid, REQUEST=None): def getobject(self, rid, REQUEST=None):
"""Return a cataloged object given a 'data_record_id_' """Return a cataloged object given a 'data_record_id_'
""" """
obj = self.aq_parent.unrestrictedTraverse(self.getpath(rid)) obj = self.aq_parent.unrestrictedTraverse(self.getpath(rid), None)
if not obj: if obj is None:
if REQUEST is None: if REQUEST is None:
REQUEST=self.REQUEST REQUEST=self.REQUEST
obj = self.resolve_url(self.getpath(rid), REQUEST) obj = self.resolve_url(self.getpath(rid), REQUEST)
......
...@@ -28,6 +28,7 @@ import OFS.Application ...@@ -28,6 +28,7 @@ import OFS.Application
from AccessControl.SecurityManagement import setSecurityManager from AccessControl.SecurityManagement import setSecurityManager
from AccessControl.SecurityManagement import noSecurityManager from AccessControl.SecurityManagement import noSecurityManager
from AccessControl import Unauthorized from AccessControl import Unauthorized
from Acquisition import Implicit
from Products.ZCatalog import Vocabulary from Products.ZCatalog import Vocabulary
from Products.ZCatalog.Catalog import Catalog from Products.ZCatalog.Catalog import Catalog
from Products.ZCatalog.Catalog import CatalogError from Products.ZCatalog.Catalog import CatalogError
...@@ -159,6 +160,31 @@ class zdummyFalse(zdummy): ...@@ -159,6 +160,31 @@ class zdummyFalse(zdummy):
def __nonzero__(self): def __nonzero__(self):
return False return False
# make objects with failing __len__ and __nonzero__
class dummyLenFail(zdummy):
def __init__(self, num, fail):
zdummy.__init__(self, num)
self.fail = fail
def __len__(self):
self.fail("__len__() was called")
class dummyNonzeroFail(zdummy):
def __init__(self, num, fail):
zdummy.__init__(self, num)
self.fail = fail
def __nonzero__(self):
self.fail("__nonzero__() was called")
class fakeparent(Implicit):
# fake parent mapping unrestrictedTraverse to
# catalog.resolve_path as simulated by TestZCatalog
def __init__(self, d):
self.d = d
def unrestrictedTraverse(self, path, default=None):
return self.d.get(path, default)
class TestZCatalog(unittest.TestCase): class TestZCatalog(unittest.TestCase):
...@@ -246,6 +272,29 @@ class TestZCatalog(unittest.TestCase): ...@@ -246,6 +272,29 @@ class TestZCatalog(unittest.TestCase):
result = self._catalog(title='9999') result = self._catalog(title='9999')
self.assertEquals(1, len(result)) self.assertEquals(1, len(result))
def testBooleanEvalOn_manage_catalogObject(self):
self.d['11'] = dummyLenFail(11, self.fail)
self.d['12'] = dummyNonzeroFail(12, self.fail)
# create a fake response that doesn't bomb on manage_catalogObject()
class myresponse:
def redirect(self, url):
pass
# this next call should not fail
self._catalog.manage_catalogObject(None, myresponse(), 'URL1', urls=('11', '12'))
def testBooleanEvalOn_refreshCatalog_getobject(self):
# wrap catalog under the fake parent
catalog = self._catalog.__of__(fakeparent(self.d))
# replace entries to test refreshCatalog
self.d['0'] = dummyLenFail(0, self.fail)
self.d['1'] = dummyNonzeroFail(1, self.fail)
# this next call should not fail
catalog.refreshCatalog()
for uid in ('0', '1'):
rid = self._catalog.getrid(uid)
# neither should these
catalog.getobject(rid)
class dummy(ExtensionClass.Base): class dummy(ExtensionClass.Base):
att1 = 'att1' att1 = 'att1'
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment