[Checkins] SVN: z3c.dobbin/trunk/ Reimplemented persistence policy such that all non-mapped attributes are persisted automatically using the Pickle-protocol.

Malthe Borch mborch at gmail.com
Tue Jul 22 09:04:46 EDT 2008


Log message for revision 88685:
  Reimplemented persistence policy such that all non-mapped attributes are persisted automatically using the Pickle-protocol.

Changed:
  U   z3c.dobbin/trunk/CHANGES.txt
  U   z3c.dobbin/trunk/README.txt
  U   z3c.dobbin/trunk/setup.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/README.txt
  U   z3c.dobbin/trunk/src/z3c/dobbin/bootstrap.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/mapper.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/session.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/testing.py
  A   z3c.dobbin/trunk/src/z3c/dobbin/utility.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/zs2sa.py

-=-
Modified: z3c.dobbin/trunk/CHANGES.txt
===================================================================
--- z3c.dobbin/trunk/CHANGES.txt	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/CHANGES.txt	2008-07-22 13:04:45 UTC (rev 88685)
@@ -1,6 +1,16 @@
 Change log
 ==========
 
+0.4dev
+------
+
+- All attributes that are not declared as interface names are now
+  persisted automatically using the Pickle-protocol. The exception to
+  this rule is attributes starting with the characters "_v_" (volatile
+  attributes).
+
+- Changed target to SQLAlchemy 0.5-series.
+
 0.3.2
 -----
 
@@ -15,35 +25,29 @@
 
 - Use native UUID column type (available on PostgreSQL); compatibility
   with SQLite is preserved due to its weak typing.
-  [malthe]
 
+
 - Basic type factories are now registered as components.
-  [malthe]
 
 0.3.0
 -----
 
 - Implemented rest of list methods.
-  [malthe]
   
 - Refactoring of table bootstrapping; internal tables now using a
   naming convention less likely to clash with existing tables.
-  [malthe]
 
 - Added support for ``schema.Dict`` (including polymorphic dictionary
   relation).
-  [malthe]
 
 - Implemented polymorphic relations for a subset of the basic types
   (int, str, unicode, tuple and list).
-  [malthe]
-
+  
 0.2.9
 -----
 
 - Tables are now only created once per minimal interface; this fixes
   issue on both SQLite and Postgres when we create mappers with an
   explicit polymorphic class.
-  [malthe]
 
 - First entry in change-log.

Modified: z3c.dobbin/trunk/README.txt
===================================================================
--- z3c.dobbin/trunk/README.txt	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/README.txt	2008-07-22 13:04:45 UTC (rev 88685)
@@ -1,21 +1,26 @@
 Overview
 ========
 
-Dobbin is a relational database abstraction layer supporting a
-semi-transparent object persistance model.
+Dobbin is an object database implemented on top of SQLAlchemy. It's
+designed to mimick the behavior of the Zope object database (ZODB)
+while providing greater flexibility and control of the storage.
 
-It relies on descriptive attribute and field declarations based on
-zope.interface and zope.schema. Strong typing is supported (and
-encouraged when possible), but not required.
+It supports strong typing with native SQL columns by utilizing the
+declarative field definitions from zope.schema. Weak typing is
+supported using the Python pickle protocol. Attributes are
+automatically persisted with the exception of those starting with the
+characters "_v_" (volatile attributes).
 
-Tables are created on-the-fly with 1:1 correspondence to interfaces
-with no inheritance (base interface). As such, objects are modelled as
-a join between the interfaces they implement.
+Tables to support the strongly typed attributes are created on-the-fly
+with a 1:1 correspondence to interfaces with no inheritance (base
+interface). As such, objects are modelled as a join between the
+interfaces they implement plus a table that maintains object metadata
+and weakly typed instance attributes.
 
 Authors
 -------
 
-This package was designed and implemented by Malthe Borch, Stefan
+This package was designed and implemented by Malthe Borch and Stefan
 Eletzhofer with parts contributed by Kapil Thangavelu and Laurence
 Rowe. It's licensed as ZPL.
 

