[Checkins] SVN: keas.pbpersist/ Added keas.pbpersist, a layer over keas.pbstate that serializes in ZODB

Shane Hathaway shane at hathawaymix.org
Wed Jan 21 19:48:09 EST 2009


Log message for revision 94914:
  Added keas.pbpersist, a layer over keas.pbstate that serializes in ZODB 
  without any pickling.
  

Changed:
  A   keas.pbpersist/
  A   keas.pbpersist/trunk/
  A   keas.pbpersist/trunk/.installed.cfg
  A   keas.pbpersist/trunk/bootstrap.py
  A   keas.pbpersist/trunk/buildout.cfg
  A   keas.pbpersist/trunk/setup.py
  A   keas.pbpersist/trunk/src/
  A   keas.pbpersist/trunk/src/keas/
  A   keas.pbpersist/trunk/src/keas/__init__.py
  A   keas.pbpersist/trunk/src/keas/pbpersist/
  A   keas.pbpersist/trunk/src/keas/pbpersist/README.txt
  A   keas.pbpersist/trunk/src/keas/pbpersist/__init__.py
  A   keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py
  A   keas.pbpersist/trunk/src/keas/pbpersist/persistent.proto
  A   keas.pbpersist/trunk/src/keas/pbpersist/persistent_pb2.py
  A   keas.pbpersist/trunk/src/keas/pbpersist/tests.py

-=-
Added: keas.pbpersist/trunk/.installed.cfg
===================================================================
--- keas.pbpersist/trunk/.installed.cfg	                        (rev 0)
+++ keas.pbpersist/trunk/.installed.cfg	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,69 @@
+[buildout]
+installed_develop_eggs = /home/shane/svn/keas.pbpersist/trunk/develop-eggs/keas.pbstate.egg-link
+parts = test python coverage-test coverage-report
+
+[test]
+__buildout_installed__ = /home/shane/svn/keas.pbpersist/trunk/parts/test
+	/home/shane/svn/keas.pbpersist/trunk/bin/test
+__buildout_signature__ = zc.recipe.testrunner-1.1.0-py2.5.egg zc.recipe.egg-1.1.0-py2.5.egg setuptools-0.6c9-py2.5.egg zope.testing-3.7.1-py2.5.egg zc.buildout-1.1.1-py2.5.egg zc.buildout-1.1.1-py2.5.egg zope.interface-3.5.0-py2.5-linux-x86_64.egg
+_b = /home/shane/svn/keas.pbpersist/trunk/bin
+_d = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+_e = /home/shane/.buildout/eggs
+bin-directory = /home/shane/svn/keas.pbpersist/trunk/bin
+develop-eggs-directory = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+eggs = keas.pbpersist
+eggs-directory = /home/shane/.buildout/eggs
+executable = /usr/bin/python
+find-links = http://packages.willowrise.org
+location = /home/shane/svn/keas.pbpersist/trunk/parts/test
+recipe = zc.recipe.testrunner
+script = /home/shane/svn/keas.pbpersist/trunk/bin/test
+
+[python]
+__buildout_installed__ = /home/shane/svn/keas.pbpersist/trunk/bin/python
+__buildout_signature__ = zc.recipe.egg-1.1.0-py2.5.egg setuptools-0.6c9-py2.5.egg zc.buildout-1.1.1-py2.5.egg
+_b = /home/shane/svn/keas.pbpersist/trunk/bin
+_d = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+_e = /home/shane/.buildout/eggs
+bin-directory = /home/shane/svn/keas.pbpersist/trunk/bin
+develop-eggs-directory = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+eggs = keas.pbpersist
+eggs-directory = /home/shane/.buildout/eggs
+executable = /usr/bin/python
+find-links = http://packages.willowrise.org
+interpreter = python
+recipe = zc.recipe.egg
+
+[coverage-test]
+__buildout_installed__ = /home/shane/svn/keas.pbpersist/trunk/parts/coverage-test
+	/home/shane/svn/keas.pbpersist/trunk/bin/coverage-test
+__buildout_signature__ = zc.recipe.testrunner-1.1.0-py2.5.egg zc.recipe.egg-1.1.0-py2.5.egg setuptools-0.6c9-py2.5.egg zope.testing-3.7.1-py2.5.egg zc.buildout-1.1.1-py2.5.egg zc.buildout-1.1.1-py2.5.egg zope.interface-3.5.0-py2.5-linux-x86_64.egg
+_b = /home/shane/svn/keas.pbpersist/trunk/bin
+_d = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+_e = /home/shane/.buildout/eggs
+bin-directory = /home/shane/svn/keas.pbpersist/trunk/bin
+defaults = ['--coverage', '../../coverage']
+develop-eggs-directory = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+eggs = keas.pbpersist
+eggs-directory = /home/shane/.buildout/eggs
+executable = /usr/bin/python
+find-links = http://packages.willowrise.org
+location = /home/shane/svn/keas.pbpersist/trunk/parts/coverage-test
+recipe = zc.recipe.testrunner
+script = /home/shane/svn/keas.pbpersist/trunk/bin/coverage-test
+
+[coverage-report]
+__buildout_installed__ = /home/shane/svn/keas.pbpersist/trunk/bin/coverage-report
+__buildout_signature__ = zc.recipe.egg-1.1.0-py2.5.egg setuptools-0.6c9-py2.5.egg zc.buildout-1.1.1-py2.5.egg
+_b = /home/shane/svn/keas.pbpersist/trunk/bin
+_d = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+_e = /home/shane/.buildout/eggs
+arguments = ('coverage', 'coverage/report')
+bin-directory = /home/shane/svn/keas.pbpersist/trunk/bin
+develop-eggs-directory = /home/shane/svn/keas.pbpersist/trunk/develop-eggs
+eggs = z3c.coverage
+eggs-directory = /home/shane/.buildout/eggs
+executable = /usr/bin/python
+find-links = http://packages.willowrise.org
+recipe = zc.recipe.egg
+scripts = coverage=coverage-report

