From: Mike Bayer Date: Sun, 30 Mar 2008 16:03:23 +0000 (+0000) Subject: - rearranged LoaderStrategies a bit X-Git-Tag: rel_0_4_5~48 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0f0b9552fb4523b1c373492495b2bb72478514b5;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - rearranged LoaderStrategies a bit - removed awareness of "dynamic" from attributes and replaced with "impl_class" - moved DynaLoader into dynamic.py - removed create_strategy() method from StrategizedProperty; they set up 'strategy_class' so that StrategizedProperty treats the default the same as the optional loaders --- diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py index 39eb40daa2..a12ac6518f 100644 --- a/lib/sqlalchemy/orm/__init__.py +++ b/lib/sqlalchemy/orm/__init__.py @@ -287,7 +287,7 @@ def dynamic_loader(argument, secondary=None, primaryjoin=None, secondaryjoin=Non A subset of arguments available to relation() are available here. """ - from sqlalchemy.orm.strategies import DynaLoader + from sqlalchemy.orm.dynamic import DynaLoader return PropertyLoader(argument, secondary=secondary, primaryjoin=primaryjoin, secondaryjoin=secondaryjoin, entity_name=entity_name, foreign_keys=foreign_keys, backref=backref, diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index b0c2ac8261..5d2b21ddd0 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -1169,10 +1169,9 @@ def get_as_list(state, key, passive=False): def has_parent(class_, instance, key, optimistic=False): return getattr(class_, key).impl.hasparent(instance._state, optimistic=optimistic) -def _create_prop(class_, key, uselist, callable_, typecallable, useobject, mutable_scalars, **kwargs): - if kwargs.pop('dynamic', False): - from sqlalchemy.orm import dynamic - return dynamic.DynamicAttributeImpl(class_, key, typecallable, **kwargs) +def _create_prop(class_, key, uselist, callable_, typecallable, useobject, mutable_scalars, impl_class, **kwargs): + if impl_class: + return impl_class(class_, key, typecallable, **kwargs) elif uselist: return CollectionAttributeImpl(class_, key, callable_, typecallable, **kwargs) elif useobject: @@ -1272,7 +1271,7 @@ def unregister_class(class_): delattr(class_, attr.impl.key) delattr(class_, '_class_state') -def register_attribute(class_, key, uselist, useobject, callable_=None, proxy_property=None, mutable_scalars=False, **kwargs): +def register_attribute(class_, key, uselist, useobject, callable_=None, proxy_property=None, mutable_scalars=False, impl_class=None, **kwargs): _init_class_state(class_) typecallable = kwargs.pop('typecallable', None) @@ -1291,7 +1290,7 @@ def register_attribute(class_, key, uselist, useobject, callable_=None, proxy_pr inst = proxy_type(key, proxy_property, comparator) else: inst = InstrumentedAttribute(_create_prop(class_, key, uselist, callable_, useobject=useobject, - typecallable=typecallable, mutable_scalars=mutable_scalars, **kwargs), comparator=comparator) + typecallable=typecallable, mutable_scalars=mutable_scalars, impl_class=impl_class, **kwargs), comparator=comparator) setattr(class_, key, inst) class_._class_state.attrs[key] = inst diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py index 09de60db2d..133ad99c89 100644 --- a/lib/sqlalchemy/orm/dynamic.py +++ b/lib/sqlalchemy/orm/dynamic.py @@ -1,22 +1,34 @@ """'dynamic' collection API. returns Query() objects on the 'read' side, alters a special AttributeHistory on the 'write' side.""" -from sqlalchemy import exceptions, util -from sqlalchemy.orm import attributes, object_session, util as mapperutil +from sqlalchemy import exceptions, util, logging +from sqlalchemy.orm import attributes, object_session, util as mapperutil, strategies from sqlalchemy.orm.query import Query from sqlalchemy.orm.mapper import has_identity, object_mapper + +class DynaLoader(strategies.AbstractRelationLoader): + def init_class_attribute(self): + self.is_class_level = True + self._register_attribute(self.parent.class_, impl_class=DynamicAttributeImpl, target_mapper=self.parent_property.mapper, order_by=self.parent_property.order_by) + + def create_row_processor(self, selectcontext, mapper, row): + return (None, None, None) + +DynaLoader.logger = logging.class_logger(DynaLoader) + class DynamicAttributeImpl(attributes.AttributeImpl): def __init__(self, class_, key, typecallable, target_mapper, order_by, **kwargs): super(DynamicAttributeImpl, self).__init__(class_, key, typecallable, **kwargs) self.target_mapper = target_mapper self.order_by=order_by + self.query_class = AppenderQuery def get(self, state, passive=False): if passive: return self._get_collection_history(state, passive=True).added_items else: - return AppenderQuery(self, state) + return self.query_class(self, state) def get_collection(self, state, user_data=None, passive=True): if passive: diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py index 010a8002ae..c43bae6c08 100644 --- a/lib/sqlalchemy/orm/interfaces.py +++ b/lib/sqlalchemy/orm/interfaces.py @@ -529,9 +529,7 @@ class StrategizedProperty(MapperProperty): def do_init(self): self._all_strategies = {} - self.strategy = self.create_strategy() - self._all_strategies[self.strategy.__class__] = self.strategy - self.strategy.init() + self.strategy = self._get_strategy(self.strategy_class) if self.is_primary(): self.strategy.init_class_attribute() diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index 15546d7e8b..970e49ea4d 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -39,17 +39,15 @@ class ColumnProperty(StrategizedProperty): self.group = kwargs.pop('group', None) self.deferred = kwargs.pop('deferred', False) self.comparator = ColumnProperty.ColumnComparator(self) + if self.deferred: + self.strategy_class = strategies.DeferredColumnLoader + else: + self.strategy_class = strategies.ColumnLoader # sanity check for col in columns: if not isinstance(col, ColumnElement): raise ArgumentError('column_property() must be given a ColumnElement as its argument. Try .label() or .as_scalar() for Selectables to fix this.') - def create_strategy(self): - if self.deferred: - return strategies.DeferredColumnLoader(self) - else: - return strategies.ColumnLoader(self) - def do_init(self): super(ColumnProperty, self).do_init() if len(self.columns) > 1 and self.parent.primary_key.issuperset(self.columns): @@ -235,7 +233,19 @@ class PropertyLoader(StrategizedProperty): self.enable_typechecks = enable_typechecks self.comparator = PropertyLoader.Comparator(self) self.join_depth = join_depth - self.strategy_class = strategy_class + + if strategy_class: + self.strategy_class = strategy_class + elif self.lazy == 'dynamic': + from sqlalchemy.orm import dynamic + self.strategy_class = dynamic.DynaLoader + elif self.lazy is False: + self.strategy_class = strategies.EagerLoader + elif self.lazy is None: + self.strategy_class = strategies.NoLoader + else: + self.strategy_class = strategies.LazyLoader + self._reverse_property = None if cascade is not None: @@ -398,18 +408,6 @@ class PropertyLoader(StrategizedProperty): return self.cascade.delete_orphan private = property(private) - def create_strategy(self): - if self.strategy_class: - return self.strategy_class(self) - elif self.lazy == 'dynamic': - return strategies.DynaLoader(self) - elif self.lazy: - return strategies.LazyLoader(self) - elif self.lazy is False: - return strategies.EagerLoader(self) - elif self.lazy is None: - return strategies.NoLoader(self) - def __str__(self): return str(self.parent.class_.__name__) + "." + self.key + " (" + str(self.mapper.class_.__name__) + ")" diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index 57237e08f5..e591145774 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -237,16 +237,6 @@ class AbstractRelationLoader(LoaderStrategy): self.logger.info("register managed %s attribute %s on class %s" % ((self.uselist and "list-holding" or "scalar"), self.key, self.parent.class_.__name__)) sessionlib.register_attribute(class_, self.key, uselist=self.uselist, useobject=True, extension=self.attributeext, cascade=self.cascade, trackparent=True, typecallable=self.parent_property.collection_class, callable_=callable_, comparator=self.parent_property.comparator, **kwargs) -class DynaLoader(AbstractRelationLoader): - def init_class_attribute(self): - self.is_class_level = True - self._register_attribute(self.parent.class_, dynamic=True, target_mapper=self.parent_property.mapper, order_by=self.parent_property.order_by) - - def create_row_processor(self, selectcontext, mapper, row): - return (None, None, None) - -DynaLoader.logger = logging.class_logger(DynaLoader) - class NoLoader(AbstractRelationLoader): def init_class_attribute(self): self.is_class_level = True