Modified: z3c.dobbin/trunk/setup.py
===================================================================
--- z3c.dobbin/trunk/setup.py	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/setup.py	2008-07-22 13:04:45 UTC (rev 88685)
@@ -18,7 +18,7 @@
     return "\n".join((open(f).read() for f in files))
 
 setup(name='z3c.dobbin',
-      version='0.3dev',
+      version='0.4dev',
       license='ZPL',
       author = "Malthe Borch, Stefan Eletzhofer and the Zope Community",
       author_email = "zope-dev at zope.org",
@@ -51,5 +51,5 @@
                            'zope.configuration',
                            'z3c.saconfig',
                            'transaction',
-                           'SQLAlchemy==0.4.6'],
+                           'SQLAlchemy>0.4'],
       )

Modified: z3c.dobbin/trunk/src/z3c/dobbin/README.txt
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/README.txt	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/src/z3c/dobbin/README.txt	2008-07-22 13:04:45 UTC (rev 88685)
@@ -1,21 +1,38 @@
 Walk-through of the framework
 =============================
 
-This section demonstrates the main functionality of the package using
-the doctest format. 
+This section demonstrates the functionality of the package.
 
+Introduction
+------------
+
+Dobbin uses SQLAlchemy's object relational mapper to transparently
+store objects in the database. Objects are persisted in two levels:
+
+Attributes may correspond directly to a table column in which case we
+say that the attribute is strongly typed. This is the most optimal
+way to store data.
+
+We may also store attributes that are not mapped directly to a column;
+in this case, the value of the attribute is stored as a Python
+pickle. This allows weak typing, but also persistence of amorphic
+data, e.g. data which does not fit naturally in a relational database.
+
+A universally unique id (UUID) is automatically assigned to all
+objects.
+
 We begin with a new database session.
 
     >>> import z3c.saconfig
     >>> session = z3c.saconfig.Session()
+    
+Declarative configuration
+-------------------------
 
-Mappers from interface specification
-------------------------------------
+We can map attributes to table columns using zope.schema. Instead of
+using SQL column definitions, we rely on the declarative properties of
+schema fields.
 
-We'll start out creating mappers directly from an interface
-specification. The instances will only afford access to the declared
-attributes and have no methods.
-
 We start out with an interface decribing a recorded album.
 
     >>> class IAlbum(interface.Interface):
@@ -28,8 +45,8 @@
     ...         default=u"")
 
 We can now fabricate instances that implement this interface by using
-the ``create`` method. This is a shorthand for setting up the mapper
-and creating an instance using its factory.
+the ``create`` method. This is a shorthand for setting up a mapper and
+creating an instance by calling it.
 
     >>> from z3c.dobbin.factory import create
     >>> album = create(IAlbum)
@@ -44,30 +61,27 @@
 
     >>> class IVinyl(IAlbum):
     ...     rpm = schema.Int(
-    ...         title=u"RPM",
-    ...         default=33)
+    ...         title=u"RPM")
 
     >>> vinyl = create(IVinyl)
-
-What actually happens on the database side is that columns are mapped
-to the interface that they provide.
-
-Let's demonstrate that the mapper instance actually implements the
-defined fields.
-
     >>> vinyl.artist = "Diana Ross and The Supremes"
     >>> vinyl.title = "Taking Care of Business"
     >>> vinyl.rpm = 45
 
-Or a compact disc.
+The attributes are instrumented by SQLAlchemy and map directly to a
+column in a table.
 
+    >>> IVinyl.__mapper__.artist
+    <sqlalchemy.orm.attributes.InstrumentedAttribute object at ...>
+
+A compact disc is another kind of album.
+
     >>> class ICompactDisc(IAlbum):
     ...     year = schema.Int(title=u"Year")
 
-    >>> cd = create(ICompactDisc)
-
 Let's pick a more recent Diana Ross, to fit the format.
     
+    >>> cd = create(ICompactDisc)
     >>> cd.artist = "Diana Ross"
     >>> cd.title = "The Great American Songbook"
     >>> cd.year = 2005
@@ -83,6 +97,8 @@
 to be a bug in ``zope.sqlalchemy``.
     
     >>> results = session.query(album.__class__).all()
+
+Proceed with the transaction.
     
     >>> import transaction
     >>> transaction.commit()
@@ -113,8 +129,8 @@
     >>> session.execute(metadata.tables[encode(ICompactDisc)].select()).fetchall()
     [(3, 2005)]
 
-Concrete class specification
-----------------------------
+Mapping concrete classes
+------------------------
     
 Now we'll create a mapper based on a concrete class. We'll let the
 class implement the interface that describes the attributes we want to
