summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2009-01-22 03:55:48 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2009-01-22 03:55:48 +0000
commit3954df86cb950aeb65444116c3e20f0a51647c10 (patch)
treefed1ba8c150feede8f429833c1aa92fc916ebf7b /lib/sqlalchemy/orm
parenta7459fe1abaec1c4d6aca443e7b7e5f1d1e6db21 (diff)
downloadsqlalchemy-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.py3
-rw-r--r--lib/sqlalchemy/orm/interfaces.py40
-rw-r--r--lib/sqlalchemy/orm/mapper.py10
-rw-r--r--lib/sqlalchemy/orm/properties.py2
-rw-r--r--lib/sqlalchemy/orm/strategies.py31
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."""