Commit 3d72a8f4 authored by Hanno Schlichting's avatar Hanno Schlichting

Brain PEP8 cleanup and define __contains__ for brains.

parent a1d83432
...@@ -13,7 +13,8 @@ ...@@ -13,7 +13,8 @@
from zope.interface import implements from zope.interface import implements
import Acquisition, Record import Acquisition
import Record
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
from interfaces import ICatalogBrain from interfaces import ICatalogBrain
...@@ -22,15 +23,19 @@ from interfaces import ICatalogBrain ...@@ -22,15 +23,19 @@ from interfaces import ICatalogBrain
# Use 'catalog-getObject-raises off' in zope.conf to restore old behavior. # Use 'catalog-getObject-raises off' in zope.conf to restore old behavior.
GETOBJECT_RAISES = True GETOBJECT_RAISES = True
class AbstractCatalogBrain(Record.Record, Acquisition.Implicit): class AbstractCatalogBrain(Record.Record, Acquisition.Implicit):
"""Abstract base brain that handles looking up attributes as """Abstract base brain that handles looking up attributes as
required, and provides just enough smarts to let us get the URL, path, required, and provides just enough smarts to let us get the URL, path,
and cataloged object without having to ask the catalog directly. and cataloged object without having to ask the catalog directly.
""" """
implements(ICatalogBrain) implements(ICatalogBrain)
def has_key(self, key): def has_key(self, key):
return self.__record_schema__.has_key(key) return key in self.__record_schema__
def __contains__(self, name):
return name in self.__record_schema__
def getPath(self): def getPath(self):
"""Get the physical path for this record""" """Get the physical path for this record"""
...@@ -39,11 +44,11 @@ class AbstractCatalogBrain(Record.Record, Acquisition.Implicit): ...@@ -39,11 +44,11 @@ class AbstractCatalogBrain(Record.Record, Acquisition.Implicit):
def getURL(self, relative=0): def getURL(self, relative=0):
"""Generate a URL for this record""" """Generate a URL for this record"""
# XXX The previous implementation attempted to eat errors coming from # XXX The previous implementation attempted to eat errors coming from
# REQUEST.physicalPathToURL. Unfortunately it also ate # REQUEST.physicalPathToURL. Unfortunately it also ate
# ConflictErrors (from getPath), which is bad. Staring at the # ConflictErrors (from getPath), which is bad. Staring at the
# relevent code in HTTPRequest.py it's unclear to me what could be # relevent code in HTTPRequest.py it's unclear to me what could be
# raised by it so I'm removing the exception handling here all # raised by it so I'm removing the exception handling here all
# together. If undesired exceptions get raised somehow we should # together. If undesired exceptions get raised somehow we should
# avoid bare except band-aids and find a real solution. # avoid bare except band-aids and find a real solution.
return self.REQUEST.physicalPathToURL(self.getPath(), relative) return self.REQUEST.physicalPathToURL(self.getPath(), relative)
...@@ -101,6 +106,7 @@ class AbstractCatalogBrain(Record.Record, Acquisition.Implicit): ...@@ -101,6 +106,7 @@ class AbstractCatalogBrain(Record.Record, Acquisition.Implicit):
"""Return the record ID for this object.""" """Return the record ID for this object."""
return self.data_record_id_ return self.data_record_id_
class NoBrainer: class NoBrainer:
""" This is an empty class to use when no brain is specified. """ """ This is an empty class to use when no brain is specified. """
pass pass
...@@ -244,19 +244,23 @@ class IZCatalog(Interface): ...@@ -244,19 +244,23 @@ class IZCatalog(Interface):
pghandler -- optional Progresshandler as defined in ProgressHandler.py pghandler -- optional Progresshandler as defined in ProgressHandler.py
(see also README.txt) (see also README.txt)
""" """
# XXX This should inherit from an IRecord interface, if there ever is one. # This should inherit from an IRecord interface, if there ever is one.
class ICatalogBrain(Interface): class ICatalogBrain(Interface):
"""Catalog brain that handles looking up attributes as """Catalog brain that handles looking up attributes as
required, and provides just enough smarts to let us get the URL, path, required, and provides just enough smarts to let us get the URL, path,
and cataloged object without having to ask the catalog directly. and cataloged object without having to ask the catalog directly.
""" """
def has_key(key): def has_key(key):
"""Record has this field""" """Record has this field"""
def __contains__(self, name):
"""Record has this field"""
def getPath(): def getPath():
"""Get the physical path for this record""" """Get the physical path for this record"""
def getURL(relative=0): def getURL(relative=0):
"""Generate a URL for this record""" """Generate a URL for this record"""
...@@ -272,7 +276,6 @@ class ICatalogBrain(Interface): ...@@ -272,7 +276,6 @@ class ICatalogBrain(Interface):
Will return None if the object cannot be found via its cataloged path Will return None if the object cannot be found via its cataloged path
(i.e., it was deleted or moved without recataloging), or if the user is (i.e., it was deleted or moved without recataloging), or if the user is
not authorized to access the object. not authorized to access the object.
""" """
def getRID(): def getRID():
......
...@@ -14,27 +14,38 @@ ...@@ -14,27 +14,38 @@
""" """
import unittest import unittest
import Acquisition import Acquisition
from zExceptions import Unauthorized from zExceptions import Unauthorized
from ZODB.POSException import ConflictError from ZODB.POSException import ConflictError
_marker = object()
class Happy(Acquisition.Implicit): class Happy(Acquisition.Implicit):
"""Happy content""" """Happy content"""
def __init__(self, id): def __init__(self, id):
self.id = id self.id = id
def check(self): def check(self):
pass pass
class Secret(Happy): class Secret(Happy):
"""Object that raises Unauthorized when accessed""" """Object that raises Unauthorized when accessed"""
def check(self): def check(self):
raise Unauthorized raise Unauthorized
class Conflicter(Happy): class Conflicter(Happy):
"""Object that raises ConflictError when accessed""" """Object that raises ConflictError when accessed"""
def check(self): def check(self):
raise ConflictError raise ConflictError
class DummyRequest(Acquisition.Implicit): class DummyRequest(Acquisition.Implicit):
def physicalPathToURL(self, path, relative=False): def physicalPathToURL(self, path, relative=False):
...@@ -42,13 +53,12 @@ class DummyRequest(Acquisition.Implicit): ...@@ -42,13 +53,12 @@ class DummyRequest(Acquisition.Implicit):
path = 'http://superbad.com' + path path = 'http://superbad.com' + path
return path return path
_marker = object()
class DummyCatalog(Acquisition.Implicit): class DummyCatalog(Acquisition.Implicit):
_objs = {'/happy':Happy('happy'), _objs = {'/happy': Happy('happy'),
'/secret':Secret('secret'), '/secret': Secret('secret'),
'/conflicter':Conflicter('conflicter')} '/conflicter': Conflicter('conflicter')}
_paths = _objs.keys() + ['/zonked'] _paths = _objs.keys() + ['/zonked']
_paths.sort() _paths.sort()
...@@ -78,14 +88,17 @@ class DummyCatalog(Acquisition.Implicit): ...@@ -78,14 +88,17 @@ class DummyCatalog(Acquisition.Implicit):
return self.restrictedTraverse(self._paths[rid]) return self.restrictedTraverse(self._paths[rid])
def resolve_url(self, path, REQUEST): def resolve_url(self, path, REQUEST):
path = path[path.find('/', path.find('//')+1):] # strip server part # strip server part
path = path[path.find('/', path.find('//') + 1):]
return self.restrictedTraverse(path) return self.restrictedTraverse(path)
class ConflictingCatalog(DummyCatalog): class ConflictingCatalog(DummyCatalog):
def getpath(self, rid): def getpath(self, rid):
raise ConflictError raise ConflictError
class BrainsTestBase: class BrainsTestBase:
_old_flag = None _old_flag = None
...@@ -110,15 +123,17 @@ class BrainsTestBase: ...@@ -110,15 +123,17 @@ class BrainsTestBase:
def _makeBrain(self, rid): def _makeBrain(self, rid):
from Products.ZCatalog.CatalogBrains import AbstractCatalogBrain from Products.ZCatalog.CatalogBrains import AbstractCatalogBrain
class Brain(AbstractCatalogBrain): class Brain(AbstractCatalogBrain):
__record_schema__ = {'test_field': 0, 'data_record_id_':1} __record_schema__ = {'test_field': 0, 'data_record_id_': 1}
return Brain(('test', rid)).__of__(self.cat) return Brain(('test', rid)).__of__(self.cat)
def testHasKey(self): def testHasKey(self):
b = self._makeBrain(1) b = self._makeBrain(1)
self.failUnless(b.has_key('test_field')) self.failUnless('test_field' in b)
self.failUnless(b.has_key('data_record_id_')) self.failUnless('data_record_id_' in b)
self.failIf(b.has_key('godel')) self.failIf('godel' in b)
def testGetPath(self): def testGetPath(self):
b = [self._makeBrain(rid) for rid in range(3)] b = [self._makeBrain(rid) for rid in range(3)]
...@@ -149,6 +164,7 @@ class BrainsTestBase: ...@@ -149,6 +164,7 @@ class BrainsTestBase:
self.assertEqual(b.getPath(), '/conflicter') self.assertEqual(b.getPath(), '/conflicter')
self.assertRaises(ConflictError, b.getObject) self.assertRaises(ConflictError, b.getObject)
class TestBrains(BrainsTestBase, unittest.TestCase): class TestBrains(BrainsTestBase, unittest.TestCase):
def _flag_value(self): def _flag_value(self):
...@@ -167,6 +183,7 @@ class TestBrains(BrainsTestBase, unittest.TestCase): ...@@ -167,6 +183,7 @@ class TestBrains(BrainsTestBase, unittest.TestCase):
self.assertRaises(KeyError, self.cat.getobject, 3) self.assertRaises(KeyError, self.cat.getobject, 3)
self.assertRaises((NotFound, AttributeError, KeyError), b.getObject) self.assertRaises((NotFound, AttributeError, KeyError), b.getObject)
class TestBrainsOldBehavior(BrainsTestBase, unittest.TestCase): class TestBrainsOldBehavior(BrainsTestBase, unittest.TestCase):
def _flag_value(self): def _flag_value(self):
...@@ -183,6 +200,7 @@ class TestBrainsOldBehavior(BrainsTestBase, unittest.TestCase): ...@@ -183,6 +200,7 @@ class TestBrainsOldBehavior(BrainsTestBase, unittest.TestCase):
self.assertRaises(KeyError, self.cat.getobject, 3) self.assertRaises(KeyError, self.cat.getobject, 3)
self.assertEqual(b.getObject(), None) self.assertEqual(b.getObject(), None)
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestBrains)) suite.addTest(unittest.makeSuite(TestBrains))
......
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