]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- added 'comparator' keyword argument to PickleType. By default, "mutable"
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 22 Sep 2007 15:55:02 +0000 (15:55 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 22 Sep 2007 15:55:02 +0000 (15:55 +0000)
  PickleType does a "deep compare" of objects using their dumps() representation.
  But this doesn't work for dictionaries.  Pickled objects which provide an
  adequate __eq__() implementation can be set up with "PickleType(comparator=operator.eq)"
  [ticket:560]

CHANGES
lib/sqlalchemy/types.py
test/orm/unitofwork.py

diff --git a/CHANGES b/CHANGES
index 00b01f4a362585030b7dd75530c4ee4f1ccc8a1b..c35978f42b7a47908a9062c5980ff522db54f3e6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -22,6 +22,12 @@ CHANGES
   insert/update statement compilation process in terms of the column names
   present but not the values for those columns.  Produces more consistent
   execute/executemany behavior, simplifies things a bit internally.
+- added 'comparator' keyword argument to PickleType.  By default, "mutable"
+  PickleType does a "deep compare" of objects using their dumps() representation.  
+  But this doesn't work for dictionaries.  Pickled objects which provide an 
+  adequate __eq__() implementation can be set up with "PickleType(comparator=operator.eq)"
+  [ticket:560]
   
 - Fixed reflection of the empty string for mysql enums.
 
index 833d2cf1595d88f7a483f46ff20145fa8ed92f0f..71b4bbec1bc651477da1143eddfcabac13be928d 100644 (file)
@@ -421,10 +421,11 @@ class Binary(TypeEngine):
 class PickleType(MutableType, TypeDecorator):
     impl = Binary
 
-    def __init__(self, protocol=pickle.HIGHEST_PROTOCOL, pickler=None, mutable=True):
+    def __init__(self, protocol=pickle.HIGHEST_PROTOCOL, pickler=None, mutable=True, comparator=None):
         self.protocol = protocol
         self.pickler = pickler or pickle
         self.mutable = mutable
+        self.comparator = comparator
         super(PickleType, self).__init__()
 
     def bind_processor(self, dialect):
@@ -455,7 +456,9 @@ class PickleType(MutableType, TypeDecorator):
             return value
 
     def compare_values(self, x, y):
-        if self.mutable:
+        if self.comparator:
+            return self.comparator(x, y)
+        elif self.mutable:
             return self.pickler.dumps(x, self.protocol) == self.pickler.dumps(y, self.protocol)
         else:
             return x is y
index c202abf99b8300de7a8091add5f893c1a73c6e88..b7bff2d787584b54dbe2ce96dc5129bd1301a5d1 100644 (file)
@@ -301,7 +301,6 @@ class MutableTypesTest(ORMTest):
             ),
         ])
         
-        
     def test_nocomparison(self):
         """test that types marked as MutableType get changes detected on them when the type has no __eq__ method"""
         class Foo(object):pass
@@ -352,7 +351,49 @@ class MutableTypesTest(ORMTest):
         def go():
             Session.commit()
         self.assert_sql_count(testbase.db, go, 0)
+
+class MutableTypesTest2(ORMTest):
+    def define_tables(self, metadata):
+        global table
+        import operator
+        table = Table('mutabletest', metadata,
+            Column('id', Integer, Sequence('mutableidseq', optional=True), primary_key=True),
+            Column('data', PickleType(comparator=operator.eq)),
+            )
+    
+    def test_dicts(self):
+        """dictionaries dont pickle the same way twice, sigh."""
+
+        class Foo(object):pass
+        mapper(Foo, table)
+        f1 = Foo()
+        f1.data = [{'personne': {'nom': u'Smith', 'pers_id': 1, 'prenom': u'john', 'civilite': u'Mr', \
+                    'int_3': False, 'int_2': False, 'int_1': u'23', 'VenSoir': True, 'str_1': u'Test', \
+                    'SamMidi': False, 'str_2': u'chien', 'DimMidi': False, 'SamSoir': True, 'SamAcc': False}}]
+
+        Session.commit()
+        def go():
+            Session.commit()
+        self.assert_sql_count(testbase.db, go, 0)
+
+        f1.data = [{'personne': {'nom': u'Smith', 'pers_id': 1, 'prenom': u'john', 'civilite': u'Mr', \
+                    'int_3': False, 'int_2': False, 'int_1': u'23', 'VenSoir': True, 'str_1': u'Test', \
+                    'SamMidi': False, 'str_2': u'chien', 'DimMidi': False, 'SamSoir': True, 'SamAcc': False}}]
+
+        def go():
+            Session.commit()
+        self.assert_sql_count(testbase.db, go, 0)
+
+        f1.data[0]['personne']['VenSoir']= False
+        def go():
+            Session.commit()
+        self.assert_sql_count(testbase.db, go, 1)
         
+        Session.clear()
+        f = Session.query(Foo).get(f1.id)
+        assert f.data == [{'personne': {'nom': u'Smith', 'pers_id': 1, 'prenom': u'john', 'civilite': u'Mr', \
+                    'int_3': False, 'int_2': False, 'int_1': u'23', 'VenSoir': False, 'str_1': u'Test', \
+                    'SamMidi': False, 'str_2': u'chien', 'DimMidi': False, 'SamSoir': True, 'SamAcc': False}}]
         
 class PKTest(ORMTest):
     def define_tables(self, metadata):