[Checkins] SVN: z3c.dobbin/trunk/src/z3c/dobbin/ Tables for minimal interfaces are now generated exactly once; this fixes an issue on postgres first appearing in SQLAlchemy 0.4.6 (r4565). Mappers are now polymorphic; this fixes an issue on SQLite where joins would be reversed.

Malthe Borch mborch at gmail.com
Wed Jun 18 12:47:38 EDT 2008


Log message for revision 87528:
  Tables for minimal interfaces are now generated exactly once; this fixes an issue on postgres first appearing in SQLAlchemy 0.4.6 (r4565). Mappers are now polymorphic; this fixes an issue on SQLite where joins would be reversed.

Changed:
  U   z3c.dobbin/trunk/src/z3c/dobbin/README.txt
  U   z3c.dobbin/trunk/src/z3c/dobbin/collections.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/mapper.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/relations.py
  U   z3c.dobbin/trunk/src/z3c/dobbin/session.py

-=-
Modified: z3c.dobbin/trunk/src/z3c/dobbin/README.txt
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/README.txt	2008-06-18 16:44:12 UTC (rev 87527)
+++ z3c.dobbin/trunk/src/z3c/dobbin/README.txt	2008-06-18 16:47:38 UTC (rev 87528)
@@ -131,6 +131,7 @@
 
     >>> import __builtin__
     >>> __builtin__.IVinyl = IVinyl
+    >>> __builtin__.IAlbum = IAlbum
     >>> __builtin__.Vinyl = Vinyl
 
 Create an instance using the ``create`` factory.
@@ -144,8 +145,8 @@
 
 Copy the attributes from the Diana Ross vinyl record.
 
-    >>> diana = session.query(IVinyl.__mapper__).filter_by(id=2)[0]
-    
+    >>> diana = session.query(IVinyl.__mapper__).filter_by(
+    ...     artist=u"Diana Ross and The Supremes")[0]
     >>> vinyl.artist = diana.artist
     >>> vinyl.title = diana.title
     >>> vinyl.rpm = diana.rpm
@@ -254,7 +255,10 @@
 persisted in the database.
 
     >>> cleaner.name = u"CD cleaner"
-    >>> transaction.commit()
+    
+    >>> session.flush()
+    >>> session.update(favorite)
+    
     >>> favorite.item.name
     u'CD cleaner'
     
@@ -285,7 +289,7 @@
     
 We can get our collection back.
 
-    >>> from z3c.dobbin.relations import lookup
+    >>> from z3c.dobbin.soup import lookup
     >>> collection = lookup(collection.uuid)
 
 Let's verify that we've stored the Diana Ross record.
@@ -295,7 +299,7 @@
     >>> record.artist, record.title
     (u'Diana Ross and The Supremes', u'Taking Care of Business')
 
-    >>> transaction.commit()
+    >>> session.flush()
     
 When we create a new, transient object and append it to a list, it's
 automatically saved on the session.
@@ -304,14 +308,14 @@
 
     >>> vinyl = create(IVinyl)
     >>> vinyl.artist = u"Kool & the Gang"
-    >>> vinyl.album = u"Music Is the Message"
+    >>> vinyl.title = u"Music Is the Message"
     >>> vinyl.rpm = 33
 
     >>> collection.records.append(vinyl)
     >>> [record.artist for record in collection.records]
     [u'Diana Ross and The Supremes', u'Kool & the Gang']
 
-    >>> transaction.commit()
+    >>> session.flush()
     >>> session.update(collection)
     
 We can remove items.
@@ -383,10 +387,9 @@
     ...     __name__ = schema.TextLine()
 
     >>> from z3c.dobbin.interfaces import IMapper
-    
     >>> mapper = IMapper(IKnownLimitations)
-    >>> '__name__' in mapper.c
-    False
+    >>> mapper.__name__
+    'Mapper'
 
 Cleanup
 -------

Modified: z3c.dobbin/trunk/src/z3c/dobbin/collections.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/collections.py	2008-06-18 16:44:12 UTC (rev 87527)
+++ z3c.dobbin/trunk/src/z3c/dobbin/collections.py	2008-06-18 16:47:38 UTC (rev 87528)
@@ -4,6 +4,7 @@
 
 import interfaces
 import relations
