diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-01-22 03:55:48 +0000 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2009-01-22 03:55:48 +0000 |
| commit | 3954df86cb950aeb65444116c3e20f0a51647c10 (patch) | |
| tree | fed1ba8c150feede8f429833c1aa92fc916ebf7b /lib/sqlalchemy/orm | |
| parent | a7459fe1abaec1c4d6aca443e7b7e5f1d1e6db21 (diff) | |
| download | sqlalchemy-3954df86cb950aeb65444116c3e20f0a51647c10.tar.gz | |
- Adjusted the attribute instrumentation change from 0.5.1 to
fully establish instrumentation for subclasses where the mapper
was created after the superclass had already been fully
instrumented. [ticket:1292]
Diffstat (limited to 'lib/sqlalchemy/orm')
| -rw-r--r-- | lib/sqlalchemy/orm/dynamic.py | 3 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/interfaces.py | 40 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/mapper.py | 10 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/properties.py | 2 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 31 |
5 files changed, 54 insertions, 32 deletions
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py index a46734dde..0de5b98ff 100644 --- a/lib/sqlalchemy/orm/dynamic.py +++ b/lib/sqlalchemy/orm/dynamic.py @@ -22,10 +22,11 @@ from sqlalchemy.orm.util import _state_has_identity, has_identity class DynaLoader(strategies.AbstractRelationLoader): - def init_class_attribute(self): + def init_class_attribute(self, mapper): self.is_class_level = True strategies._register_attribute(self, + mapper, useobject=True, impl_class=DynamicAttributeImpl, target_mapper=self.parent_property.mapper, diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index 3e0fb94a4..6c3c3b1ba 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -395,23 +395,35 @@ class MapperProperty(object): def instrument_class(self, mapper): raise NotImplementedError() + _compile_started = False + _compile_finished = False + def init(self): - """Called after all mappers are compiled to assemble - relationships between mappers, establish instrumented class - attributes. + """Called after all mappers are created to assemble + relationships between mappers and perform other post-mapper-creation + initialization steps. + """ - - self._compiled = True + self._compile_started = True self.do_init() - + self._compile_finished = True + def do_init(self): - """Perform subclass-specific initialization steps. + """Perform subclass-specific initialization post-mapper-creation steps. This is a *template* method called by the - ``MapperProperty`` object's init() method.""" - + ``MapperProperty`` object's init() method. + + """ pass - + + def post_instrument_class(self, mapper): + """Perform instrumentation adjustments that need to occur + after init() has completed. + + """ + pass + def register_dependencies(self, *args, **kwargs): """Called by the ``Mapper`` in response to the UnitOfWork calling the ``Mapper``'s register_dependencies operation. @@ -573,9 +585,11 @@ class StrategizedProperty(MapperProperty): def do_init(self): self.__all_strategies = {} self.strategy = self.__init_strategy(self.strategy_class) - if self.is_primary(): - self.strategy.init_class_attribute() + def post_instrument_class(self, mapper): + if self.is_primary(): + self.strategy.init_class_attribute(mapper) + def build_path(entity, key, prev=None): if prev: return prev + (entity, key) @@ -810,7 +824,7 @@ class LoaderStrategy(object): def init(self): raise NotImplementedError("LoaderStrategy") - def init_class_attribute(self): + def init_class_attribute(self, mapper): pass def setup_query(self, context, entity, path, adapter, **kwargs): diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 6bcc89b3c..7cc6bad12 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -620,6 +620,7 @@ class Mapper(object): if init: prop.init() + prop.post_instrument_class(self) def compile(self): @@ -684,9 +685,14 @@ class Mapper(object): self._log("_post_configure_properties() started") l = [(key, prop) for key, prop in self._props.iteritems()] for key, prop in l: - if not getattr(prop, '_compiled', False): - self._log("initialize prop " + key) + self._log("initialize prop " + key) + + if not prop._compile_started: prop.init() + + if prop._compile_finished: + prop.post_instrument_class(self) + self._log("_post_configure_properties() complete") self.compiled = True diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 22806e364..f05613f5c 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -711,6 +711,7 @@ class RelationProperty(StrategizedProperty): self._determine_direction() self._determine_local_remote_pairs() self._post_init() + super(RelationProperty, self).do_init() def _get_target(self): if not hasattr(self, 'mapper'): @@ -998,7 +999,6 @@ class RelationProperty(StrategizedProperty): "added to the primary mapper, i.e. the very first " "mapper created for class '%s' " % (self.key, self.parent.class_.__name__, self.parent.class_.__name__)) - super(RelationProperty, self).do_init() def _refers_to_parent_table(self): return self.parent.mapped_table is self.target or self.parent.mapped_table is self.target diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 22ef7ded2..6edbd73d3 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -18,7 +18,7 @@ from sqlalchemy.orm.interfaces import ( from sqlalchemy.orm import session as sessionlib from sqlalchemy.orm import util as mapperutil -def _register_attribute(strategy, useobject, +def _register_attribute(strategy, mapper, useobject, compare_function=None, typecallable=None, copy_function=None, @@ -46,10 +46,10 @@ def _register_attribute(strategy, useobject, if useobject: attribute_ext.append(sessionlib.UOWEventHandler(prop.key)) - for mapper in prop.parent.polymorphic_iterator(): - if (mapper is prop.parent or not mapper.concrete) and mapper.has_property(prop.key): + for m in mapper.polymorphic_iterator(): + if (m is prop.parent or not m.concrete) and m.has_property(prop.key): attributes.register_attribute_impl( - mapper.class_, + m.class_, prop.key, parent_token=prop, mutable_scalars=mutable_scalars, @@ -98,12 +98,12 @@ class ColumnLoader(LoaderStrategy): c = adapter.columns[c] column_collection.append(c) - def init_class_attribute(self): + def init_class_attribute(self, mapper): self.is_class_level = True coltype = self.columns[0].type active_history = self.columns[0].primary_key # TODO: check all columns ? check for foreign Key as well? - _register_attribute(self, useobject=False, + _register_attribute(self, mapper, useobject=False, compare_function=coltype.compare_values, copy_function=coltype.copy_value, mutable_scalars=self.columns[0].type.is_mutable(), @@ -137,7 +137,7 @@ log.class_logger(ColumnLoader) class CompositeColumnLoader(ColumnLoader): """Strategize the loading of a composite column-based MapperProperty.""" - def init_class_attribute(self): + def init_class_attribute(self, mapper): self.is_class_level = True self.logger.info("%s register managed composite attribute" % self) @@ -158,7 +158,7 @@ class CompositeColumnLoader(ColumnLoader): else: return True - _register_attribute(self, useobject=False, + _register_attribute(self, mapper, useobject=False, compare_function=compare, copy_function=copy, mutable_scalars=True @@ -220,10 +220,10 @@ class DeferredColumnLoader(LoaderStrategy): self.columns = self.parent_property.columns self.group = self.parent_property.group - def init_class_attribute(self): + def init_class_attribute(self, mapper): self.is_class_level = True - _register_attribute(self, useobject=False, + _register_attribute(self, mapper, useobject=False, compare_function=self.columns[0].type.compare_values, copy_function=self.columns[0].type.copy_value, mutable_scalars=self.columns[0].type.is_mutable(), @@ -335,10 +335,10 @@ class AbstractRelationLoader(LoaderStrategy): class NoLoader(AbstractRelationLoader): """Strategize a relation() that doesn't load data automatically.""" - def init_class_attribute(self): + def init_class_attribute(self, mapper): self.is_class_level = True - _register_attribute(self, + _register_attribute(self, mapper, useobject=True, uselist=self.parent_property.uselist, typecallable = self.parent_property.collection_class, @@ -372,11 +372,12 @@ class LazyLoader(AbstractRelationLoader): if self.use_get: self.logger.info("%s will use query.get() to optimize instance loads" % self) - def init_class_attribute(self): + def init_class_attribute(self, mapper): self.is_class_level = True _register_attribute(self, + mapper, useobject=True, callable_=self.class_level_loader, uselist = self.parent_property.uselist, @@ -600,8 +601,8 @@ class EagerLoader(AbstractRelationLoader): super(EagerLoader, self).init() self.join_depth = self.parent_property.join_depth - def init_class_attribute(self): - self.parent_property._get_strategy(LazyLoader).init_class_attribute() + def init_class_attribute(self, mapper): + self.parent_property._get_strategy(LazyLoader).init_class_attribute(mapper) def setup_query(self, context, entity, path, adapter, column_collection=None, parentmapper=None, **kwargs): """Add a left outer join to the statement thats being constructed.""" |
