Commits

Mike Bayer committed 2de43a8

- Generalized the IdentityManagedState._instance_dict() callable
to the IdentityMap class so that Weak/StrongInstanceDict both
have the same behavior wrt the state referencing the map
- Fixed bug when using weak_instance_map=False where modified
events would not be intercepted for a flush(). [ticket:1272]

Comments (0)

Files changed (3)

       next compile() call.  This issue occurs frequently
       when using declarative.
 
+    - Fixed bug when using weak_instance_map=False where modified
+      events would not be intercepted for a flush(). [ticket:1272]
+      
     - Fixed some deep "column correspondence" issues which could
       impact a Query made against a selectable containing
       multiple versions of the same table, as well as 

lib/sqlalchemy/orm/identity.py

     def __init__(self):
         self._mutable_attrs = {}
         self.modified = False
+        self._wr = weakref.ref(self)
         
     def add(self, state):
         raise NotImplementedError()
         raise NotImplementedError("IdentityMap uses remove() to remove data")
         
     def _manage_incoming_state(self, state):
+        state._instance_dict = self._wr
+        
         if state.modified:  
             self.modified = True
         if state.manager.mutable_attributes:
             self._mutable_attrs[state] = True
     
     def _manage_removed_state(self, state):
+        del state._instance_dict
+        
         if state in self._mutable_attrs:
             del self._mutable_attrs[state]
             
         
 class WeakInstanceDict(IdentityMap):
 
-    def __init__(self):
-        IdentityMap.__init__(self)
-        self._wr = weakref.ref(self)
-
     def __getitem__(self, key):
         state = dict.__getitem__(self, key)
         o = state.obj()
                 raise AssertionError("A conflicting state is already present in the identity map for key %r" % state.key)
         else:
             dict.__setitem__(self, state.key, state)
-            state._instance_dict = self._wr
             self._manage_incoming_state(state)
     
     def remove_key(self, key):
     def remove(self, state):
         if dict.pop(self, state.key) is not state:
             raise AssertionError("State %s is not present in this identity map" % state)
-        del state._instance_dict
         self._manage_removed_state(state)
     
     def discard(self, state):
         if self.contains_state(state):
             dict.__delitem__(self, state.key)
-            del state._instance_dict
             self._manage_removed_state(state)
         
     def get(self, key, default=None):

test/orm/session.py

         gc.collect()
         assert len(s.identity_map) == 1
 
+        user = s.query(User).one()
+        assert not s.identity_map.modified
+        user.name = 'u2'
+        assert s.identity_map.modified
+        s.flush()
+        assert users.select().execute().fetchall() == [(1, 'u2')]
+        
+        
     @testing.resolve_artifact_names
     def test_prune(self):
         s = create_session(weak_identity_map=False)