]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- added "mutable" flag to PickleType, set to False to allow old (faster) behavior
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 23 Sep 2006 21:02:33 +0000 (21:02 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 23 Sep 2006 21:02:33 +0000 (21:02 +0000)
- fix attribute unit test
- attributes have explicit flag for "mutable_scalars", propigated by ColumnProperty

lib/sqlalchemy/attributes.py
lib/sqlalchemy/orm/properties.py
lib/sqlalchemy/types.py
test/base/attributes.py

index 7fd9686e3568a181585974d4bdfefa3ff3146a9b..46c791bffa61ea705215389fc3500f53c60c03a5 100644 (file)
@@ -13,15 +13,15 @@ class InstrumentedAttribute(object):
     
     PASSIVE_NORESULT = object()
     
-    def __init__(self, manager, key, uselist, callable_, typecallable, trackparent=False, extension=None, copy_function=None, compare_function=None, **kwargs):
+    def __init__(self, manager, key, uselist, callable_, typecallable, trackparent=False, extension=None, copy_function=None, compare_function=None, mutable_scalars=False, **kwargs):
         self.manager = manager
         self.key = key
         self.uselist = uselist
         self.callable_ = callable_
         self.typecallable= typecallable
         self.trackparent = trackparent
+        self.mutable_scalars = mutable_scalars
         if copy_function is None:
-            self._check_mutable_modified = False
             if uselist:
                 self._copyfunc = lambda x: [y for y in x]
             else:
@@ -29,7 +29,6 @@ class InstrumentedAttribute(object):
                 # is passed
                 self._copyfunc = lambda x: x
         else:
-            self._check_mutable_modified = True
             self._copyfunc = copy_function
         if compare_function is None:
             self._compare_function = lambda x,y: x == y
@@ -52,7 +51,7 @@ class InstrumentedAttribute(object):
         return self._copyfunc(value)
     
     def check_mutable_modified(self, obj):
-        if self._check_mutable_modified:
+        if self.mutable_scalars:
             h = self.get_history(obj, passive=True)
             if h is not None and h.is_modified():
                 obj._state['modified'] = True
index c78593fcbaca99be365606ec720aae1ffeac82e6..d846b3396caed739d8e1fb503c788a76fb520570 100644 (file)
@@ -42,7 +42,7 @@ class ColumnProperty(mapper.MapperProperty):
         # establish a SmartProperty property manager on the object for this key
         if self.is_primary():
             #print "regiser col on class %s key %s" % (parent.class_.__name__, key)
-            sessionlib.attribute_manager.register_attribute(self.parent.class_, self.key, uselist=False, copy_function=lambda x: self.columns[0].type.copy_value(x), compare_function=lambda x,y:self.columns[0].type.compare_values(x,y))
+            sessionlib.attribute_manager.register_attribute(self.parent.class_, self.key, uselist=False, copy_function=lambda x: self.columns[0].type.copy_value(x), compare_function=lambda x,y:self.columns[0].type.compare_values(x,y), mutable_scalars=self.columns[0].type.is_mutable())
     def execute(self, session, instance, row, identitykey, imap, isnew):
         if isnew:
             #print "POPULATING OBJ", instance.__class__.__name__, "COL", self.columns[0]._label, "WITH DATA", row[self.columns[0]], "ROW IS A", row.__class__.__name__, "COL ID", id(self.columns[0])
@@ -69,7 +69,7 @@ class DeferredColumnProperty(ColumnProperty):
         # establish a SmartProperty property manager on the object for this key, 
         # containing a callable to load in the attribute
         if self.is_primary():
-            sessionlib.attribute_manager.register_attribute(self.parent.class_, self.key, uselist=False, callable_=lambda i:self.setup_loader(i), copy_function=lambda x: self.columns[0].type.copy_value(x), compare_function=lambda x,y:self.columns[0].type.compare_values(x,y))
+            sessionlib.attribute_manager.register_attribute(self.parent.class_, self.key, uselist=False, callable_=lambda i:self.setup_loader(i), copy_function=lambda x: self.columns[0].type.copy_value(x), compare_function=lambda x,y:self.columns[0].type.compare_values(x,y), mutable_scalars=self.columns[0].type.is_mutable())
     def setup_loader(self, instance):
         if not self.localparent.is_assigned(instance):
             return mapper.object_mapper(instance).props[self.key].setup_loader(instance)
index 5463c23968888936cea242711663b7d10eac86b3..47c9d73df8cccdc8c786df7d015cc68deececb33 100644 (file)
@@ -227,23 +227,30 @@ class Binary(TypeEngine):
 
 class PickleType(MutableType, TypeDecorator):
     impl = Binary
-    def __init__(self, protocol=pickle.HIGHEST_PROTOCOL, pickler=None):
-       self.protocol = protocol
-       self.pickler = pickler or pickle
-       super(PickleType, self).__init__()
+    def __init__(self, protocol=pickle.HIGHEST_PROTOCOL, pickler=None, mutable=True):
+        self.protocol = protocol
+        self.pickler = pickler or pickle
+        self.mutable = mutable
+        super(PickleType, self).__init__()
     def convert_result_value(self, value, dialect):
-      if value is None:
-          return None
-      buf = self.impl.convert_result_value(value, dialect)
-      return self.pickler.loads(str(buf))
+        if value is None:
+            return None
+        buf = self.impl.convert_result_value(value, dialect)
+        return self.pickler.loads(str(buf))
     def convert_bind_param(self, value, dialect):
-      if value is None:
-          return None
-      return self.impl.convert_bind_param(self.pickler.dumps(value, self.protocol), dialect)
+        if value is None:
+            return None
+        return self.impl.convert_bind_param(self.pickler.dumps(value, self.protocol), dialect)
     def copy_value(self, value):
-      return self.pickler.loads(self.pickler.dumps(value, self.protocol))
+        if self.mutable:
+            return self.pickler.loads(self.pickler.dumps(value, self.protocol))
+        else:
+            return value
     def compare_values(self, x, y):
-        return self.pickler.dumps(x, self.protocol) == self.pickler.dumps(y, self.protocol)
+        if self.mutable:
+            return self.pickler.dumps(x, self.protocol) == self.pickler.dumps(y, self.protocol)
+        else:
+            return x is y
         
 class Boolean(TypeEngine):
     pass
index ca3937a98c0c6d9f636277d175c5fbf8835ae255..c2facd52d38788f3cd29aa6bc0ccbd074a1a20eb 100644 (file)
@@ -294,11 +294,11 @@ class AttributesTest(PersistTest):
         b2.element = None
         assert not manager.get_history(b2, 'element').hasparent(f2)
 
-    def testaggressivediffs(self):
-        """test the 'double check for changes' behavior of check_modified"""
+    def testmutablescalars(self):
+        """test detection of changes on mutable scalar items"""
         class Foo(object):pass
         manager = attributes.AttributeManager()
-        manager.register_attribute(Foo, 'element', uselist=False, copy_function=lambda x:[y for y in x])
+        manager.register_attribute(Foo, 'element', uselist=False, copy_function=lambda x:[y for y in x], mutable_scalars=True)
         x = Foo()
         x.element = ['one', 'two', 'three']    
         manager.commit(x)