@@ -123,9 +139,6 @@
     >>> class Vinyl(object):
     ...     interface.implements(IVinyl)
     ...
-    ...     artist = title = u""
-    ...     rpm = 33
-    ...
     ...     def __repr__(self):
     ...         return "<Vinyl %s: %s (@ %d RPM)>" % \
     ...                (self.artist, self.title, self.rpm)
@@ -162,8 +175,10 @@
     >>> repr(vinyl)
     '<Vinyl Diana Ross and The Supremes: Taking Care of Business (@ 45 RPM)>'
 
-If we're mapping a concrete class, and run into class properties, we
-won't instrument them even if they're declared by the schema.
+When mapping a class we may run into properties that should take the
+place of a column (a read-only value). As an example, consider this
+experimental record class where rotation speed is a function of the
+title and artist.
 
     >>> class Experimental(Vinyl):
     ...     @property
@@ -171,6 +186,13 @@
     ...         return len(self.title+self.artist)
 
     >>> experimental = create(Experimental)
+
+XXX: There's currently an issue with SQLAlchemy that hinders this
+behavior; it specifically won't work if a default value is set on the
+column that we're overriding.
+
+    >>> # session.save(experimental)
+    
     >>> experimental.artist = vinyl.artist
     >>> experimental.title = vinyl.title
 
@@ -179,26 +201,20 @@
     >>> experimental.rpm
     50
 
-Instances of mappers automatically join the object soup.
-
-    >>> from z3c.dobbin.mapper import getMapper
-    >>> mapper = getMapper(Vinyl)
-    >>> instance = mapper()
-    >>> instance.uuid is not None
-    True
-    
 Relations
 ---------
 
-Relations are columns that act as references to other objects.
+Relations are columns that act as references to other objects. They're
+declared using the ``zope.schema.Object`` field.
 
-As an example, let's create an object holds a reference to some
-favorite item. We use ``zope.schema.Object`` to declare this
-reference; relations are polymorphic and we needn't declare the schema
-of the referenced object in advance.
+Note that we needn't declare the relation target type in advance,
+although it may be useful in general to specialize the ``schema``
+keyword parameter.
 
     >>> class IFavorite(interface.Interface):
-    ...     item = schema.Object(title=u"Item", schema=interface.Interface)
+    ...     item = schema.Object(
+    ...         title=u"Item",
+    ...         schema=interface.Interface)
 
     >>> __builtin__.IFavorite = IFavorite
     
@@ -211,7 +227,7 @@
 
     >>> session.save(favorite)
 
-We'll commit the transaction and lookup the object by its UUID.
+We'll commit the transaction and lookup the object by its unique id.
 
     >>> transaction.commit()
 
@@ -485,18 +501,29 @@
     ...         title=u"Discographies by artist",
     ...         value_type=schema.List())
 
-Polymorphic structures
-----------------------
+Amorphic objects
+----------------
 
-We can use weak typing to store (almost) any kind of structure. Values
-are kept as Python pickles.
+We can set and retrieve attributes that aren't declared in an
+interface.
 
-    >>> class IPolyFavorite(interface.Interface):
-    ...     item = interface.Attribute(u"Any kind of favorite")
+    >>> record = create(interface.Interface)
 
-    >>> __builtin__.IPolyFavorite = IPolyFavorite
-    >>> favorite = create(IPolyFavorite)
+    >>> record.publisher = u"Columbia records"
+    >>> record.publisher
+    u'Columbia records'
 
+    >>> session.save(record)
+    >>> session.query(record.__class__).filter_by(
+    ...     uuid=record.uuid)[0].publisher
+    u'Columbia records'
+    
+Using this kind of weak we can store (almost) any kind of
+structure. Values are kept as Python pickles.
+
+    >>> favorite = create(interface.Interface)
+    >>> session.save(favorite)
+
 A transaction hook makes sure that assigned values are transient
 during a session.
     
@@ -547,12 +574,9 @@
     >>> favorite.item = favorite.item
     >>> transaction.commit()
 
-Clear the object cache and verify value.
-    
-    >>> del favorite._v_cached_item_pickle
     >>> sorted(favorite.item.items())
     [(u'black', 0), (u'blue', 255), (u'green', 65280), (u'red', 16711680)]