Added: keas.pbpersist/trunk/bootstrap.py
===================================================================
--- keas.pbpersist/trunk/bootstrap.py	                        (rev 0)
+++ keas.pbpersist/trunk/bootstrap.py	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py,v 1.1 2009/01/10 15:13:39 shane Exp $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                     ).read() in ez
+ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+# use pkg_resources from the package just downloaded.
+del sys.modules['pkg_resources']
+import pkg_resources
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: keas.pbpersist/trunk/buildout.cfg
===================================================================
--- keas.pbpersist/trunk/buildout.cfg	                        (rev 0)
+++ keas.pbpersist/trunk/buildout.cfg	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,29 @@
+[buildout]
+develop = .
+          ../../keas.pbstate/trunk
+parts = test python coverage-test coverage-report
+find-links = http://packages.willowrise.org
+versions = versions
+
+[versions]
+ZODB3 = 3.8.1-polling-serial
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = keas.pbpersist
+
+[python]
+recipe = zc.recipe.egg
+eggs = keas.pbpersist
+interpreter = python
+
+[coverage-test]
+recipe = zc.recipe.testrunner
+eggs = keas.pbpersist
+defaults = ['--coverage', '../../coverage']
+
+[coverage-report]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+scripts = coverage=coverage-report
+arguments = ('coverage', 'coverage/report')

Added: keas.pbpersist/trunk/setup.py
===================================================================
--- keas.pbpersist/trunk/setup.py	                        (rev 0)
+++ keas.pbpersist/trunk/setup.py	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,33 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+
+from setuptools import setup
+
+setup(
+    name='keas.pbpersist',
+    version='0.1dev',
+    author='Shane Hathaway and the Zope Community',
+    author_email='zope-dev at zope.org',
+    description='ZODB Persistence in a Google Protocol Buffer',
+    license='ZPL 2.1',
+
+    package_dir={'': 'src'},
+    packages=['keas.pbpersist'],
+    namespace_packages=['keas'],
+    install_requires=[
+        'setuptools',
+        'keas.pbstate',
+        'ZODB3',
+        ],
+)

Added: keas.pbpersist/trunk/src/keas/__init__.py
===================================================================
--- keas.pbpersist/trunk/src/keas/__init__.py	                        (rev 0)
+++ keas.pbpersist/trunk/src/keas/__init__.py	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,7 @@
+# this is a namespace package
+try:
+    import pkg_resources
+    pkg_resources.declare_namespace(__name__)
+except ImportError:
+    import pkgutil
+    __path__ = pkgutil.extend_path(__path__, __name__)

