summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2007-12-20 02:37:48 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2007-12-20 02:37:48 +0000
commit2db36bf59c447d4d113cba0ae12f1b739c2ae923 (patch)
treef623c70981cccb85f02f0f0f0fc638da168fb3cf /lib/sqlalchemy
parent267523e4da6a6575fae507eabd003e975fc7094f (diff)
downloadsqlalchemy-2db36bf59c447d4d113cba0ae12f1b739c2ae923.tar.gz
- inheriting mappers now inherit the MapperExtensions of their parent
mapper directly, so that all methods for a particular MapperExtension are called for subclasses as well. As always, any MapperExtension can return either EXT_CONTINUE to continue extension processing or EXT_STOP to stop processing. The order of mapper resolution is: <extensions declared on the classes mapper> <extensions declared on the classes' parent mapper> <globally declared extensions>. Note that if you instantiate the same extension class separately and then apply it individually for two mappers in the same inheritance chain, the extension will be applied twice to the inheriting class, and each method will be called twice. To apply a mapper extension explicitly to each inheriting class but have each method called only once per operation, use the same instance of the extension for both mappers. [ticket:490]
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/orm/mapper.py57
1 files changed, 32 insertions, 25 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 2c3d3ea40..8c375ea39 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -153,8 +153,8 @@ class Mapper(object):
self.__should_log_debug = logging.is_debug_enabled(self.logger)
self._compile_class()
- self._compile_extensions()
self._compile_inheritance()
+ self._compile_extensions()
self._compile_tables()
self._compile_properties()
self._compile_pks()
@@ -281,12 +281,19 @@ class Mapper(object):
for ext_obj in util.to_list(extension):
# local MapperExtensions have already instrumented the class
extlist.add(ext_obj)
-
- for ext in global_extensions:
- if isinstance(ext, type):
- ext = ext()
- extlist.add(ext)
- ext.instrument_class(self, self.class_)
+
+ if self.inherits is not None:
+ for ext in self.inherits.extension:
+ if ext not in extlist:
+ extlist.add(ext)
+ ext.instrument_class(self, self.class_)
+ else:
+ for ext in global_extensions:
+ if isinstance(ext, type):
+ ext = ext()
+ if ext not in extlist:
+ extlist.add(ext)
+ ext.instrument_class(self, self.class_)
self.extension = ExtensionCarrier()
for ext in extlist:
@@ -960,14 +967,13 @@ class Mapper(object):
if not postupdate:
# call before_XXX extensions
for state, connection, has_identity in tups:
+ mapper = _state_mapper(state)
if not has_identity:
- for mapper in _state_mapper(state).iterate_to_root():
- if 'before_insert' in mapper.extension.methods:
- mapper.extension.before_insert(mapper, connection, state.obj())
+ if 'before_insert' in mapper.extension.methods:
+ mapper.extension.before_insert(mapper, connection, state.obj())
else:
- for mapper in _state_mapper(state).iterate_to_root():
- if 'before_update' in mapper.extension.methods:
- mapper.extension.before_update(mapper, connection, state.obj())
+ if 'before_update' in mapper.extension.methods:
+ mapper.extension.before_update(mapper, connection, state.obj())
for state, connection, has_identity in tups:
# detect if we have a "pending" instance (i.e. has no instance_key attached to it),
@@ -1131,13 +1137,14 @@ class Mapper(object):
if not postupdate:
# call after_XXX extensions
for state, connection in inserted_objects:
- for mapper in _state_mapper(state).iterate_to_root():
- if 'after_insert' in mapper.extension.methods:
- mapper.extension.after_insert(mapper, connection, state.obj())
+ 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 mapper in _state_mapper(state).iterate_to_root():
- if 'after_update' in mapper.extension.methods:
- mapper.extension.after_update(mapper, connection, state.obj())
+ mapper = _state_mapper(state)
+ 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
@@ -1177,9 +1184,9 @@ class Mapper(object):
tups = [(state, connection) for state in states]
for (state, connection) in tups:
- for mapper in _state_mapper(state).iterate_to_root():
- if 'before_delete' in mapper.extension.methods:
- mapper.extension.before_delete(mapper, connection, state.obj())
+ mapper = _state_mapper(state)
+ if 'before_delete' in mapper.extension.methods:
+ mapper.extension.before_delete(mapper, connection, state.obj())
deleted_objects = util.Set()
table_to_mapper = {}
@@ -1225,9 +1232,9 @@ class Mapper(object):
raise exceptions.ConcurrentModificationError("Deleted rowcount %d does not match number of objects deleted %d" % (c.rowcount, len(del_objects)))
for state, connection in deleted_objects:
- for mapper in _state_mapper(state).iterate_to_root():
- if 'after_delete' in mapper.extension.methods:
- mapper.extension.after_delete(mapper, connection, state.obj())
+ mapper = _state_mapper(state)
+ if 'after_delete' in mapper.extension.methods:
+ mapper.extension.after_delete(mapper, connection, state.obj())
def _register_dependencies(self, uowcommit):
"""Register ``DependencyProcessor`` instances with a