[Checkins] SVN: ZODB/branches/shane-cross-database-seatbelt/src/ZODB/ Corrected a case where the wrong _p_check_xref method would be called.

Shane Hathaway shane at hathawaymix.org
Tue Apr 28 04:27:50 EDT 2009


Log message for revision 99552:
  Corrected a case where the wrong _p_check_xref method would be called.
  

Changed:
  U   ZODB/branches/shane-cross-database-seatbelt/src/ZODB/cross-database-references.txt
  U   ZODB/branches/shane-cross-database-seatbelt/src/ZODB/serialize.py
  U   ZODB/branches/shane-cross-database-seatbelt/src/ZODB/tests/testcrossdatabasereferences.py

-=-
Modified: ZODB/branches/shane-cross-database-seatbelt/src/ZODB/cross-database-references.txt
===================================================================
--- ZODB/branches/shane-cross-database-seatbelt/src/ZODB/cross-database-references.txt	2009-04-28 07:37:42 UTC (rev 99551)
+++ ZODB/branches/shane-cross-database-seatbelt/src/ZODB/cross-database-references.txt	2009-04-28 08:27:49 UTC (rev 99552)
@@ -186,33 +186,39 @@
     >>> hasattr(main_obj, 'someattr')
     False
 
-A reference from `session_obj` to `main_obj` is allowed, however.
+A reference from `session_obj` to `main_obj` is allowed, however, because
+the seat belt is disabled in session_db.
 
     >>> session_obj.someattr = main_obj
     >>> tm.commit()
     >>> hasattr(session_obj, 'someattr')
     True
 
-The reference from `main_obj` can be allowed by its _p_check_xref method:
+Create an object that has a _p_check_xref method.  Allow the object to
+refer to session_obj.
 
-    >>> def _p_check_xref(obj):
-    ...     return obj is session_obj
-    >>> main_obj._p_check_xref = _p_check_xref
+    >>> main_obj = MyClass_w__p_check_xref()
+    >>> main_conn.root()['p'] = main_obj
+    >>> main_obj.allowed_xrefs = [session_obj]
     >>> main_obj.someattr = session_obj
     >>> tm.commit()
 
-The _p_check_xref method can also disallow a reference:
+The _p_check_xref method can disallow a reference.
 
-    >>> def _p_check_xref(obj):
-    ...     return False
-    >>> main_obj._p_check_xref = _p_check_xref
-    >>> main_obj.someattr = session_obj
+    >>> main_obj.allowed_xrefs = ()
     >>> tm.commit() # doctest: +NORMALIZE_WHITESPACE
     Traceback (most recent call last):
     ...
     InvalidObjectReference: A cross database reference was disallowed by a _p_check_xref method
     >>> tm.abort()
 
+Verify the right _p_check_xref method is called:
+
+    >>> main_obj.second = MyClass_w__p_check_xref()
+    >>> main_obj.second.allowed_xrefs = [session_obj]
+    >>> main_obj.second.someattr = session_obj
+    >>> tm.commit()
+
 NOTE
 ----
 

Modified: ZODB/branches/shane-cross-database-seatbelt/src/ZODB/serialize.py
===================================================================
--- ZODB/branches/shane-cross-database-seatbelt/src/ZODB/serialize.py	2009-04-28 07:37:42 UTC (rev 99551)
+++ ZODB/branches/shane-cross-database-seatbelt/src/ZODB/serialize.py	2009-04-28 08:27:49 UTC (rev 99552)
@@ -175,7 +175,6 @@
         self._p = cPickle.Pickler(self._file, 1)
         self._p.inst_persistent_id = self.persistent_id
         self._stack = []
-        self._obj = obj
         if obj is not None:
             self._stack.append(obj)
             jar = obj._p_jar
@@ -354,8 +353,10 @@
                     "Won't try to guess which one was correct!"
                     )
 
+        if database_name is not None:
             if self._jar.db().check_xrefs:
-                method = getattr(self._obj, '_p_check_xref', None)
+                # Apply cross-database reference policy
+                method = getattr(self._serializing, '_p_check_xref', None)
                 if method is None:
                     raise InvalidObjectReference(
                         "Attempt to store a cross database reference "
@@ -391,6 +392,9 @@
         return oid, klass
 
     def serialize(self, obj):
+        # Keep a record of which persistent object is being serialized
+        self._serializing = obj
+
         # We don't use __class__ here, because obj could be a persistent proxy.
         # We don't want to be fooled by proxies.
         klass = type(obj)

Modified: ZODB/branches/shane-cross-database-seatbelt/src/ZODB/tests/testcrossdatabasereferences.py
===================================================================
--- ZODB/branches/shane-cross-database-seatbelt/src/ZODB/tests/testcrossdatabasereferences.py	2009-04-28 07:37:42 UTC (rev 99551)
+++ ZODB/branches/shane-cross-database-seatbelt/src/ZODB/tests/testcrossdatabasereferences.py	2009-04-28 08:27:49 UTC (rev 99552)
@@ -26,6 +26,15 @@
     def __getnewargs__(self):
         return ()
 
+class MyClass_w__p_check_xref(persistent.Persistent):
+
+    def __init__(self):
+        allowed_xrefs = ()
+
+    def _p_check_xref(self, obj):
+        return obj in self.allowed_xrefs
+
+
 def test_must_use_consistent_connections():
     """
 
@@ -179,11 +188,13 @@
 def test_suite():
     return unittest.TestSuite((
         doctest.DocFileSuite('../cross-database-references.txt',
-                             globs=dict(MyClass=MyClass),
+                             globs=dict(MyClass=MyClass,
+                             MyClass_w__p_check_xref=MyClass_w__p_check_xref),
                              tearDown=tearDownDbs,
                              ),
         doctest.DocFileSuite('../cross-database-references.txt',
-                             globs=dict(MyClass=MyClass_w_getnewargs),
+                             globs=dict(MyClass=MyClass_w_getnewargs,
+                             MyClass_w__p_check_xref=MyClass_w__p_check_xref),
                              tearDown=tearDownDbs,
                              ),
         doctest.DocTestSuite(),



More information about the Checkins mailing list