-    
+
 When we create relations to mutable objects, a hook is made into the
 transaction machinery to keep track of the pending state.
 
@@ -571,18 +595,14 @@
 Structures involving relations to other instances.
 
     >>> favorite.item = vinyl; transaction.commit()
-    >>> del favorite._v_cached_item_pickle
     >>> favorite.item
     <Vinyl Diana Ross and The Supremes: Taking Care of Business (@ 45 RPM)>
 
 Self-referencing works because polymorphic attributes are lazy.
 
-    >>> session.save(favorite)
-    
     >>> favorite.item = favorite; transaction.commit()
-    >>> del favorite._v_cached_item_pickle
     >>> favorite.item
-    <Mapper (__builtin__.IPolyFavorite) at ...>
+    <z3c.dobbin.bootstrap.Soup object at ...>
     
 Security
 --------
@@ -593,7 +613,9 @@
 
 Our ``Vinyl`` class does not have a security checker defined.
     
+    >>> from z3c.dobbin.mapper import getMapper
     >>> mapper = getMapper(Vinyl)
+    
     >>> getCheckerForInstancesOf(mapper) is None
     True
 

Modified: z3c.dobbin/trunk/src/z3c/dobbin/bootstrap.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/bootstrap.py	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/src/z3c/dobbin/bootstrap.py	2008-07-22 13:04:45 UTC (rev 88685)
@@ -1,3 +1,4 @@
+from zope import interface
 from zope import component
 
 import sqlalchemy as rdb
@@ -6,27 +7,25 @@
 from z3c.saconfig import Session
 
 import soup
+import utility
 import relations
 import interfaces
+import cPickle
 
 class UUID(rdb.types.TypeEngine):
     def get_col_spec(self):
         return "UUID"
 
