Log message for revision 113943:
  LP #143531: Fix broken object so they give access to their state.
  
  merge branch gotcha-LP143531
  

Changed:
  U   Zope/branches/2.12/doc/CHANGES.rst
  U   Zope/branches/2.12/src/OFS/Uninstalled.py
  U   Zope/branches/2.12/src/OFS/tests/test_Uninstalled.py

-=-
Modified: Zope/branches/2.12/doc/CHANGES.rst
===================================================================
--- Zope/branches/2.12/doc/CHANGES.rst  2010-06-27 16:12:02 UTC (rev 113942)
+++ Zope/branches/2.12/doc/CHANGES.rst  2010-06-27 16:17:03 UTC (rev 113943)
@@ -11,6 +11,8 @@
 Bugs Fixed
 ++++++++++
 
+- LP #143531: Fix broken object so they give access to their state.
+
 - LP #578326: Issue a warning if someone specifies a non-public permission
   attribute in the browser:view directive. This attribute has never been
   supported in Zope 2.

Modified: Zope/branches/2.12/src/OFS/Uninstalled.py
===================================================================
--- Zope/branches/2.12/src/OFS/Uninstalled.py   2010-06-27 16:12:02 UTC (rev 
113942)
+++ Zope/branches/2.12/src/OFS/Uninstalled.py   2010-06-27 16:17:03 UTC (rev 
113943)
@@ -22,12 +22,14 @@
 from App.special_dtml import DTMLFile
 from OFS.SimpleItem import Item
 from Persistence import Overridable
+from ZODB.broken import Broken as ZODB_Broken
+from ZODB.broken import persistentBroken
 
 broken_klasses={}
 broken_klasses_lock = allocate_lock()
 LOG = getLogger('OFS.Uninstalled')
 
-class BrokenClass(Explicit, Item, Overridable):
+class BrokenClass(ZODB_Broken, Explicit, Item, Overridable):
     _p_changed=0
     meta_type='Broken Because Product is Gone'
     icon='p_/broken'
@@ -37,12 +39,6 @@
     manage_page_header = Acquired
     manage_page_footer = Acquired
 
-    def __getstate__(self):
-        raise SystemError, (
-            """This object was originally created by a product that
-            is no longer installed.  It cannot be updated.
-            (%s)""" % repr(self))
-
     def __getattr__(self, name):
         if name[:3]=='_p_':
             return BrokenClass.inheritedAttribute('__getattr__')(self, name)
@@ -74,6 +70,7 @@
             klass.info=(
                 'This object\'s class was %s in module %s.' %
                 (klass.__name__, klass.__module__))
+            klass = persistentBroken(klass)
             LOG.warning('Could not import class %s '
                     'from module %s' % (`klass.__name__`, `klass.__module__`))
     finally:

Modified: Zope/branches/2.12/src/OFS/tests/test_Uninstalled.py
===================================================================
--- Zope/branches/2.12/src/OFS/tests/test_Uninstalled.py        2010-06-27 
16:12:02 UTC (rev 113942)
+++ Zope/branches/2.12/src/OFS/tests/test_Uninstalled.py        2010-06-27 
16:17:03 UTC (rev 113943)
@@ -13,7 +13,14 @@
 ##############################################################################
 
 import unittest
+from OFS.SimpleItem import SimpleItem
+from Testing.ZopeTestCase import base
 
+
+class ToBreak(SimpleItem):
+    pass
+
+
 class TestsOfBroken(unittest.TestCase):
     """Tests for the factory for "broken" classes.
     """
@@ -77,24 +84,8 @@
         self.assertEqual(klass.__module__, 'Products.MyProduct.MyClass')
         self.assertEqual(klass.product_name, 'MyProduct')
 
-    def test_Broken_instance___getstate___raises_useful_exception(self):
-        # see http://www.zope.org/Collectors/Zope/2157
-        from OFS.Uninstalled import Broken
-        from OFS.Uninstalled import BrokenClass
-        OID = '\x01' * 8
-
-        inst = Broken(self, OID, ('Products.MyProduct.MyClass', 'MyClass'))
-
-        try:
-            dict = inst.__getstate__()
-        except SystemError, e:
-            self.failUnless('MyClass' in str(e), str(e))
-        else:
-            self.fail("'__getstate__' didn't raise SystemError!")
-
     def test_Broken_instance___getattr___allows_persistence_attrs(self):
         from OFS.Uninstalled import Broken
-        from OFS.Uninstalled import BrokenClass
         OID = '\x01' * 8
         PERSISTENCE_ATTRS = ["_p_changed",
                              "_p_jar",
@@ -119,14 +110,47 @@
         for meth_name in PERSISTENCE_METHODS:
             meth = getattr(inst, meth_name) # doesn't raise
 
+
+class TestsIntegratedBroken(base.TestCase):
+
+    def test_Broken_instance___getstate___gives_access_to_its_state(self):
+        from Acquisition import aq_base
+        from OFS.Uninstalled import BrokenClass
+        from OFS.tests import test_Uninstalled
+        import transaction
+
+        # store an instance
+        tr = ToBreak()
+        tr.id = 'tr'
+        self.app._setObject('tr', tr)
+        # commit to allow access in another connection
+        transaction.commit()
+        # remove class from namespace to ensure broken object
+        del test_Uninstalled.ToBreak
+        # get new connection that will give access to broken object
+        app = base.app()
+        inst = aq_base(app.tr)
+        self.failUnless(isinstance(inst, BrokenClass))
+        state = inst.__getstate__()
+        self.assertEqual(state, {'id': 'tr'})
+
+        # cleanup
+        app.manage_delObjects('tr')
+        transaction.commit()
+        # check that object is not left over
+        app = base.app()
+        self.failIf('tr' in app.objectIds())
+
+
 def test_suite():
     suite = unittest.TestSuite()
-    suite.addTest( unittest.makeSuite(TestsOfBroken))
+    suite.addTest(unittest.makeSuite(TestsOfBroken))
+    suite.addTest(unittest.makeSuite(TestsIntegratedBroken))
     return suite
 
+
 def main():
     unittest.main(defaultTest='test_suite')
 
 if __name__ == '__main__':
     main()
-

_______________________________________________
Zope-Checkins maillist  -  Zope-Checkins@zope.org
https://mail.zope.org/mailman/listinfo/zope-checkins

Reply via email to