From dc94cb7b10927b412b813dc9493532c149816658 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Sat, 29 Dec 2007 18:33:27 +0000 Subject: [PATCH] - MapperExtension.before_update() and after_update() are now called symmetrically; previously, an instance that had no modified column attributes (but had a relation() modification) could be called with before_update() but not after_update() [ticket:907] --- CHANGES | 5 +++++ lib/sqlalchemy/orm/mapper.py | 15 +++++++-------- test/orm/mapper.py | 22 ++++++++++++++++++++++ 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/CHANGES b/CHANGES index 2e4c88642b..8f379be1a7 100644 --- a/CHANGES +++ b/CHANGES @@ -100,6 +100,11 @@ CHANGES instance of the extension for both mappers. [ticket:490] + - MapperExtension.before_update() and after_update() are now called + symmetrically; previously, an instance that had no modified column + attributes (but had a relation() modification) could be called with + before_update() but not after_update() [ticket:907] + - columns which are missing from a Query's select statement now get automatically deferred during load. diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index dca3c97b1b..bec5d5c6ee 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1125,15 +1125,14 @@ class Mapper(object): if not postupdate: # call after_XXX extensions - for state, connection in inserted_objects: - mapper = _state_mapper(state) - if 'after_insert' in mapper.extension.methods: - mapper.extension.after_insert(mapper, connection, state.obj()) - - for state, connection in updated_objects: + for state, connection, has_identity in tups: mapper = _state_mapper(state) - if 'after_update' in mapper.extension.methods: - mapper.extension.after_update(mapper, connection, state.obj()) + if not has_identity: + if 'after_insert' in mapper.extension.methods: + mapper.extension.after_insert(mapper, connection, state.obj()) + else: + if 'after_update' in mapper.extension.methods: + mapper.extension.after_update(mapper, connection, state.obj()) def _postfetch(self, connection, table, state, resultproxy, params, value_params): """After an ``INSERT`` or ``UPDATE``, assemble newly generated diff --git a/test/orm/mapper.py b/test/orm/mapper.py index a7cb3a57d3..e1aca13457 100644 --- a/test/orm/mapper.py +++ b/test/orm/mapper.py @@ -1237,6 +1237,28 @@ class MapperExtensionTest(PersistTest): self.assertEquals(methods, ['before_insert', 'after_insert', 'load', 'translate_row', 'populate_instance', 'get', 'translate_row', 'create_instance', 'populate_instance', 'before_update', 'after_update', 'before_delete', 'after_delete']) + def test_after_with_no_changes(self): + # test that after_update is called even if no cols were updated + + mapper(Item, orderitems, extension=Ext() , properties={ + 'keywords':relation(Keyword, secondary=itemkeywords) + }) + mapper(Keyword, keywords, extension=Ext() ) + + sess = create_session() + i1 = Item() + k1 = Keyword('blue') + sess.save(i1) + sess.save(k1) + sess.flush() + self.assertEquals(methods, ['before_insert', 'after_insert', 'before_insert', 'after_insert']) + + methods[:] = [] + i1.keywords.append(k1) + sess.flush() + self.assertEquals(methods, ['before_update', 'after_update']) + + def test_inheritance_with_dupes(self): # test using inheritance, same extension on both mappers class AdminUser(User): -- 2.47.3