-def bootstrapDatabaseEngine(event=None):
-    session = Session()
-    engine = session.bind
-    engine.metadata = metadata = rdb.MetaData(engine)
+def initialize(event=None):
+    """Database initialization.
 
-    # setup metadata
-    setUp(metadata)
-    
-def setUp(metadata):
-    """Table setup.
-
     This method sets up the tables that are necessary for the
     operation of the persistence and relational framework.
     """
+
+    session = Session()
+    engine = session.bind
+    engine.metadata = metadata = rdb.MetaData(engine)
     
     soup = rdb.Table(
         'dobbin:soup',
@@ -34,10 +33,11 @@
         rdb.Column('id', rdb.Integer, primary_key=True, autoincrement=True),
         rdb.Column('uuid', UUID, unique=True, index=True),
         rdb.Column('spec', rdb.String, index=True),
+        rdb.Column('dict', rdb.PickleType, default={}, index=False),
         )
 
     soup_fk = rdb.ForeignKey(soup.c.uuid)
-
+    
     int_relation = rdb.Table(
         'dobbin:relation:int',
         metadata,
@@ -63,11 +63,18 @@
     metadata.create_all()
 
 class Soup(object):
+    interface.implements(interfaces.IMapped)
+    
     """Soup class.
 
     This is the base object of all mappers.
     """
 
+    def __new__(cls, *args, **kwargs):
+        inst = object.__new__(cls, *args, **kwargs)
+        inst.__dict__ = utility.dictproxy(inst)
+        return inst
+    
     def __cmp__(self, other):
         if interfaces.IMapped.providedBy(other):
             return cmp(self.id, other.id)
@@ -75,4 +82,4 @@
         return -1
 
     def __reduce__(self):
-        return (soup.lookup, (self.uuid,))
+        return (soup.build, (self.__spec__, self.uuid,))

Modified: z3c.dobbin/trunk/src/z3c/dobbin/mapper.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/mapper.py	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/src/z3c/dobbin/mapper.py	2008-07-22 13:04:45 UTC (rev 88685)
@@ -22,6 +22,7 @@
 from itertools import chain
 
 import bootstrap
+import session as tx
 import soup
 import zs2sa
 import types
@@ -54,6 +55,8 @@
 def createMapper(spec):
     """Create a mapper for the specification."""
 
+    interface.alsoProvides(spec, IMapped)
+
     engine = Session().bind
     metadata = engine.metadata
 
@@ -73,12 +76,14 @@
             if isinstance(value, property):
                 exclude.append(name)
 
-    assert ifaces, "Specification must declare at least one field."
-    
+    if not ifaces:
+        spec.__mapper__ = bootstrap.Soup
+        return spec.__mapper__
+
     # create joined table
     properties = {}
     first_table = None
-    
+
     for (t, p) in (getTable(iface, metadata, exclude) for iface in ifaces):
         if first_table is None:
             table = first_table = t
@@ -89,10 +94,10 @@
     specification_path = '%s.%s' % (spec.__module__, spec.__name__)
 
     class Mapper(bootstrap.Soup, kls):
-        interface.implements(IMapped, *ifaces)
+        interface.implements(*ifaces)
 
         __spec__ = specification_path
-        
+
         def __init__(self, *args, **kwargs):
             super(Mapper, self).__init__(*args, **kwargs)
 
@@ -125,7 +130,9 @@
             del properties[name]
             setattr(Mapper, name, prop)
 
-    soup_table = bootstrap.Soup.c.id.table
+    # XXX: there must be a more straight-forward way to do this
+    soup_table = bootstrap.Soup._sa_class_manager.mappers[None].local_table
+    
     polymorphic = (
         [Mapper], table.join(
         soup_table, first_table.c.id==soup_table.c.id))
@@ -140,8 +147,7 @@
         inherit_condition=(first_table.c.id==soup_table.c.id))
 
     spec.__mapper__ = Mapper
-    interface.alsoProvides(spec, IMapped)
-
+    
     return Mapper
 
 def removeMapper(spec):
@@ -187,13 +193,15 @@
         
     kw = dict(useexisting=True)
 
+    soup_table = bootstrap.Soup._sa_class_manager.mappers[None].local_table
+
     table = rdb.Table(
         name,
         metadata,
-        rdb.Column('id', rdb.Integer, rdb.ForeignKey(bootstrap.Soup.c.id), primary_key=True),
+        rdb.Column('id', rdb.Integer, rdb.ForeignKey(soup_table.c.id), primary_key=True),
         *columns,
         **kw)
 
-    metadata.create_all(checkfirst=True)
+    table.create(checkfirst=True)
     
     return table, properties

Modified: z3c.dobbin/trunk/src/z3c/dobbin/session.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/session.py	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/src/z3c/dobbin/session.py	2008-07-22 13:04:45 UTC (rev 88685)
@@ -7,9 +7,6 @@
 def COPY_CONCRETE_TO_INSTANCE(uuid):
     return COPY_CONCRETE_TO_INSTANCE, uuid
 
-def COPY_VALUE_TO_INSTANCE(uuid, name):
-    return COPY_VALUE_TO_INSTANCE, uuid, name
-
 def addBeforeCommitHook(token, value, hook):
     session = Session()
 

Modified: z3c.dobbin/trunk/src/z3c/dobbin/testing.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/testing.py	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/src/z3c/dobbin/testing.py	2008-07-22 13:04:45 UTC (rev 88685)
@@ -20,11 +20,11 @@
     component.provideUtility(factory)
 
     # setup scoped session
-    utility = GloballyScopedSession(autoflush=True)
+    utility = GloballyScopedSession()
     component.provideUtility(utility)
     
     # bootstrap database engine
-    z3c.dobbin.bootstrap.bootstrapDatabaseEngine()
+    z3c.dobbin.bootstrap.initialize()
 
     # register components
     zope.configuration.xmlconfig.XMLConfig('meta.zcml', component)()

Added: z3c.dobbin/trunk/src/z3c/dobbin/utility.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/utility.py	                        (rev 0)
+++ z3c.dobbin/trunk/src/z3c/dobbin/utility.py	2008-07-22 13:04:45 UTC (rev 88685)
@@ -0,0 +1,40 @@
+import soup
+import session as tx
+import interfaces
+
+class dictproxy(dict):
+    """Dictionary proxy.
+
+    Proxies non-mapped attributes to an internal dictionary.
+    """
+    
+    def __init__(self, owner):
+        assert interfaces.IMapped.providedBy(owner)
+        self.owner = owner
+
+    def _is_mapped(self, key):
+        owner = self.owner
+        return key.startswith('_v_') or \
+               key in owner.__class__.__dict__ or \
+               key in owner._sa_class_manager.keys()
+    
+    def __getitem(self, key):
+        if self._is_mapped(key):
+            return dict.__getitem__(key)
+
+        if self.owner.dict is None:
+            raise KeyError(key)
+        
+        return self.owner.dict[key]
+        
+    def __setitem__(self, key, value):
+        if self._is_mapped(key):
+            dict.__setitem__(self, key, value)
+        else:
+            if self.owner.dict is None:
+                self.owner.dict = {key: value}
+            else:
+                self.owner.dict[key] = value
+
+    def __repr__(self):
+        return "<dictproxy %s>" % dict.__repr__(self)

Modified: z3c.dobbin/trunk/src/z3c/dobbin/zs2sa.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/zs2sa.py	2008-07-22 12:56:23 UTC (rev 88684)
+++ z3c.dobbin/trunk/src/z3c/dobbin/zs2sa.py	2008-07-22 13:04:45 UTC (rev 88685)
@@ -24,8 +24,6 @@
 import relations
 import collections
 
-import cPickle as Pickle
-
 class FieldTranslator(object):
     """Translate a zope schema field to a SQLAlchemy column."""
 
@@ -78,66 +76,6 @@
         return rdb.Column(
             field.__name__+'_uuid', bootstrap.UUID, nullable=False)
 
-class PickleTranslator(object):
-    def __call__(self, field, metadata):
-        return rdb.Column(
-            field.__name__+'_pickle', rdb.BLOB, nullable=True)
-
-class PickleProperty(property):
-    def __init__(self, name):
-        self.name = name
-        self.cache = '_v_cached_'+name
-        property.__init__(self, self._get, self._set)
-        
-    def _get(self, obj, type=None):
-        session = Session()
-        name = self.name
-        cache = self.cache
-        
-        token = tx.COPY_VALUE_TO_INSTANCE(obj.uuid, name)
-
-        # check pending objects
-        try:
-            return session._d_pending[token]
-        except (AttributeError, KeyError):
-            pass
-
-        # check object cache
-        value = getattr(obj, cache, None)
-        if value is not None:
-            return value
-
-        # load pickle
-        pickle = getattr(obj, name)
-        value = pickle and Pickle.loads(pickle)
-
-        # update cache
-        if value is not None:
-            setattr(obj, cache, value)
-        
-        return value
-
-    def _set(self, obj, value):
-        name = self.name
-        token = tx.COPY_VALUE_TO_INSTANCE(obj.uuid, name)
-        
-        def copy_value_to_instance():
-            value = Session()._d_pending[token]
-            pickle = Pickle.dumps(value)
-            setattr(obj, name, pickle)
-
-        # add transaction hook
-        tx.addBeforeCommitHook(
-            token, value, copy_value_to_instance)
-
-        # update cache
-        if value is not None:
-            setattr(obj, self.cache, value)
-
-class PicklePropertyFactory(object):
-    def __call__(self, field, column, metadata):
-        return {field.__name__: PickleProperty(column.name)}
-
 class ObjectProperty(object):
     """Object property.
     
