]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
restored "optimistic" behavior of hasparent. its generally disastrous without that...
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 5 Sep 2006 16:58:02 +0000 (16:58 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 5 Sep 2006 16:58:02 +0000 (16:58 +0000)
lib/sqlalchemy/attributes.py
lib/sqlalchemy/orm/mapper.py
test/base/attributes.py

index b29b03aa8f4111b31b10c841141659318c2ce48d..af2c908c44c594f2c7e5ceeed4c93f31285c5658 100644 (file)
@@ -33,8 +33,14 @@ class InstrumentedAttribute(object):
 
     def hasparent(self, item, optimistic=False):
         """return the boolean value of a "hasparent" flag attached to the given item.
+        
+        the 'optimistic' flag determines what the default return value should be if 
+        no "hasparent" flag can be located.  as this function is used to determine if 
+        an instance is an "orphan", instances that were loaded from storage should be assumed
+        to not be orphans, until a True/False value for this flag is set.  an instance attribute
+        that is loaded by a callable function will also not have a "hasparent" flag.
         """
-        return item._state.get(('hasparent', id(self)), False)
+        return item._state.get(('hasparent', id(self)), optimistic)
         
     def sethasparent(self, item, value):
         """sets a boolean flag on the given item corresponding to whether or not it is
@@ -486,12 +492,16 @@ class CommittedState(object):
         if value is not False:
             if attr.uselist:
                 self.data[attr.key] = [x for x in value]
-                if attr.trackparent:
-                    [attr.sethasparent(x, True) for x in self.data[attr.key] if x is not None]
+                # not tracking parent on lazy-loaded instances at the moment.
+                # its not needed since they will be "optimistically" tested
+                #if attr.trackparent:
+                #    [attr.sethasparent(x, True) for x in self.data[attr.key] if x is not None]
             else:
                 self.data[attr.key] = value
-                if attr.trackparent and value is not None:
-                    attr.sethasparent(value, True)
+                # not tracking parent on lazy-loaded instances at the moment.
+                # its not needed since they will be "optimistically" tested
+                #if attr.trackparent and value is not None:
+                #    attr.sethasparent(value, True)
 
     def rollback(self, manager, obj):
         for attr in manager.managed_attributes(obj.__class__):
index c7531eb8e7c22e3727066b773c213f0161ad54cb..fe0525b4acf591db99c6b95122fc30fa1922b2cf 100644 (file)
@@ -141,8 +141,9 @@ class Mapper(object):
         #self.compile()
     
     def _is_orphan(self, obj):
+        optimistic = has_identity(obj)
         for (key,klass) in self.delete_orphans:
-            if not getattr(klass, key).hasparent(obj):
+            if not getattr(klass, key).hasparent(obj, optimistic=optimistic):
                 if not has_identity(obj):
                     raise exceptions.FlushError("instance %s is an unsaved, pending instance and is an orphan" % obj)
                 return True
index abacd0ac960abd569edb527ca9dc383238953b22..d1c6978e127c15ea7bde086840cb34b17a187259 100644 (file)
@@ -182,13 +182,14 @@ class AttributesTest(PersistTest):
         Blog.posts.set_callable(b, lambda:[p1])
         Post.blog.set_callable(p1, lambda:b)
         manager.commit(p1, b)
+
+        # no orphans (called before the lazy loaders fire off)
+        assert getattr(Blog, 'posts').hasparent(p1, optimistic=True)
+        assert getattr(Post, 'blog').hasparent(b, optimistic=True)
+
         # assert connections
         assert p1.blog is b
         assert p1 in b.posts
-
-        # no orphans
-        assert getattr(Blog, 'posts').hasparent(p1)
-        assert getattr(Post, 'blog').hasparent(b)
         
         # manual connections
         b2 = Blog()