Added: keas.pbpersist/trunk/src/keas/pbpersist/README.txt
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/README.txt	                        (rev 0)
+++ keas.pbpersist/trunk/src/keas/pbpersist/README.txt	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,47 @@
+
+
+Tests of keas.pbpersist
+=======================
+
+Create a PContact instance.  PContact is a Persistent class that stores
+its state in a protobuf instance.
+
+    >>> from keas.pbpersist.tests import PContact
+    >>> pc = PContact()
+    >>> pc.__getstate__()
+    Traceback (most recent call last):
+    ...
+    EncodeError: Required field ContactPB.name is not set.
+    >>> pc.name = u'Joe'
+    >>> pc.__getstate__()
+    ('\x08\x01\x12\x03Joe', {})
+
+Register the protobuf serializer with ZODB.
+
+    >>> from keas.pbpersist.pbformat import register
+    >>> register()
+
+Set up an in-memory database and put the PContact in it.
+
+    >>> from ZODB.DemoStorage import DemoStorage
+    >>> from ZODB.DB import DB
+    >>> import transaction
+    >>> storage = DemoStorage()
+    >>> db = DB(storage)
+    >>> conn1 = db.open()
+    >>> conn1.root()['contact'] = pc
+    >>> transaction.commit()
+
+Read the PContact from another connection.
+
+    >>> conn2 = db.open()
+    >>> pc2 = conn2.root()['contact']
+    >>> pc2.name
+    u'Joe'
+    >>> conn2.close()
+
+Close the object database.
+
+    >>> transaction.abort()
+    >>> conn1.close()
+    >>> db.close()

Added: keas.pbpersist/trunk/src/keas/pbpersist/__init__.py
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/__init__.py	                        (rev 0)
+++ keas.pbpersist/trunk/src/keas/pbpersist/__init__.py	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1 @@
+

Added: keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py	                        (rev 0)
+++ keas.pbpersist/trunk/src/keas/pbpersist/pbformat.py	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,180 @@
+
+
+"""A serializer for ZODB that stores protobuf messages instead of pickles."""
+
+from zope.interface import implements
+from ZODB.interfaces import ISerialFormat, ISerializer, IDeserializer
+from ZODB.format import register_format
+from ZODB.utils import p64, u64
+from ZODB.POSException import POSError
+from keas.pbstate.state import StateTuple
+
+from keas.pbpersist.persistent_pb2 import ClassMetadata
+from keas.pbpersist.persistent_pb2 import ObjectRecord
+from keas.pbpersist.persistent_pb2 import Reference
+
+format_prefix = "{%s}" % StateTuple.serial_format
+
+def decode_record(data):
+    """Deserialize an ObjectRecord.
+
+    The serialized data must start with the serialization format prefix.
+    """
+    if not data.startswith(format_prefix):
+        raise POSError("Not a protobuf record: %s" % repr(data))
+    res = ObjectRecord()
+    res.MergeFromString(data[len(format_prefix):])
+    return res
+
+def read_class_meta(class_meta):
+    """Return a ZODB formatted tuple given a ClassMetadata.
+
+    This uses class metadata format #3 described by the
+    ZODB.serialize docstring.
+    """
+    return (class_meta.module_name, class_meta.class_name), None
+
+def write_class_meta(class_meta, source):
+    """Set attributes of a ClassMetadata from a source class metadata object.
+
+    The source is in any of the formats described by the
+    ZODB.serialize docstring.
+    """
+    if not isinstance(source, tuple):
+        # source is in format #1
+        class_meta.module_name = source.__module__
+        class_meta.class_name = source.__name__
+    else:
+        klass, args = source
+        if args is not None:
+            # source is in format #2, 4, 6, or 7
+            raise POSError(
+                "ProtobufSerializer can not serialize classes "
+                "using __getnewargs__ or __getinitargs__")
+        if isinstance(klass, tuple):
+            # source is in format #3
+            class_meta.module_name, class_meta.class_name = klass
+        else:
+            # source is in format #5
+            class_meta.module_name = klass.__module__
+            class_meta.class_name = klass.__name__
+
+def read_reference(ref):
+    """Return a ZODB formatted reference given a Reference message."""
+    oid = p64(ref.zoid)
+    if ref.weak:
+        return ['w', (oid,)]
+    elif ref.database:
+        if ref.class_meta:
+            cm = read_class_meta(ref.class_meta)
+            return ['m', (ref.database, oid, cm)]
+        else:
+            return ['n', (ref.database, oid)]
+    elif ref.class_meta:
+        cm = read_class_meta(ref.class_meta)
+        return (oid, cm)
+    else:
+        return oid
+
+
+class ProtobufFormat(object):
+    implements(ISerialFormat)
+
+    def makeSerializer(self, persistent_id):
+        return ProtobufSerializer(persistent_id)
+
+    def makeDeserializer(self, persistent_load, find_global=None):
+        return ProtobufDeserializer(persistent_load, find_global)
+
+    def listPersistentReferences(self, data):
+        record = decode_record(data)
+        return (read_reference(ref) for ref in record.references)
+
+
+class ProtobufSerializer(object):
+    implements(ISerializer)
+
+    def __init__(self, persistent_id):
+        self.persistent_id = persistent_id
+
+    def dump(self, classmeta, state):
+        """Serialize a persistent object as an ObjectRecord message."""
+        record = ObjectRecord()
+        write_class_meta(record.class_meta, classmeta)
+        record.state, refs = state
+
+        for refid, target in refs.iteritems():
+            p = self.persistent_id(target)
+            if p is None:
+                # All references must point to Persistent objects because
+                # the serialization format requires references to have an OID
+                # and only Persistent objects have an OID.
+                raise POSError(
+                    "Protobuf reference target is not a Persistent object: %s"
+                    % repr(target))
+            self.add_reference(record, refid, p)
+
+        return '%s%s' % (format_prefix, record.SerializeToString())
+
+    def add_reference(self, record, refid, p):
+        """Add a reference to an ObjectRecord.
+
+        p is a reference, created by the persistent_id() function,
+        in one of the formats documented by ZODB.serialize.
+        """
+        r = record.references.add()
+        r.refid = refid
+        oid = None
+        cm = None
+        if isinstance(p, tuple):
+            oid, cm = p
+        elif isinstance(p, str):
+            oid = p
+        elif len(p) == 1:
+            # old weakref format: [oid]
+            (oid,) = p
+            r.weak = True
+        else:
+            ref_type, args = p
+            if ref_type == 'm':
+                r.database, oid, cm = args
+            elif ref_type == 'w':
+                (oid,) = args
+                r.weak = True
+            elif ref_type == 'n':
+                r.database, oid = args
+            else:
+                raise POSError("Unknown reference type: %s" % repr(ref_type))
+        r.zoid = u64(oid)
+        if cm is not None:
+            write_class_meta(r.class_meta, cm)
+
+
+class ProtobufDeserializer(object):
+    implements(IDeserializer)
+
+    def __init__(self, persistent_load, find_global=None):
+        self.persistent_load = persistent_load
+        self.find_global = find_global
+
+    def getClassAndState(self, data):
+        record = decode_record(data)
+        yield read_class_meta(record.class_meta)
+        ref_dict = {}
+        for ref in record.references:
+            zodb_ref = read_reference(ref)
+            target = self.persistent_load(zodb_ref)
+            ref_dict[ref.refid] = target
+        yield record.state, ref_dict
+
+    def getClassMetadata(self, data):
+        return self.getClassAndState(data).next()
+
+    def getState(self, data):
+        i = self.getClassAndState(data)
+        i.next()
+        return i.next()
+
+
+def register():
+    register_format(StateTuple.serial_format, ProtobufFormat())