@@ -152,7 +90,7 @@
             field.__name__: relation,
             relation.name: orm.relation(
             bootstrap.Soup,
-            primaryjoin=bootstrap.Soup.c.uuid==column,
+            primaryjoin=bootstrap.Soup.uuid==column,
             foreign_keys=[column],
             enable_typechecks=False,
             lazy=True)
@@ -181,7 +119,7 @@
     relation_class = relations.OrderedRelation
 
     def getPrimaryJoinCondition(self):
-        return bootstrap.Soup.c.uuid==relations.OrderedRelation.c.left
+        return bootstrap.Soup.uuid==relations.OrderedRelation.left
     
 class TupleProperty(ListProperty):
     collection_class = collections.Tuple
@@ -191,7 +129,7 @@
     relation_class = relations.KeyRelation
 
     def getPrimaryJoinCondition(self):
-        return bootstrap.Soup.c.uuid==relations.KeyRelation.c.left
+        return bootstrap.Soup.uuid==relations.KeyRelation.left
                         
 fieldmap = {
     schema.ASCII: StringTranslator(), 
@@ -214,6 +152,6 @@
     schema.Text: StringTranslator(rdb.UnicodeText),
     schema.TextLine: StringTranslator(rdb.Unicode),
     schema.URI: StringTranslator(rdb.Unicode),
-    interface.Attribute: (PickleTranslator(), PicklePropertyFactory()),
+    interface.Attribute: None,
     interface.interface.Method: None,
 }



More information about the Checkins mailing list