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.
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
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
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()
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()
.. 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.
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):
def has_state(self, instance):
try:
- state = self._get_state(instance)
+ self._get_state(instance)
except orm_exc.NO_STATE:
return False
else:
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()
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)
+
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")
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,
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()
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.
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
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
"""
include_removes = kw.pop('include_removes', False)
+
def wrap(fn):
fn.__sa_validators__ = names
fn.__sa_include_removes__ = include_removes
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,\
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()