[Zope3-checkins] CVS: Zope3/src/zope/app/broken - tests.py:1.1
broken.py:1.3 configure.zcml:1.3
Jim Fulton
jim at zope.com
Thu Mar 4 17:41:47 EST 2004
Update of /cvs-repository/Zope3/src/zope/app/broken
In directory cvs.zope.org:/tmp/cvs-serv3904/src/zope/app/broken
Modified Files:
broken.py configure.zcml
Added Files:
tests.py
Log Message:
Adden annotation support for broken objects. Also added some
logic to set a checker on broken classes. This is necessary
because broken classes are generated when needed.
=== Added File Zope3/src/zope/app/broken/tests.py ===
##############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Broken-object tests
$Id: tests.py,v 1.1 2004/03/04 22:41:47 jim Exp $
"""
import unittest
from zope.testing.doctestunit import DocTestSuite
def test_annotations():
"""Broken objects may have attribute annotations
If they do, we can access them::
>>> from zope.app.broken.broken import Broken
>>> b = Broken()
>>> b.__setstate__({'__annotations__': {'foo.bar': 42}})
>>> b['foo.bar']
42
>>> b.get('foo.bar')
42
Missing keys are handled as expected:
>>> b['foo.baz']
Traceback (most recent call last):
...
KeyError: 'foo.baz'
>>> b.get('foo.baz')
It is an error to modify annotations:
>>> b['foo.baz'] = []
Traceback (most recent call last):
...
BrokenModified: Can't modify broken objects
>>> del b['foo.bar']
Traceback (most recent call last):
...
BrokenModified: Can't modify broken objects
If there are no annotation data, then, obviously, there are no annotations:
>>> b = Broken()
>>> b['foo.bar']
Traceback (most recent call last):
...
KeyError: 'foo.bar'
>>> b.get('foo.bar')
>>> b['foo.bar'] = []
Traceback (most recent call last):
...
BrokenModified: Can't modify broken objects
>>> del b['foo.bar']
Traceback (most recent call last):
...
BrokenModified: Can't modify broken objects
Cleanup:
>>> import ZODB.broken
>>> ZODB.broken.broken_cache.clear()
"""
def test_suite():
return unittest.TestSuite((
DocTestSuite(),
DocTestSuite('zope.app.broken.broken'),
))
if __name__ == '__main__': unittest.main()
=== Zope3/src/zope/app/broken/broken.py 1.2 => 1.3 ===
--- Zope3/src/zope/app/broken/broken.py:1.2 Tue Mar 2 12:51:49 2004
+++ Zope3/src/zope/app/broken/broken.py Thu Mar 4 17:41:47 2004
@@ -21,13 +21,21 @@
import zope.interface
import zope.app.location.interfaces
import zope.app.event.function
+import zope.security.checker
+
+
+from zope.app.interfaces.annotation import IAnnotations
class IBroken(zope.interface.Interface):
"""Marker interface for broken objects
"""
class Broken(ZODB.broken.Broken):
- zope.interface.implements(IBroken, zope.app.location.interfaces.ILocation)
+ zope.interface.implements(
+ IBroken,
+ zope.app.location.interfaces.ILocation,
+ IAnnotations,
+ )
def __parent__(self):
return self.__Broken_state__.get('__parent__')
@@ -39,14 +47,86 @@
__name__ = property(__name__)
+ def __getAnnotations(self):
+ get = getattr(self.__Broken_state__, 'get', None)
+ if get is not None:
+ return get('__annotations__')
+
+ def __getitem__(self, key):
+ annotations = self.__getAnnotations()
+ if annotations:
+ return annotations[key]
+ raise KeyError, key
+
+ def __setitem__(self, key, value):
+ raise ZODB.broken.BrokenModified("Can't modify broken objects")
+
+ def __delitem__(self, key):
+ raise ZODB.broken.BrokenModified("Can't modify broken objects")
+
+ def get(self, key, default=None):
+ annotations = self.__getAnnotations()
+ if annotations is None:
+ return default
+ return annotations.get(key, default)
+
def installBroken(event):
+ """Install a class factory that handled broken objects
+
+ This method installs a custom class factory when it gets a
+ database-opened event::
+
+ >>> import ZODB.tests.util
+ >>> from zope.app.process.event import DatabaseOpened
+ >>> db = ZODB.tests.util.DB()
+ >>> installBroken(DatabaseOpened(db))
+
+ If someone tries to load an object for which there is no class,
+ then they will get a Broken object. We can simulate that by
+ calling the database's class factory directly with a connection
+ (None will do for our purposes, since the class factory function
+ we register ignores the connection argument), a non-existent
+ module and class name::
+
+ >>> cls = db.classFactory(None, 'ZODB.not.there', 'atall')
+
+ The class that comes back is a subclass of Broken::
+
+ >>> issubclass(cls, Broken)
+ True
+
+ It implements ILocation and IAnnotations::
+
+ >>> zope.app.location.interfaces.ILocation.isImplementedByInstancesOf(
+ ... cls)
+ True
+ >>> IAnnotations.isImplementedByInstancesOf(cls)
+ True
+
+ and it has a security checker that is the same as the checker that
+ Broken has::
+
+ >>> (cls.__Security_checker__ is
+ ... zope.security.checker.getCheckerForInstancesOf(Broken))
+ True
+
+ Cleanup:
+
+ >>> ZODB.broken.broken_cache.clear()
+ """
Broken_ = Broken # make it local for speed
find_global = ZODB.broken.find_global
+
+ def type_(name, bases, dict):
+ cls = type(name, bases, dict)
+ checker = zope.security.checker.getCheckerForInstancesOf(Broken_)
+ cls.__Security_checker__ = checker
+ return cls
def classFactory(connection, modulename, globalname):
- return find_global(modulename, globalname, Broken_)
+ return find_global(modulename, globalname, Broken_, type_)
- event.database.setClassFactory(classFactory)
+ event.database.classFactory = classFactory
-installBroken = zope.app.event.function.Subscriber(installBroken)
+installBrokenSubscriber = zope.app.event.function.Subscriber(installBroken)
=== Zope3/src/zope/app/broken/configure.zcml 1.2 => 1.3 ===
--- Zope3/src/zope/app/broken/configure.zcml:1.2 Tue Mar 2 13:50:55 2004
+++ Zope3/src/zope/app/broken/configure.zcml Thu Mar 4 17:41:47 2004
@@ -3,8 +3,12 @@
xmlns:event="http://namespaces.zope.org/event"
>
+ <content class=".broken.Broken">
+ <allow interface="zope.app.interfaces.annotation.IAnnotations" />
+ </content>
+
<event:subscribe
- subscriber=".broken.installBroken"
+ subscriber=".broken.installBrokenSubscriber"
event_types="zope.app.event.interfaces.IDatabaseOpenedEvent"
/>
More information about the Zope3-Checkins
mailing list