+import soup
 
 class OrderedList(object):
     __Security_checker__ = NamesChecker(
@@ -27,11 +28,12 @@
     @orm.collections.collection.remover
     def _remover(self, item):
         self.data.remove(item)
-        
+
+    @orm.collections.collection.internally_instrumented
     def append(self, item, _sa_initiator=None):
         # make sure item is mapped
         if not interfaces.IMapped.providedBy(item):
-            item = relations.persist(item)
+            item = soup.persist(item)
 
         # set up relation
         relation = relations.Relation()
@@ -43,6 +45,7 @@
         # add relation to internal list
         self.data.append(relation)
 
+    @orm.collections.collection.internally_instrumented
     def remove(self, item, _sa_initiator=None):
         if interfaces.IMapped.providedBy(item):
             uuid = item.uuid

Modified: z3c.dobbin/trunk/src/z3c/dobbin/mapper.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/mapper.py	2008-06-18 16:44:12 UTC (rev 87527)
+++ z3c.dobbin/trunk/src/z3c/dobbin/mapper.py	2008-06-18 16:47:38 UTC (rev 87528)
@@ -172,8 +172,8 @@
     engine = component.getUtility(IDatabaseEngine)
     metadata = engine.metadata
 
-    ignore = ('__name__',)
-
+    exclude = ['__name__']
+    
     # expand specification
     if interface.interfaces.IInterface.providedBy(spec):
         ifaces = set([spec.get(name).interface for name in schema.getFields(spec)])
@@ -184,12 +184,16 @@
         ifaces = set([implemented.get(name).interface for name in fields])
         kls = spec
 
+        for name, value in spec.__dict__.items():
+            if isinstance(value, property):
+                exclude.append(name)
+
     # create joined table
     soup_table = table = metadata.tables['soup']
     properties = {}
     first_table = None
     
-    for (t, p) in (getTable(iface, metadata, ignore) for iface in ifaces):
+    for (t, p) in (getTable(iface, metadata, exclude) for iface in ifaces):
         if first_table is None:
             table = first_table = t
         else:
@@ -197,7 +201,7 @@
         properties.update(p)
 
     specification_path = '%s.%s' % (spec.__module__, spec.__name__)
-        
+
     class Mapper(bootstrap.Soup, kls):
         interface.implements(IMapped, *ifaces)
 
@@ -235,18 +239,17 @@
             del properties[name]
             setattr(Mapper, name, prop)
 
-    exclude = ()
-    
-    if not interface.interfaces.IInterface.providedBy(spec):
-        for name, value in spec.__dict__.items():
-            if isinstance(value, property):
-                exclude += (name,)
 
+    polymorphic = (
+        [Mapper], table.join(
+        soup_table, first_table.c.id==soup_table.c.id))
+
     orm.mapper(
         Mapper,
         table,
         properties=properties,
         exclude_properties=exclude,
+        with_polymorphic=polymorphic,
         inherits=bootstrap.Soup,
         inherit_condition=(first_table.c.id==soup_table.c.id))
 
@@ -260,24 +263,28 @@
     interface.noLongerProvides(spec, IMapped)
         
 def getTable(iface, metadata, ignore=()):
+    name = encode(iface)
+
     columns = []
     properties = {}
     
     for field in map(lambda key: iface[key], iface.names()):
         property_factory = None
 
-        # ignores
         if field.__name__ in ignore:
             continue
-        
+
         try:
-            column_factory, property_factory = fieldmap[type(field)]
-        except TypeError:
-            column_factory = fieldmap[type(field)]
+            factories = fieldmap[type(field)]
         except KeyError:
             # raise NotImplementedError("Field type unsupported (%s)." % field)
             continue
 
+        try:
+            column_factory, property_factory = factories
+        except TypeError:
+            column_factory = factories
+            
         if column_factory is not None:
             column = column_factory(field, metadata)
             columns.append(column)
@@ -287,11 +294,14 @@
         if property_factory is not None:
             props = property_factory(field, column, metadata)
             properties.update(props)
+
+    if name in metadata.tables:
+        return metadata.tables[name], properties
         
     kw = dict(useexisting=True)
 
     table = rdb.Table(
-        encode(iface),
+        name,
         metadata,
         rdb.Column('id', rdb.Integer, rdb.ForeignKey("soup.id"), primary_key=True),
         *columns,

Modified: z3c.dobbin/trunk/src/z3c/dobbin/relations.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/relations.py	2008-06-18 16:44:12 UTC (rev 87527)
+++ z3c.dobbin/trunk/src/z3c/dobbin/relations.py	2008-06-18 16:47:38 UTC (rev 87528)
@@ -18,7 +18,7 @@
 
     def _set_target(self, item):
         if not interfaces.IMapped.providedBy(item):
-            item = persist(item)
+            item = soup.persist(item)
 
         if item.id is None:
             session = Session()
@@ -41,7 +41,7 @@
 
     def set(kls, instance, item):
         if not interfaces.IMapped.providedBy(item):
-            item = persist(item)
+            item = soup.persist(item)
 
         if item.id is None:
             session = Session()

Modified: z3c.dobbin/trunk/src/z3c/dobbin/session.py
===================================================================
--- z3c.dobbin/trunk/src/z3c/dobbin/session.py	2008-06-18 16:44:12 UTC (rev 87527)
+++ z3c.dobbin/trunk/src/z3c/dobbin/session.py	2008-06-18 16:47:38 UTC (rev 87528)
@@ -5,7 +5,7 @@
 
 from ore.alchemist import Session
 
-import relations
+import soup
 
 class Savepoint:
     """Transaction savepoint."""
@@ -53,10 +53,10 @@
         del session._d_pending[uuid]
 
         # build instance
-        instance = relations.lookup(uuid)
+        instance = soup.lookup(uuid)
 
         # update attributes
-        relations.update(instance, obj)
+        soup.update(instance, obj)
         
     def tpc_vote(self, transaction):
         pass



More information about the Checkins mailing list