]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- move load_scalar_attributes out to loading.py
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 14 Jul 2012 15:51:11 +0000 (11:51 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 14 Jul 2012 15:51:11 +0000 (11:51 -0400)
lib/sqlalchemy/ext/instrumentation.py
lib/sqlalchemy/orm/loading.py
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/state.py

index c42cf6ec9b3cd8932bf1334f33496a73a9185160..f840ad066fd4814237c355697f1c513008051df7 100644 (file)
@@ -2,7 +2,7 @@
 
 The :mod:`sqlalchemy.ext.instrumentation` package provides for alternate
 systems of class instrumentation within the ORM.  Class instrumentation
-refers to how the ORM places attributes on the class which maintain 
+refers to how the ORM places attributes on the class which maintain
 data and track changes to that data, as well as event hooks installed
 on the class.
 
@@ -11,24 +11,24 @@ on the class.
     with other object management packages, which already perform
     their own instrumentation.  It is not intended for general use.
 
-For examples of how the instrumentation extension is used, 
+For examples of how the instrumentation extension is used,
 see the example :ref:`examples_instrumentation`.
 
 .. versionchanged:: 0.8
-   The :mod:`sqlalchemy.orm.instrumentation` was split out so 
+   The :mod:`sqlalchemy.orm.instrumentation` was split out so
    that all functionality having to do with non-standard
    instrumentation was moved out to :mod:`sqlalchemy.ext.instrumentation`.
    When imported, the module installs itself within
    :mod:`sqlalchemy.orm.instrumentation` so that it
-   takes effect, including recognition of 
-   ``__sa_instrumentation_manager__`` on mapped classes, as 
-   well :attr:`.instrumentation_finders` 
+   takes effect, including recognition of
+   ``__sa_instrumentation_manager__`` on mapped classes, as
+   well :attr:`.instrumentation_finders`
    being used to determine class instrumentation resolution.
-   
+
 """
 from ..orm import instrumentation as orm_instrumentation
 from ..orm.instrumentation import (
-    ClassManager, InstrumentationFactory, _default_state_getter, 
+    ClassManager, InstrumentationFactory, _default_state_getter,
     _default_dict_getter, _default_manager_getter
 )
 from ..orm import attributes, collections
@@ -66,9 +66,10 @@ def find_native_user_instrumentation_hook(cls):
     return getattr(cls, INSTRUMENTATION_MANAGER, None)
 
 instrumentation_finders = [find_native_user_instrumentation_hook]
-"""An extensible sequence of callables which return instrumentation implementations
+"""An extensible sequence of callables which return instrumentation
+implementations
 
-When a class is registered, each callable will be passed a class object.  
+When a class is registered, each callable will be passed a class object.
 If None is returned, the
 next finder in the sequence is consulted.  Otherwise the return must be an
 instrumentation factory that follows the same guidelines as
@@ -82,9 +83,9 @@ ClassManager instrumentation is used.
 
 class ExtendedInstrumentationRegistry(InstrumentationFactory):
     """Extends :class:`.InstrumentationFactory` with additional
-    bookkeeping, to accommodate multiple types of 
+    bookkeeping, to accommodate multiple types of
     class managers.
-    
+
     """
     _manager_finders = weakref.WeakKeyDictionary()
     _state_finders = weakref.WeakKeyDictionary()
@@ -116,7 +117,7 @@ class ExtendedInstrumentationRegistry(InstrumentationFactory):
 
         if factory != ClassManager and not self._extended:
             # somebody invoked a custom ClassManager.
-            # reinstall global "getter" functions with the more 
+            # reinstall global "getter" functions with the more
             # expensive ones.
             self._extended = True
             _install_instrumented_lookups()
@@ -196,9 +197,9 @@ class InstrumentationManager(object):
 
     .. versionchanged:: 0.8
        :class:`.InstrumentationManager` was moved from
-       :mod:`sqlalchemy.orm.instrumentation` to 
-       :mod:`sqlalchemy.ext.instrumentation`.   
-       
+       :mod:`sqlalchemy.orm.instrumentation` to
+       :mod:`sqlalchemy.ext.instrumentation`.
+
     """
 
     # r4361 added a mandatory (cls) constructor to this interface.
@@ -307,7 +308,7 @@ class _ClassInstrumentationAdapter(ClassManager):
         if delegate:
             return delegate(key, state, factory)
         else:
-            return ClassManager.initialize_collection(self, key, 
+            return ClassManager.initialize_collection(self, key,
                                                         state, factory)
 
     def new_instance(self, state=None):
@@ -340,7 +341,7 @@ class _ClassInstrumentationAdapter(ClassManager):
 
     def has_state(self, instance):
         try:
-            state = self._get_state(instance)
+            self._get_state(instance)
         except orm_exc.NO_STATE:
             return False
         else:
index 987d47ceade07893b3ea8140192d6b1215abba90..41b82d8d1afd9480d525562b716fd67d615bf434 100644 (file)
@@ -18,6 +18,8 @@ from . import attributes, exc as orm_exc, state as statelib
 from .interfaces import EXT_CONTINUE
 from ..sql import util as sql_util
 from .util import _none_set, state_str
+from .. import exc as sa_exc
+sessionlib = util.importlater("sqlalchemy.orm", "session")
 
 _new_runid = util.counter()
 
@@ -534,3 +536,66 @@ def _configure_subclass_mapper(mapper, context, path, adapter):
                             adapter,
                             polymorphic_from=mapper)
     return configure_subclass_mapper
+
+def load_scalar_attributes(mapper, state, attribute_names):
+    """initiate a column-based attribute refresh operation."""
+
+    #assert mapper is _state_mapper(state)
+    session = sessionlib._state_session(state)
+    if not session:
+        raise orm_exc.DetachedInstanceError(
+                    "Instance %s is not bound to a Session; "
+                    "attribute refresh operation cannot proceed" %
+                    (state_str(state)))
+
+    has_key = bool(state.key)
+
+    result = False
+
+    if mapper.inherits and not mapper.concrete:
+        statement = mapper._optimized_get_statement(state, attribute_names)
+        if statement is not None:
+            result = load_on_ident(
+                        session.query(mapper).from_statement(statement),
+                            None,
+                            only_load_props=attribute_names,
+                            refresh_state=state
+                        )
+
+    if result is False:
+        if has_key:
+            identity_key = state.key
+        else:
+            # this codepath is rare - only valid when inside a flush, and the
+            # object is becoming persistent but hasn't yet been assigned
+            # an identity_key.
+            # check here to ensure we have the attrs we need.
+            pk_attrs = [mapper._columntoproperty[col].key
+                        for col in mapper.primary_key]
+            if state.expired_attributes.intersection(pk_attrs):
+                raise sa_exc.InvalidRequestError(
+                            "Instance %s cannot be refreshed - it's not "
+                            " persistent and does not "
+                            "contain a full primary key." % state_str(state))
+            identity_key = mapper._identity_key_from_state(state)
+
+        if (_none_set.issubset(identity_key) and \
+                not mapper.allow_partial_pks) or \
+                _none_set.issuperset(identity_key):
+            util.warn("Instance %s to be refreshed doesn't "
+                        "contain a full primary key - can't be refreshed "
+                        "(and shouldn't be expired, either)."
+                        % state_str(state))
+            return
+
+        result = load_on_ident(
+                    session.query(mapper),
+                                identity_key,
+                                refresh_state=state,
+                                only_load_props=attribute_names)
+
+    # if instance is pending, a refresh operation
+    # may not complete (even if PK attributes are assigned)
+    if has_key and result is None:
+        raise orm_exc.ObjectDeletedError(state)
+
index dceccf70f837612b0f12a81a95e6286f6276f39a..3339564076b20fc860a9e5f7ed979097d955d508 100644 (file)
@@ -16,22 +16,19 @@ available in :class:`~sqlalchemy.orm.`.
 from __future__ import absolute_import
 import types
 import weakref
-import operator
-from itertools import chain, groupby
+from itertools import chain
 from collections import deque
 
 from .. import sql, util, log, exc as sa_exc, event, schema
 from ..sql import expression, visitors, operators, util as sql_util
-from . import instrumentation, attributes, sync, \
+from . import instrumentation, attributes, \
                         exc as orm_exc, unitofwork, events, loading
-from .interfaces import MapperProperty, EXT_CONTINUE, \
-                                PropComparator
+from .interfaces import MapperProperty
 
 from .util import _INSTRUMENTOR, _class_to_mapper, \
-     _state_mapper, class_mapper, instance_str, state_str,\
-     PathRegistry, _none_set
+     _state_mapper, class_mapper, \
+     PathRegistry
 import sys
-sessionlib = util.importlater("sqlalchemy.orm", "session")
 properties = util.importlater("sqlalchemy.orm", "properties")
 descriptor_props = util.importlater("sqlalchemy.orm", "descriptor_props")
 
@@ -68,17 +65,17 @@ class Mapper(object):
     def __init__(self,
                  class_,
                  local_table,
-                 properties = None,
-                 primary_key = None,
-                 non_primary = False,
-                 inherits = None,
-                 inherit_condition = None,
-                 inherit_foreign_keys = None,
-                 extension = None,
-                 order_by = False,
-                 always_refresh = False,
-                 version_id_col = None,
-                 version_id_generator = None,
+                 properties=None,
+                 primary_key=None,
+                 non_primary=False,
+                 inherits=None,
+                 inherit_condition=None,
+                 inherit_foreign_keys=None,
+                 extension=None,
+                 order_by=False,
+                 always_refresh=False,
+                 version_id_col=None,
+                 version_id_generator=None,
                  polymorphic_on=None,
                  _polymorphic_map=None,
                  polymorphic_identity=None,
@@ -182,8 +179,8 @@ class Mapper(object):
         self.configured = False
 
         # prevent this mapper from being constructed
-        # while a configure_mappers() is occurring (and defer a configure_mappers()
-        # until construction succeeds)
+        # while a configure_mappers() is occurring (and defer a
+        # configure_mappers() until construction succeeds)
         _COMPILE_MUTEX.acquire()
         try:
             self._configure_inheritance()
@@ -659,7 +656,8 @@ class Mapper(object):
         self.class_manager = manager
 
         manager.mapper = self
-        manager.deferred_scalar_loader = self._load_scalar_attributes
+        manager.deferred_scalar_loader = util.partial(
+                            loading.load_scalar_attributes, self)
 
         # The remaining members can be added by any mapper,
         # e_name None or not.
@@ -676,10 +674,11 @@ class Mapper(object):
                     self._reconstructor = method
                     event.listen(manager, 'load', _event_on_load, raw=True)
                 elif hasattr(method, '__sa_validators__'):
-                    include_removes = getattr(method, "__sa_include_removes__", False)
+                    include_removes = getattr(method,
+                                            "__sa_include_removes__", False)
                     for name in method.__sa_validators__:
                         self.validators = self.validators.union(
-                            {name : (method, include_removes)}
+                            {name: (method, include_removes)}
                         )
 
         manager.info[_INSTRUMENTOR] = self
@@ -1678,65 +1677,6 @@ class Mapper(object):
         return state.manager[prop.key].impl.\
                     get_committed_value(state, dict_, passive=passive)
 
-    def _load_scalar_attributes(self, state, attribute_names):
-        """initiate a column-based attribute refresh operation."""
-
-        #assert mapper is _state_mapper(state)
-        session = sessionlib._state_session(state)
-        if not session:
-            raise orm_exc.DetachedInstanceError(
-                        "Instance %s is not bound to a Session; "
-                        "attribute refresh operation cannot proceed" %
-                        (state_str(state)))
-
-        has_key = bool(state.key)
-
-        result = False
-
-        if self.inherits and not self.concrete:
-            statement = self._optimized_get_statement(state, attribute_names)
-            if statement is not None:
-                result = loading.load_on_ident(
-                            session.query(self).from_statement(statement),
-                                None,
-                                only_load_props=attribute_names,
-                                refresh_state=state
-                            )
-
-        if result is False:
-            if has_key:
-                identity_key = state.key
-            else:
-                # this codepath is rare - only valid when inside a flush, and the
-                # object is becoming persistent but hasn't yet been assigned an identity_key.
-                # check here to ensure we have the attrs we need.
-                pk_attrs = [self._columntoproperty[col].key
-                            for col in self.primary_key]
-                if state.expired_attributes.intersection(pk_attrs):
-                    raise sa_exc.InvalidRequestError("Instance %s cannot be refreshed - it's not "
-                                                    " persistent and does not "
-                                                    "contain a full primary key." % state_str(state))
-                identity_key = self._identity_key_from_state(state)
-
-            if (_none_set.issubset(identity_key) and \
-                    not self.allow_partial_pks) or \
-                    _none_set.issuperset(identity_key):
-                util.warn("Instance %s to be refreshed doesn't "
-                            "contain a full primary key - can't be refreshed "
-                            "(and shouldn't be expired, either)."
-                            % state_str(state))
-                return
-
-            result = loading.load_on_ident(
-                        session.query(self),
-                                    identity_key,
-                                    refresh_state=state,
-                                    only_load_props=attribute_names)
-
-        # if instance is pending, a refresh operation
-        # may not complete (even if PK attributes are assigned)
-        if has_key and result is None:
-            raise orm_exc.ObjectDeletedError(state)
 
     def _optimized_get_statement(self, state, attribute_names):
         """assemble a WHERE clause which retrieves a given state by primary
@@ -2052,6 +1992,7 @@ def validates(*names, **kw):
 
     """
     include_removes = kw.pop('include_removes', False)
+
     def wrap(fn):
         fn.__sa_validators__ = names
         fn.__sa_include_removes__ = include_removes
index 557eeb13382baf0f8925c77f04f7864bf63f38a6..ea0e89caf0ed00baf0f5caadae8e27c69dcd9a63 100644 (file)
@@ -13,7 +13,7 @@ defines a large part of the ORM's interactivity.
 
 import weakref
 from .. import util
-from . import exc as orm_exc, attributes,util as orm_util
+from . import exc as orm_exc, attributes, util as orm_util
 from .attributes import (
     PASSIVE_NO_RESULT,
     SQL_OK, NEVER_SET, ATTR_WAS_SET, NO_VALUE,\
@@ -198,8 +198,10 @@ class InstanceState(object):
         if manager is None:
             raise orm_exc.UnmappedInstanceError(
                         inst,
-                        "Cannot deserialize object of type %r - no mapper() has"
-                        " been configured for this class within the current Python process!" %
+                        "Cannot deserialize object of type %r - "
+                        "no mapper() has "
+                        "been configured for this class within the current "
+                        "Python process!" %
                         self.class_)
         elif manager.is_mapped and not manager.mapper.configured:
             mapperlib.configure_mappers()