Added: keas.pbpersist/trunk/src/keas/pbpersist/persistent.proto
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/persistent.proto	                        (rev 0)
+++ keas.pbpersist/trunk/src/keas/pbpersist/persistent.proto	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,23 @@
+// This structure is derived from the documentation in the
+// ZODB.serialize module, although this version restricts the structure of
+// class metadata.
+
+message ClassMetadata {
+    required string module_name = 1;
+    required string class_name = 2;
+}
+
+message Reference {
+    required uint32 refid = 1;  // Identity within the persistent object record
+    required uint64 zoid = 2;   // ZODB OID as an integer
+    optional ClassMetadata class_meta = 3;  // Optimization for loading ghosts
+    optional string database = 4;   // for inter-database references
+    optional bool weak = 5;     // True for weak references
+    // note that weak references ignore class_meta and database.
+}
+
+message ObjectRecord {
+    required ClassMetadata class_meta = 1;
+    required bytes state = 2;
+    repeated Reference references = 3;
+}

Added: keas.pbpersist/trunk/src/keas/pbpersist/persistent_pb2.py
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/persistent_pb2.py	                        (rev 0)
+++ keas.pbpersist/trunk/src/keas/pbpersist/persistent_pb2.py	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,143 @@
+#!/usr/bin/python2.4
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+
+from google.protobuf import descriptor
+from google.protobuf import message
+from google.protobuf import reflection
+from google.protobuf import service
+from google.protobuf import service_reflection
+from google.protobuf import descriptor_pb2
+
+
+
+_CLASSMETADATA = descriptor.Descriptor(
+  name='ClassMetadata',
+  full_name='ClassMetadata',
+  filename='persistent.proto',
+  containing_type=None,
+  fields=[
+    descriptor.FieldDescriptor(
+      name='module_name', full_name='ClassMetadata.module_name', index=0,
+      number=1, type=9, cpp_type=9, label=2,
+      default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    descriptor.FieldDescriptor(
+      name='class_name', full_name='ClassMetadata.class_name', index=1,
+      number=2, type=9, cpp_type=9, label=2,
+      default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],  # TODO(robinson): Implement.
+  enum_types=[
+  ],
+  options=None)
+
+
+_REFERENCE = descriptor.Descriptor(
+  name='Reference',
+  full_name='Reference',
+  filename='persistent.proto',
+  containing_type=None,
+  fields=[
+    descriptor.FieldDescriptor(
+      name='refid', full_name='Reference.refid', index=0,
+      number=1, type=13, cpp_type=3, label=2,
+      default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    descriptor.FieldDescriptor(
+      name='zoid', full_name='Reference.zoid', index=1,
+      number=2, type=4, cpp_type=4, label=2,
+      default_value=0,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    descriptor.FieldDescriptor(
+      name='class_meta', full_name='Reference.class_meta', index=2,
+      number=3, type=11, cpp_type=10, label=1,
+      default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    descriptor.FieldDescriptor(
+      name='database', full_name='Reference.database', index=3,
+      number=4, type=9, cpp_type=9, label=1,
+      default_value=unicode("", "utf-8"),
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    descriptor.FieldDescriptor(
+      name='weak', full_name='Reference.weak', index=4,
+      number=5, type=8, cpp_type=7, label=1,
+      default_value=False,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],  # TODO(robinson): Implement.
+  enum_types=[
+  ],
+  options=None)
+
+
+_OBJECTRECORD = descriptor.Descriptor(
+  name='ObjectRecord',
+  full_name='ObjectRecord',
+  filename='persistent.proto',
+  containing_type=None,
+  fields=[
+    descriptor.FieldDescriptor(
+      name='class_meta', full_name='ObjectRecord.class_meta', index=0,
+      number=1, type=11, cpp_type=10, label=2,
+      default_value=None,
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    descriptor.FieldDescriptor(
+      name='state', full_name='ObjectRecord.state', index=1,
+      number=2, type=12, cpp_type=9, label=2,
+      default_value="",
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+    descriptor.FieldDescriptor(
+      name='references', full_name='ObjectRecord.references', index=2,
+      number=3, type=11, cpp_type=10, label=3,
+      default_value=[],
+      message_type=None, enum_type=None, containing_type=None,
+      is_extension=False, extension_scope=None,
+      options=None),
+  ],
+  extensions=[
+  ],
+  nested_types=[],  # TODO(robinson): Implement.
+  enum_types=[
+  ],
+  options=None)
+
+
+_REFERENCE.fields_by_name['class_meta'].message_type = _CLASSMETADATA
+_OBJECTRECORD.fields_by_name['class_meta'].message_type = _CLASSMETADATA
+_OBJECTRECORD.fields_by_name['references'].message_type = _REFERENCE
+
+class ClassMetadata(message.Message):
+  __metaclass__ = reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _CLASSMETADATA
+
+class Reference(message.Message):
+  __metaclass__ = reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _REFERENCE
+
+class ObjectRecord(message.Message):
+  __metaclass__ = reflection.GeneratedProtocolMessageType
+  DESCRIPTOR = _OBJECTRECORD
+

Added: keas.pbpersist/trunk/src/keas/pbpersist/tests.py
===================================================================
--- keas.pbpersist/trunk/src/keas/pbpersist/tests.py	                        (rev 0)
+++ keas.pbpersist/trunk/src/keas/pbpersist/tests.py	2009-01-22 00:48:09 UTC (rev 94914)
@@ -0,0 +1,40 @@
+##############################################################################
+#
+# Copyright (c) 2009 Zope Foundation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (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.
+#
+##############################################################################
+
+import time
+import unittest
+
+from zope.testing import doctest
+from persistent import Persistent
+from keas.pbstate.meta import ProtobufState
+from keas.pbstate.testclasses_pb2 import ContactPB
+
+
+class PContact(Persistent):
+    __metaclass__ = ProtobufState
+    protobuf_type = ContactPB
+
+    def __init__(self):
+        self.create_time = 1
+
+
+def test_suite():
+    return unittest.TestSuite([
+        doctest.DocFileSuite(
+            'README.txt',
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS),
+    ])
+
+if __name__ == '__main__':
+    unittest.main()



More information about the Checkins mailing list