[Checkins] SVN: keas.pbpersist/trunk/src/keas/pbpersist/ Tested and fixed handling of some less common types of persistent refs.

Shane Hathaway shane at hathawaymix.org
Thu Jan 22 04:58:38 EST 2009


Log message for revision 94927:
  Tested and fixed handling of some less common types of persistent refs.
  

Changed:
  U   keas.pbpersist/trunk/src/keas/pbpersist/README.txt
  U   keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py
  U   keas.pbpersist/trunk/src/keas/pbpersist/tests.py

-=-
Modified: keas.pbpersist/trunk/src/keas/pbpersist/README.txt
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/README.txt	2009-01-22 09:31:28 UTC (rev 94926)
+++ keas.pbpersist/trunk/src/keas/pbpersist/README.txt	2009-01-22 09:58:38 UTC (rev 94927)
@@ -213,31 +213,87 @@
     >>> storage_beta = DemoStorage()
     >>> db_beta = DB(storage_beta, database_name='beta', databases=db.databases)
     >>> root_beta = conn1.get_connection('beta').root()
+    >>> root_beta['obj'] = PersistentMapping()
+    >>> transaction.commit()
     >>> ref = bob.guardians.add()
-    >>> bob.protobuf_refs.set(ref, root_beta)
+    >>> bob.protobuf_refs.set(ref, root_beta['obj'])
     >>> transaction.commit()
 
-Access all of those references in another connection.
+We can make a reference to an instance of a class with a __getnewargs__
+method.  ZODB does not store the class metadata in references to instances
+of such classes.
 
+    >>> from keas.pbpersist.tests import Adder
+    >>> adder = Adder(7)
+    >>> conn1.root()['adder'] = adder
+    >>> ref = bob.guardians.add()
+    >>> bob.protobuf_refs.set(ref, adder)
+    >>> transaction.commit()
+
+We can make a reference to an instance of a class with a __getnewargs__
+method, even when that instance is in another database.
+
+    >>> adder = Adder(6)
+    >>> root_beta['adder'] = adder
+    >>> transaction.commit()
+    >>> ref = bob.guardians.add()
+    >>> bob.protobuf_refs.set(ref, adder)
+    >>> transaction.commit()
+
+Access all of those different kinds of references in another connection.
+
     >>> conn2 = db.open()
     >>> bob2 = conn2.root()['bob']
+    >>> len(bob2.guardians)
+    6
+
     >>> bob2.protobuf_refs.get(bob2.guardians[0])
     <keas.pbpersist.tests.PContact object at ...>
+
     >>> bob2.protobuf_refs.get(bob2.guardians[1])
     {}
     >>> bob2.protobuf_refs.get(bob2.guardians[1])._p_jar is conn2
     True
+
     >>> bob2.protobuf_refs.get(bob2.guardians[2])
     <persistent.wref.WeakRef object at ...>
     >>> bob2.protobuf_refs.get(bob2.guardians[2])()
     {}
+
     >>> bob2.protobuf_refs.get(bob2.guardians[3])
     {}
     >>> bob2.protobuf_refs.get(bob2.guardians[3])._p_jar is conn2
     False
+
+    >>> bob2.protobuf_refs.get(bob2.guardians[4])
+    <keas.pbpersist.tests.Adder object at ...>
+    >>> bob2.protobuf_refs.get(bob2.guardians[4]).add(3)
+    10
+
+    >>> bob2.protobuf_refs.get(bob2.guardians[5])
+    <keas.pbpersist.tests.Adder object at ...>
+    >>> bob2.protobuf_refs.get(bob2.guardians[5]).add(3)
+    9
+
     >>> conn2.close()
 
 
+Edge Cases
+----------
+
+We can't currently store instances of a ProtobufState Persistent class that
+implements __getnewargs__().
+
+    >>> from keas.pbpersist.tests import PContactWithGetNewArgs
+    >>> fail_contact = PContactWithGetNewArgs()
+    >>> fail_contact.name = u'Loser'
+    >>> conn1.root()['fail_contact'] = fail_contact
+    >>> transaction.commit()
+    Traceback (most recent call last):
+    ...
+    POSError: ProtobufSerializer can not serialize classes using __getnewargs__ or __getinitargs__
+
+
 Clean Up
 --------
 

Modified: keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py	2009-01-22 09:31:28 UTC (rev 94926)
+++ keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py	2009-01-22 09:58:38 UTC (rev 94927)
@@ -33,13 +33,13 @@
     if ref.weak:
         return ['w', (oid,)]
     elif ref.database:
-        if ref.class_meta:
+        if ref.HasField('class_meta'):
             klass = find_global(
                 ref.class_meta.module_name, ref.class_meta.class_name)
             return ['m', (ref.database, oid, klass)]
         else:
             return ['n', (ref.database, oid)]
-    elif ref.class_meta:
+    elif ref.HasField('class_meta'):
         klass = find_global(
             ref.class_meta.module_name, ref.class_meta.class_name)
         return (oid, klass)

Modified: keas.pbpersist/trunk/src/keas/pbpersist/tests.py
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/tests.py	2009-01-22 09:31:28 UTC (rev 94926)
+++ keas.pbpersist/trunk/src/keas/pbpersist/tests.py	2009-01-22 09:58:38 UTC (rev 94927)
@@ -22,6 +22,7 @@
 
 
 class PContact(Persistent):
+    """A simple ProtobufState class for testing"""
     __metaclass__ = ProtobufState
     protobuf_type = ContactPB
 
@@ -29,6 +30,31 @@
         self.create_time = 1
 
 
+class Adder(Persistent):
+    """A Persistent class with a __getnewargs__ method for testing"""
+
+    def __new__(cls, constant):
+        res = super(cls, Adder).__new__(cls)
+        res.constant = constant
+        return res
+
+    def add(self, n):
+        return self.constant + n
+
+    def __getnewargs__(self):
+        return (self.constant,)
+
+
+class PContactWithGetNewArgs(PContact):
+    """A ProtobufState persistent class with a __getnewargs__ method.
+
+    This is here to demonstrate that such a class won't currently work,
+    because storing the result of __getnewargs__() would require pickling.
+    """
+    def __getnewargs__(self):
+        return ()
+
+
 def test_suite():
     return unittest.TestSuite([
         doctest.DocFileSuite(



More information about the Checkins mailing list