summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-01-06 01:14:26 -0500
committermike bayer <mike_mp@zzzcomputing.com>2019-01-06 17:34:50 +0000
commit1e1a38e7801f410f244e4bbb44ec795ae152e04e (patch)
tree28e725c5c8188bd0cfd133d1e268dbca9b524978 /lib/sqlalchemy/orm
parent404e69426b05a82d905cbb3ad33adafccddb00dd (diff)
downloadsqlalchemy-1e1a38e7801f410f244e4bbb44ec795ae152e04e.tar.gz
Run black -l 79 against all source files
This is a straight reformat run using black as is, with no edits applied at all. The black run will format code consistently, however in some cases that are prevalent in SQLAlchemy code it produces too-long lines. The too-long lines will be resolved in the following commit that will resolve all remaining flake8 issues including shadowed builtins, long lines, import order, unused imports, duplicate imports, and docstring issues. Change-Id: I7eda77fed3d8e73df84b3651fd6cfcfe858d4dc9
Diffstat (limited to 'lib/sqlalchemy/orm')
-rw-r--r--lib/sqlalchemy/orm/__init__.py51
-rw-r--r--lib/sqlalchemy/orm/attributes.py781
-rw-r--r--lib/sqlalchemy/orm/base.py128
-rw-r--r--lib/sqlalchemy/orm/collections.py294
-rw-r--r--lib/sqlalchemy/orm/dependency.py1086
-rw-r--r--lib/sqlalchemy/orm/deprecated_interfaces.py150
-rw-r--r--lib/sqlalchemy/orm/descriptor_props.py207
-rw-r--r--lib/sqlalchemy/orm/dynamic.py208
-rw-r--r--lib/sqlalchemy/orm/evaluator.py101
-rw-r--r--lib/sqlalchemy/orm/events.py175
-rw-r--r--lib/sqlalchemy/orm/exc.py25
-rw-r--r--lib/sqlalchemy/orm/identity.py18
-rw-r--r--lib/sqlalchemy/orm/instrumentation.py105
-rw-r--r--lib/sqlalchemy/orm/interfaces.py139
-rw-r--r--lib/sqlalchemy/orm/loading.py381
-rw-r--r--lib/sqlalchemy/orm/mapper.py1029
-rw-r--r--lib/sqlalchemy/orm/path_registry.py70
-rw-r--r--lib/sqlalchemy/orm/persistence.py1186
-rw-r--r--lib/sqlalchemy/orm/properties.py137
-rw-r--r--lib/sqlalchemy/orm/query.py978
-rw-r--r--lib/sqlalchemy/orm/relationships.py1277
-rw-r--r--lib/sqlalchemy/orm/scoping.py38
-rw-r--r--lib/sqlalchemy/orm/session.py570
-rw-r--r--lib/sqlalchemy/orm/state.py233
-rw-r--r--lib/sqlalchemy/orm/strategies.py1144
-rw-r--r--lib/sqlalchemy/orm/strategy_options.py310
-rw-r--r--lib/sqlalchemy/orm/sync.py64
-rw-r--r--lib/sqlalchemy/orm/unitofwork.py264
-rw-r--r--lib/sqlalchemy/orm/util.py462
29 files changed, 6921 insertions, 4690 deletions
diff --git a/lib/sqlalchemy/orm/__init__.py b/lib/sqlalchemy/orm/__init__.py
index 1784ea21f..8e7b4cee6 100644
--- a/lib/sqlalchemy/orm/__init__.py
+++ b/lib/sqlalchemy/orm/__init__.py
@@ -20,14 +20,9 @@ from .mapper import (
class_mapper,
configure_mappers,
reconstructor,
- validates
-)
-from .interfaces import (
- EXT_CONTINUE,
- EXT_STOP,
- EXT_SKIP,
- PropComparator,
+ validates,
)
+from .interfaces import EXT_CONTINUE, EXT_STOP, EXT_SKIP, PropComparator
from .deprecated_interfaces import (
MapperExtension,
SessionExtension,
@@ -50,20 +45,15 @@ from .descriptor_props import (
CompositeProperty,
SynonymProperty,
)
-from .relationships import (
- foreign,
- remote,
-)
+from .relationships import foreign, remote
from .session import (
Session,
object_session,
sessionmaker,
make_transient,
- make_transient_to_detached
-)
-from .scoping import (
- scoped_session
+ make_transient_to_detached,
)
+from .scoping import scoped_session
from . import mapper as mapperlib
from .query import AliasOption, Query, Bundle
from ..util.langhelpers import public_factory
@@ -103,11 +93,12 @@ def create_session(bind=None, **kwargs):
create_session().
"""
- kwargs.setdefault('autoflush', False)
- kwargs.setdefault('autocommit', True)
- kwargs.setdefault('expire_on_commit', False)
+ kwargs.setdefault("autoflush", False)
+ kwargs.setdefault("autocommit", True)
+ kwargs.setdefault("expire_on_commit", False)
return Session(bind=bind, **kwargs)
+
relationship = public_factory(RelationshipProperty, ".orm.relationship")
@@ -133,7 +124,7 @@ def dynamic_loader(argument, **kw):
on dynamic loading.
"""
- kw['lazy'] = 'dynamic'
+ kw["lazy"] = "dynamic"
return relationship(argument, **kw)
@@ -193,16 +184,21 @@ def query_expression():
prop.strategy_key = (("query_expression", True),)
return prop
+
mapper = public_factory(Mapper, ".orm.mapper")
synonym = public_factory(SynonymProperty, ".orm.synonym")
-comparable_property = public_factory(ComparableProperty,
- ".orm.comparable_property")
+comparable_property = public_factory(
+ ComparableProperty, ".orm.comparable_property"
+)
-@_sa_util.deprecated("0.7", message=":func:`.compile_mappers` "
- "is renamed to :func:`.configure_mappers`")
+@_sa_util.deprecated(
+ "0.7",
+ message=":func:`.compile_mappers` "
+ "is renamed to :func:`.configure_mappers`",
+)
def compile_mappers():
"""Initialize the inter-mapper relationships of all mappers that have
been defined.
@@ -243,6 +239,7 @@ def clear_mappers():
finally:
mapperlib._CONFIGURE_MUTEX.release()
+
from . import strategy_options
joinedload = strategy_options.joinedload._unbound_fn
@@ -289,10 +286,14 @@ def __go(lcls):
from . import loading
import inspect as _inspect
- __all__ = sorted(name for name, obj in lcls.items()
- if not (name.startswith('_') or _inspect.ismodule(obj)))
+ __all__ = sorted(
+ name
+ for name, obj in lcls.items()
+ if not (name.startswith("_") or _inspect.ismodule(obj))
+ )
_sa_util.dependencies.resolve_all("sqlalchemy.orm")
_sa_util.dependencies.resolve_all("sqlalchemy.ext")
+
__go(locals())
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py
index b08c46741..1648c9ae1 100644
--- a/lib/sqlalchemy/orm/attributes.py
+++ b/lib/sqlalchemy/orm/attributes.py
@@ -20,19 +20,37 @@ from . import interfaces, collections, exc as orm_exc
from .base import instance_state, instance_dict, manager_of_class
-from .base import PASSIVE_NO_RESULT, ATTR_WAS_SET, ATTR_EMPTY, NO_VALUE,\
- NEVER_SET, NO_CHANGE, CALLABLES_OK, SQL_OK, RELATED_OBJECT_OK,\
- INIT_OK, NON_PERSISTENT_OK, LOAD_AGAINST_COMMITTED, PASSIVE_OFF,\
- PASSIVE_RETURN_NEVER_SET, PASSIVE_NO_INITIALIZE, PASSIVE_NO_FETCH,\
- PASSIVE_NO_FETCH_RELATED, PASSIVE_ONLY_PERSISTENT, NO_AUTOFLUSH, \
- NO_RAISE
+from .base import (
+ PASSIVE_NO_RESULT,
+ ATTR_WAS_SET,
+ ATTR_EMPTY,
+ NO_VALUE,
+ NEVER_SET,
+ NO_CHANGE,
+ CALLABLES_OK,
+ SQL_OK,
+ RELATED_OBJECT_OK,
+ INIT_OK,
+ NON_PERSISTENT_OK,
+ LOAD_AGAINST_COMMITTED,
+ PASSIVE_OFF,
+ PASSIVE_RETURN_NEVER_SET,
+ PASSIVE_NO_INITIALIZE,
+ PASSIVE_NO_FETCH,
+ PASSIVE_NO_FETCH_RELATED,
+ PASSIVE_ONLY_PERSISTENT,
+ NO_AUTOFLUSH,
+ NO_RAISE,
+)
from .base import state_str, instance_str
@inspection._self_inspects
-class QueryableAttribute(interfaces._MappedAttribute,
- interfaces.InspectionAttr,
- interfaces.PropComparator):
+class QueryableAttribute(
+ interfaces._MappedAttribute,
+ interfaces.InspectionAttr,
+ interfaces.PropComparator,
+):
"""Base class for :term:`descriptor` objects that intercept
attribute events on behalf of a :class:`.MapperProperty`
object. The actual :class:`.MapperProperty` is accessible
@@ -53,9 +71,15 @@ class QueryableAttribute(interfaces._MappedAttribute,
is_attribute = True
- def __init__(self, class_, key, impl=None,
- comparator=None, parententity=None,
- of_type=None):
+ def __init__(
+ self,
+ class_,
+ key,
+ impl=None,
+ comparator=None,
+ parententity=None,
+ of_type=None,
+ ):
self.class_ = class_
self.key = key
self.impl = impl
@@ -77,8 +101,9 @@ class QueryableAttribute(interfaces._MappedAttribute,
return self.impl.supports_population
def get_history(self, instance, passive=PASSIVE_OFF):
- return self.impl.get_history(instance_state(instance),
- instance_dict(instance), passive)
+ return self.impl.get_history(
+ instance_state(instance), instance_dict(instance), passive
+ )
def __selectable__(self):
# TODO: conditionally attach this method based on clause_element ?
@@ -159,11 +184,13 @@ class QueryableAttribute(interfaces._MappedAttribute,
def adapt_to_entity(self, adapt_to_entity):
assert not self._of_type
- return self.__class__(adapt_to_entity.entity,
- self.key, impl=self.impl,
- comparator=self.comparator.adapt_to_entity(
- adapt_to_entity),
- parententity=adapt_to_entity)
+ return self.__class__(
+ adapt_to_entity.entity,
+ self.key,
+ impl=self.impl,
+ comparator=self.comparator.adapt_to_entity(adapt_to_entity),
+ parententity=adapt_to_entity,
+ )
def of_type(self, cls):
return QueryableAttribute(
@@ -172,7 +199,8 @@ class QueryableAttribute(interfaces._MappedAttribute,
self.impl,
self.comparator.of_type(cls),
self._parententity,
- of_type=cls)
+ of_type=cls,
+ )
def label(self, name):
return self._query_clause_element().label(name)
@@ -191,12 +219,14 @@ class QueryableAttribute(interfaces._MappedAttribute,
return getattr(self.comparator, key)
except AttributeError:
raise AttributeError(
- 'Neither %r object nor %r object associated with %s '
- 'has an attribute %r' % (
+ "Neither %r object nor %r object associated with %s "
+ "has an attribute %r"
+ % (
type(self).__name__,
type(self.comparator).__name__,
self,
- key)
+ key,
+ )
)
def __str__(self):
@@ -226,8 +256,9 @@ class InstrumentedAttribute(QueryableAttribute):
"""
def __set__(self, instance, value):
- self.impl.set(instance_state(instance),
- instance_dict(instance), value, None)
+ self.impl.set(
+ instance_state(instance), instance_dict(instance), value, None
+ )
def __delete__(self, instance):
self.impl.delete(instance_state(instance), instance_dict(instance))
@@ -260,10 +291,16 @@ def create_proxied_attribute(descriptor):
"""
- def __init__(self, class_, key, descriptor,
- comparator,
- adapt_to_entity=None, doc=None,
- original_property=None):
+ def __init__(
+ self,
+ class_,
+ key,
+ descriptor,
+ comparator,
+ adapt_to_entity=None,
+ doc=None,
+ original_property=None,
+ ):
self.class_ = class_
self.key = key
self.descriptor = descriptor
@@ -284,15 +321,18 @@ def create_proxied_attribute(descriptor):
self._comparator = self._comparator()
if self._adapt_to_entity:
self._comparator = self._comparator.adapt_to_entity(
- self._adapt_to_entity)
+ self._adapt_to_entity
+ )
return self._comparator
def adapt_to_entity(self, adapt_to_entity):
- return self.__class__(adapt_to_entity.entity,
- self.key,
- self.descriptor,
- self._comparator,
- adapt_to_entity)
+ return self.__class__(
+ adapt_to_entity.entity,
+ self.key,
+ self.descriptor,
+ self._comparator,
+ adapt_to_entity,
+ )
def __get__(self, instance, owner):
if instance is None:
@@ -314,21 +354,24 @@ def create_proxied_attribute(descriptor):
return getattr(self.comparator, attribute)
except AttributeError:
raise AttributeError(
- 'Neither %r object nor %r object associated with %s '
- 'has an attribute %r' % (
+ "Neither %r object nor %r object associated with %s "
+ "has an attribute %r"
+ % (
type(descriptor).__name__,
type(self.comparator).__name__,
self,
- attribute)
+ attribute,
+ )
)
- Proxy.__name__ = type(descriptor).__name__ + 'Proxy'
+ Proxy.__name__ = type(descriptor).__name__ + "Proxy"
- util.monkeypatch_proxied_specials(Proxy, type(descriptor),
- name='descriptor',
- from_instance=descriptor)
+ util.monkeypatch_proxied_specials(
+ Proxy, type(descriptor), name="descriptor", from_instance=descriptor
+ )
return Proxy
+
OP_REMOVE = util.symbol("REMOVE")
OP_APPEND = util.symbol("APPEND")
OP_REPLACE = util.symbol("REPLACE")
@@ -364,7 +407,7 @@ class Event(object):
"""
- __slots__ = 'impl', 'op', 'parent_token'
+ __slots__ = "impl", "op", "parent_token"
def __init__(self, attribute_impl, op):
self.impl = attribute_impl
@@ -372,9 +415,11 @@ class Event(object):
self.parent_token = self.impl.parent_token
def __eq__(self, other):
- return isinstance(other, Event) and \
- other.impl is self.impl and \
- other.op == self.op
+ return (
+ isinstance(other, Event)
+ and other.impl is self.impl
+ and other.op == self.op
+ )
@property
def key(self):
@@ -387,12 +432,22 @@ class Event(object):
class AttributeImpl(object):
"""internal implementation for instrumented attributes."""
- def __init__(self, class_, key,
- callable_, dispatch, trackparent=False, extension=None,
- compare_function=None, active_history=False,
- parent_token=None, expire_missing=True,
- send_modified_events=True, accepts_scalar_loader=None,
- **kwargs):
+ def __init__(
+ self,
+ class_,
+ key,
+ callable_,
+ dispatch,
+ trackparent=False,
+ extension=None,
+ compare_function=None,
+ active_history=False,
+ parent_token=None,
+ expire_missing=True,
+ send_modified_events=True,
+ accepts_scalar_loader=None,
+ **kwargs
+ ):
r"""Construct an AttributeImpl.
\class_
@@ -471,9 +526,17 @@ class AttributeImpl(object):
self._modified_token = Event(self, OP_MODIFIED)
__slots__ = (
- 'class_', 'key', 'callable_', 'dispatch', 'trackparent',
- 'parent_token', 'send_modified_events', 'is_equal', 'expire_missing',
- '_modified_token', 'accepts_scalar_loader'
+ "class_",
+ "key",
+ "callable_",
+ "dispatch",
+ "trackparent",
+ "parent_token",
+ "send_modified_events",
+ "is_equal",
+ "expire_missing",
+ "_modified_token",
+ "accepts_scalar_loader",
)
def __str__(self):
@@ -508,8 +571,9 @@ class AttributeImpl(object):
msg = "This AttributeImpl is not configured to track parents."
assert self.trackparent, msg
- return state.parents.get(id(self.parent_token), optimistic) \
- is not False
+ return (
+ state.parents.get(id(self.parent_token), optimistic) is not False
+ )
def sethasparent(self, state, parent_state, value):
"""Set a boolean flag on the given item corresponding to
@@ -527,8 +591,10 @@ class AttributeImpl(object):
if id_ in state.parents:
last_parent = state.parents[id_]
- if last_parent is not False and \
- last_parent.key != parent_state.key:
+ if (
+ last_parent is not False
+ and last_parent.key != parent_state.key
+ ):
if last_parent.obj() is None:
raise orm_exc.StaleDataError(
@@ -536,10 +602,13 @@ class AttributeImpl(object):
"state %s along attribute '%s', "
"but the parent record "
"has gone stale, can't be sure this "
- "is the most recent parent." %
- (state_str(state),
- state_str(parent_state),
- self.key))
+ "is the most recent parent."
+ % (
+ state_str(state),
+ state_str(parent_state),
+ self.key,
+ )
+ )
return
@@ -588,8 +657,10 @@ class AttributeImpl(object):
else:
# if history present, don't load
key = self.key
- if key not in state.committed_state or \
- state.committed_state[key] is NEVER_SET:
+ if (
+ key not in state.committed_state
+ or state.committed_state[key] is NEVER_SET
+ ):
if not passive & CALLABLES_OK:
return PASSIVE_NO_RESULT
@@ -613,7 +684,8 @@ class AttributeImpl(object):
raise KeyError(
"Deferred loader for attribute "
"%r failed to populate "
- "correctly" % key)
+ "correctly" % key
+ )
elif value is not ATTR_EMPTY:
return self.set_committed_value(state, dict_, value)
@@ -627,15 +699,31 @@ class AttributeImpl(object):
self.set(state, dict_, value, initiator, passive=passive)
def remove(self, state, dict_, value, initiator, passive=PASSIVE_OFF):
- self.set(state, dict_, None, initiator,
- passive=passive, check_old=value)
+ self.set(
+ state, dict_, None, initiator, passive=passive, check_old=value
+ )
def pop(self, state, dict_, value, initiator, passive=PASSIVE_OFF):
- self.set(state, dict_, None, initiator,
- passive=passive, check_old=value, pop=True)
+ self.set(
+ state,
+ dict_,
+ None,
+ initiator,
+ passive=passive,
+ check_old=value,
+ pop=True,
+ )
- def set(self, state, dict_, value, initiator,
- passive=PASSIVE_OFF, check_old=None, pop=False):
+ def set(
+ self,
+ state,
+ dict_,
+ value,
+ initiator,
+ passive=PASSIVE_OFF,
+ check_old=None,
+ pop=False,
+ ):
raise NotImplementedError()
def get_committed_value(self, state, dict_, passive=PASSIVE_OFF):
@@ -667,7 +755,7 @@ class ScalarAttributeImpl(AttributeImpl):
collection = False
dynamic = False
- __slots__ = '_replace_token', '_append_token', '_remove_token'
+ __slots__ = "_replace_token", "_append_token", "_remove_token"
def __init__(self, *arg, **kw):
super(ScalarAttributeImpl, self).__init__(*arg, **kw)
@@ -685,10 +773,13 @@ class ScalarAttributeImpl(AttributeImpl):
state._modified_event(dict_, self, old)
existing = dict_.pop(self.key, NO_VALUE)
- if existing is NO_VALUE and old is NO_VALUE and \
- not state.expired and \
- self.key not in state.expired_attributes:
- raise AttributeError("%s object does not have a value" % self)
+ if (
+ existing is NO_VALUE
+ and old is NO_VALUE
+ and not state.expired
+ and self.key not in state.expired_attributes
+ ):
+ raise AttributeError("%s object does not have a value" % self)
def get_history(self, state, dict_, passive=PASSIVE_OFF):
if self.key in dict_:
@@ -702,23 +793,33 @@ class ScalarAttributeImpl(AttributeImpl):
else:
return History.from_scalar_attribute(self, state, current)
- def set(self, state, dict_, value, initiator,
- passive=PASSIVE_OFF, check_old=None, pop=False):
+ def set(
+ self,
+ state,
+ dict_,
+ value,
+ initiator,
+ passive=PASSIVE_OFF,
+ check_old=None,
+ pop=False,
+ ):
if self.dispatch._active_history:
old = self.get(state, dict_, PASSIVE_RETURN_NEVER_SET)
else:
old = dict_.get(self.key, NO_VALUE)
if self.dispatch.set:
- value = self.fire_replace_event(state, dict_,
- value, old, initiator)
+ value = self.fire_replace_event(
+ state, dict_, value, old, initiator
+ )
state._modified_event(dict_, self, old)
dict_[self.key] = value
def fire_replace_event(self, state, dict_, value, previous, initiator):
for fn in self.dispatch.set:
value = fn(
- state, value, previous, initiator or self._replace_token)
+ state, value, previous, initiator or self._replace_token
+ )
return value
def fire_remove_event(self, state, dict_, value, initiator):
@@ -748,13 +849,20 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
def delete(self, state, dict_):
if self.dispatch._active_history:
old = self.get(
- state, dict_,
- passive=PASSIVE_ONLY_PERSISTENT |
- NO_AUTOFLUSH | LOAD_AGAINST_COMMITTED)
+ state,
+ dict_,
+ passive=PASSIVE_ONLY_PERSISTENT
+ | NO_AUTOFLUSH
+ | LOAD_AGAINST_COMMITTED,
+ )
else:
old = self.get(
- state, dict_, passive=PASSIVE_NO_FETCH ^ INIT_OK |
- LOAD_AGAINST_COMMITTED | NO_RAISE)
+ state,
+ dict_,
+ passive=PASSIVE_NO_FETCH ^ INIT_OK
+ | LOAD_AGAINST_COMMITTED
+ | NO_RAISE,
+ )
self.fire_remove_event(state, dict_, old, self._remove_token)
@@ -763,8 +871,11 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
# if the attribute is expired, we currently have no way to tell
# that an object-attribute was expired vs. not loaded. So
# for this test, we look to see if the object has a DB identity.
- if existing is NO_VALUE and old is not PASSIVE_NO_RESULT and \
- state.key is None:
+ if (
+ existing is NO_VALUE
+ and old is not PASSIVE_NO_RESULT
+ and state.key is None
+ ):
raise AttributeError("%s object does not have a value" % self)
def get_history(self, state, dict_, passive=PASSIVE_OFF):
@@ -788,50 +899,69 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
return []
# can't use __hash__(), can't use __eq__() here
- if current is not None and \
- current is not PASSIVE_NO_RESULT and \
- current is not NEVER_SET:
+ if (
+ current is not None
+ and current is not PASSIVE_NO_RESULT
+ and current is not NEVER_SET
+ ):
ret = [(instance_state(current), current)]
else:
ret = [(None, None)]
if self.key in state.committed_state:
original = state.committed_state[self.key]
- if original is not None and \
- original is not PASSIVE_NO_RESULT and \
- original is not NEVER_SET and \
- original is not current:
+ if (
+ original is not None
+ and original is not PASSIVE_NO_RESULT
+ and original is not NEVER_SET
+ and original is not current
+ ):
ret.append((instance_state(original), original))
return ret
- def set(self, state, dict_, value, initiator,
- passive=PASSIVE_OFF, check_old=None, pop=False):
+ def set(
+ self,
+ state,
+ dict_,
+ value,
+ initiator,
+ passive=PASSIVE_OFF,
+ check_old=None,
+ pop=False,
+ ):
"""Set a value on the given InstanceState.
"""
if self.dispatch._active_history:
old = self.get(
- state, dict_,
- passive=PASSIVE_ONLY_PERSISTENT |
- NO_AUTOFLUSH | LOAD_AGAINST_COMMITTED)
+ state,
+ dict_,
+ passive=PASSIVE_ONLY_PERSISTENT
+ | NO_AUTOFLUSH
+ | LOAD_AGAINST_COMMITTED,
+ )
else:
old = self.get(
- state, dict_, passive=PASSIVE_NO_FETCH ^ INIT_OK |
- LOAD_AGAINST_COMMITTED | NO_RAISE)
+ state,
+ dict_,
+ passive=PASSIVE_NO_FETCH ^ INIT_OK
+ | LOAD_AGAINST_COMMITTED
+ | NO_RAISE,
+ )
- if check_old is not None and \
- old is not PASSIVE_NO_RESULT and \
- check_old is not old:
+ if (
+ check_old is not None
+ and old is not PASSIVE_NO_RESULT
+ and check_old is not old
+ ):
if pop:
return
else:
raise ValueError(
- "Object %s not associated with %s on attribute '%s'" % (
- instance_str(check_old),
- state_str(state),
- self.key
- ))
+ "Object %s not associated with %s on attribute '%s'"
+ % (instance_str(check_old), state_str(state), self.key)
+ )
value = self.fire_replace_event(state, dict_, value, old, initiator)
dict_[self.key] = value
@@ -847,13 +977,17 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl):
def fire_replace_event(self, state, dict_, value, previous, initiator):
if self.trackparent:
- if (previous is not value and
- previous not in (None, PASSIVE_NO_RESULT, NEVER_SET)):
+ if previous is not value and previous not in (
+ None,
+ PASSIVE_NO_RESULT,
+ NEVER_SET,
+ ):
self.sethasparent(instance_state(previous), state, False)
for fn in self.dispatch.set:
value = fn(
- state, value, previous, initiator or self._replace_token)
+ state, value, previous, initiator or self._replace_token
+ )
state._modified_event(dict_, self, previous)
@@ -875,6 +1009,7 @@ class CollectionAttributeImpl(AttributeImpl):
semantics to the orm layer independent of the user data implementation.
"""
+
default_accepts_scalar_loader = False
uses_objects = True
supports_population = True
@@ -882,21 +1017,37 @@ class CollectionAttributeImpl(AttributeImpl):
dynamic = False
__slots__ = (
- 'copy', 'collection_factory', '_append_token', '_remove_token',
- '_bulk_replace_token', '_duck_typed_as'
+ "copy",
+ "collection_factory",
+ "_append_token",
+ "_remove_token",
+ "_bulk_replace_token",
+ "_duck_typed_as",
)
- def __init__(self, class_, key, callable_, dispatch,
- typecallable=None, trackparent=False, extension=None,
- copy_function=None, compare_function=None, **kwargs):
+ def __init__(
+ self,
+ class_,
+ key,
+ callable_,
+ dispatch,
+ typecallable=None,
+ trackparent=False,
+ extension=None,
+ copy_function=None,
+ compare_function=None,
+ **kwargs
+ ):
super(CollectionAttributeImpl, self).__init__(
class_,
key,
- callable_, dispatch,
+ callable_,
+ dispatch,
trackparent=trackparent,
extension=extension,
compare_function=compare_function,
- **kwargs)
+ **kwargs
+ )
if copy_function is None:
copy_function = self.__copy
@@ -906,7 +1057,8 @@ class CollectionAttributeImpl(AttributeImpl):
self._remove_token = Event(self, OP_REMOVE)
self._bulk_replace_token = Event(self, OP_BULK_REPLACE)
self._duck_typed_as = util.duck_type_collection(
- self.collection_factory())
+ self.collection_factory()
+ )
if getattr(self.collection_factory, "_sa_linker", None):
@@ -935,35 +1087,42 @@ class CollectionAttributeImpl(AttributeImpl):
return []
current = dict_[self.key]
- current = getattr(current, '_sa_adapter')
+ current = getattr(current, "_sa_adapter")
if self.key in state.committed_state:
original = state.committed_state[self.key]
if original not in (NO_VALUE, NEVER_SET):
- current_states = [((c is not None) and
- instance_state(c) or None, c)
- for c in current]
- original_states = [((c is not None) and
- instance_state(c) or None, c)
- for c in original]
+ current_states = [
+ ((c is not None) and instance_state(c) or None, c)
+ for c in current
+ ]
+ original_states = [
+ ((c is not None) and instance_state(c) or None, c)
+ for c in original
+ ]
current_set = dict(current_states)
original_set = dict(original_states)
- return \
- [(s, o) for s, o in current_states
- if s not in original_set] + \
- [(s, o) for s, o in current_states
- if s in original_set] + \
- [(s, o) for s, o in original_states
- if s not in current_set]
+ return (
+ [
+ (s, o)
+ for s, o in current_states
+ if s not in original_set
+ ]
+ + [(s, o) for s, o in current_states if s in original_set]
+ + [
+ (s, o)
+ for s, o in original_states
+ if s not in current_set
+ ]
+ )
return [(instance_state(o), o) for o in current]
def fire_append_event(self, state, dict_, value, initiator):
for fn in self.dispatch.append:
- value = fn(
- state, value, initiator or self._append_token)
+ value = fn(state, value, initiator or self._append_token)
state._modified_event(dict_, self, NEVER_SET, True)
@@ -1015,7 +1174,8 @@ class CollectionAttributeImpl(AttributeImpl):
def _initialize_collection(self, state):
adapter, collection = state.manager.initialize_collection(
- self.key, state, self.collection_factory)
+ self.key, state, self.collection_factory
+ )
self.dispatch.init_collection(state, collection, adapter)
@@ -1025,8 +1185,9 @@ class CollectionAttributeImpl(AttributeImpl):
collection = self.get_collection(state, dict_, passive=passive)
if collection is PASSIVE_NO_RESULT:
value = self.fire_append_event(state, dict_, value, initiator)
- assert self.key not in dict_, \
- "Collection was loaded during event handling."
+ assert (
+ self.key not in dict_
+ ), "Collection was loaded during event handling."
state._get_pending_mutation(self.key).append(value)
else:
collection.append_with_event(value, initiator)
@@ -1035,8 +1196,9 @@ class CollectionAttributeImpl(AttributeImpl):
collection = self.get_collection(state, state.dict, passive=passive)
if collection is PASSIVE_NO_RESULT:
self.fire_remove_event(state, dict_, value, initiator)
- assert self.key not in dict_, \
- "Collection was loaded during event handling."
+ assert (
+ self.key not in dict_
+ ), "Collection was loaded during event handling."
state._get_pending_mutation(self.key).remove(value)
else:
collection.remove_with_event(value, initiator)
@@ -1050,8 +1212,16 @@ class CollectionAttributeImpl(AttributeImpl):
except (ValueError, KeyError, IndexError):
pass
- def set(self, state, dict_, value, initiator=None,
- passive=PASSIVE_OFF, pop=False, _adapt=True):
+ def set(
+ self,
+ state,
+ dict_,
+ value,
+ initiator=None,
+ passive=PASSIVE_OFF,
+ pop=False,
+ _adapt=True,
+ ):
iterable = orig_iterable = value
# pulling a new collection first so that an adaptation exception does
@@ -1065,23 +1235,28 @@ class CollectionAttributeImpl(AttributeImpl):
receiving_type = self._duck_typed_as
if setting_type is not receiving_type:
- given = iterable is None and 'None' or \
- iterable.__class__.__name__
+ given = (
+ iterable is None
+ and "None"
+ or iterable.__class__.__name__
+ )
wanted = self._duck_typed_as.__name__
raise TypeError(
- "Incompatible collection type: %s is not %s-like" % (
- given, wanted))
+ "Incompatible collection type: %s is not %s-like"
+ % (given, wanted)
+ )
# If the object is an adapted collection, return the (iterable)
# adapter.
- if hasattr(iterable, '_sa_iterator'):
+ if hasattr(iterable, "_sa_iterator"):
iterable = iterable._sa_iterator()
elif setting_type is dict:
if util.py3k:
iterable = iterable.values()
else:
iterable = getattr(
- iterable, 'itervalues', iterable.values)()
+ iterable, "itervalues", iterable.values
+ )()
else:
iterable = iter(iterable)
new_values = list(iterable)
@@ -1106,14 +1281,14 @@ class CollectionAttributeImpl(AttributeImpl):
dict_[self.key] = user_data
collections.bulk_replace(
- new_values, old_collection, new_collection,
- initiator=evt)
+ new_values, old_collection, new_collection, initiator=evt
+ )
del old._sa_adapter
self.dispatch.dispose_collection(state, old, old_collection)
def _invalidate_collection(self, collection):
- adapter = getattr(collection, '_sa_adapter')
+ adapter = getattr(collection, "_sa_adapter")
adapter.invalidated = True
def set_committed_value(self, state, dict_, value):
@@ -1143,8 +1318,9 @@ class CollectionAttributeImpl(AttributeImpl):
return user_data
- def get_collection(self, state, dict_,
- user_data=None, passive=PASSIVE_OFF):
+ def get_collection(
+ self, state, dict_, user_data=None, passive=PASSIVE_OFF
+ ):
"""Retrieve the CollectionAdapter associated with the given state.
Creates a new CollectionAdapter if one does not exist.
@@ -1155,7 +1331,7 @@ class CollectionAttributeImpl(AttributeImpl):
if user_data is PASSIVE_NO_RESULT:
return user_data
- return getattr(user_data, '_sa_adapter')
+ return getattr(user_data, "_sa_adapter")
def backref_listeners(attribute, key, uselist):
@@ -1177,24 +1353,29 @@ def backref_listeners(attribute, key, uselist):
"Bidirectional attribute conflict detected: "
'Passing object %s to attribute "%s" '
'triggers a modify event on attribute "%s" '
- 'via the backref "%s".' % (
+ 'via the backref "%s".'
+ % (
state_str(child_state),
initiator.parent_token,
child_impl.parent_token,
- attribute.impl.parent_token
+ attribute.impl.parent_token,
)
)
def emit_backref_from_scalar_set_event(state, child, oldchild, initiator):
if oldchild is child:
return child
- if oldchild is not None and \
- oldchild is not PASSIVE_NO_RESULT and \
- oldchild is not NEVER_SET:
+ if (
+ oldchild is not None
+ and oldchild is not PASSIVE_NO_RESULT
+ and oldchild is not NEVER_SET
+ ):
# With lazy=None, there's no guarantee that the full collection is
# present when updating via a backref.
- old_state, old_dict = instance_state(oldchild),\
- instance_dict(oldchild)
+ old_state, old_dict = (
+ instance_state(oldchild),
+ instance_dict(oldchild),
+ )
impl = old_state.manager[key].impl
# tokens to test for a recursive loop.
@@ -1204,69 +1385,90 @@ def backref_listeners(attribute, key, uselist):
check_recursive_token = impl._remove_token
if initiator is not check_recursive_token:
- impl.pop(old_state,
- old_dict,
- state.obj(),
- parent_impl._append_token,
- passive=PASSIVE_NO_FETCH)
+ impl.pop(
+ old_state,
+ old_dict,
+ state.obj(),
+ parent_impl._append_token,
+ passive=PASSIVE_NO_FETCH,
+ )
if child is not None:
- child_state, child_dict = instance_state(child),\
- instance_dict(child)
+ child_state, child_dict = (
+ instance_state(child),
+ instance_dict(child),
+ )
child_impl = child_state.manager[key].impl
- if initiator.parent_token is not parent_token and \
- initiator.parent_token is not child_impl.parent_token:
+ if (
+ initiator.parent_token is not parent_token
+ and initiator.parent_token is not child_impl.parent_token
+ ):
_acceptable_key_err(state, initiator, child_impl)
# tokens to test for a recursive loop.
check_append_token = child_impl._append_token
- check_bulk_replace_token = child_impl._bulk_replace_token \
- if child_impl.collection else None
+ check_bulk_replace_token = (
+ child_impl._bulk_replace_token
+ if child_impl.collection
+ else None
+ )
- if initiator is not check_append_token and \
- initiator is not check_bulk_replace_token:
+ if (
+ initiator is not check_append_token
+ and initiator is not check_bulk_replace_token
+ ):
child_impl.append(
child_state,
child_dict,
state.obj(),
initiator,
- passive=PASSIVE_NO_FETCH)
+ passive=PASSIVE_NO_FETCH,
+ )
return child
def emit_backref_from_collection_append_event(state, child, initiator):
if child is None:
return
- child_state, child_dict = instance_state(child), \
- instance_dict(child)
+ child_state, child_dict = instance_state(child), instance_dict(child)
child_impl = child_state.manager[key].impl
- if initiator.parent_token is not parent_token and \
- initiator.parent_token is not child_impl.parent_token:
+ if (
+ initiator.parent_token is not parent_token
+ and initiator.parent_token is not child_impl.parent_token
+ ):
_acceptable_key_err(state, initiator, child_impl)
# tokens to test for a recursive loop.
check_append_token = child_impl._append_token
- check_bulk_replace_token = child_impl._bulk_replace_token \
- if child_impl.collection else None
+ check_bulk_replace_token = (
+ child_impl._bulk_replace_token if child_impl.collection else None
+ )
- if initiator is not check_append_token and \
- initiator is not check_bulk_replace_token:
+ if (
+ initiator is not check_append_token
+ and initiator is not check_bulk_replace_token
+ ):
child_impl.append(
child_state,
child_dict,
state.obj(),
initiator,
- passive=PASSIVE_NO_FETCH)
+ passive=PASSIVE_NO_FETCH,
+ )
return child
def emit_backref_from_collection_remove_event(state, child, initiator):
- if child is not None and \
- child is not PASSIVE_NO_RESULT and \
- child is not NEVER_SET:
- child_state, child_dict = instance_state(child),\
- instance_dict(child)
+ if (
+ child is not None
+ and child is not PASSIVE_NO_RESULT
+ and child is not NEVER_SET
+ ):
+ child_state, child_dict = (
+ instance_state(child),
+ instance_dict(child),
+ )
child_impl = child_state.manager[key].impl
# tokens to test for a recursive loop.
@@ -1276,47 +1478,64 @@ def backref_listeners(attribute, key, uselist):
check_for_dupes_on_remove = uselist and not parent_impl.dynamic
else:
check_remove_token = child_impl._remove_token
- check_replace_token = child_impl._bulk_replace_token \
- if child_impl.collection else None
+ check_replace_token = (
+ child_impl._bulk_replace_token
+ if child_impl.collection
+ else None
+ )
check_for_dupes_on_remove = False
- if initiator is not check_remove_token and \
- initiator is not check_replace_token:
-
- if not check_for_dupes_on_remove or \
- not util.has_dupes(
- # when this event is called, the item is usually
- # present in the list, except for a pop() operation.
- state.dict[parent_impl.key], child):
+ if (
+ initiator is not check_remove_token
+ and initiator is not check_replace_token
+ ):
+
+ if not check_for_dupes_on_remove or not util.has_dupes(
+ # when this event is called, the item is usually
+ # present in the list, except for a pop() operation.
+ state.dict[parent_impl.key],
+ child,
+ ):
child_impl.pop(
child_state,
child_dict,
state.obj(),
initiator,
- passive=PASSIVE_NO_FETCH)
+ passive=PASSIVE_NO_FETCH,
+ )
if uselist:
- event.listen(attribute, "append",
- emit_backref_from_collection_append_event,
- retval=True, raw=True)
+ event.listen(
+ attribute,
+ "append",
+ emit_backref_from_collection_append_event,
+ retval=True,
+ raw=True,
+ )
else:
- event.listen(attribute, "set",
- emit_backref_from_scalar_set_event,
- retval=True, raw=True)
+ event.listen(
+ attribute,
+ "set",
+ emit_backref_from_scalar_set_event,
+ retval=True,
+ raw=True,
+ )
# TODO: need coverage in test/orm/ of remove event
- event.listen(attribute, "remove",
- emit_backref_from_collection_remove_event,
- retval=True, raw=True)
+ event.listen(
+ attribute,
+ "remove",
+ emit_backref_from_collection_remove_event,
+ retval=True,
+ raw=True,
+ )
-_NO_HISTORY = util.symbol('NO_HISTORY')
-_NO_STATE_SYMBOLS = frozenset([
- id(PASSIVE_NO_RESULT),
- id(NO_VALUE),
- id(NEVER_SET)])
-History = util.namedtuple("History", [
- "added", "unchanged", "deleted"
-])
+_NO_HISTORY = util.symbol("NO_HISTORY")
+_NO_STATE_SYMBOLS = frozenset(
+ [id(PASSIVE_NO_RESULT), id(NO_VALUE), id(NEVER_SET)]
+)
+
+History = util.namedtuple("History", ["added", "unchanged", "deleted"])
class History(History):
@@ -1346,6 +1565,7 @@ class History(History):
def __bool__(self):
return self != HISTORY_BLANK
+
__nonzero__ = __bool__
def empty(self):
@@ -1354,29 +1574,24 @@ class History(History):
"""
- return not bool(
- (self.added or self.deleted)
- or self.unchanged
- )
+ return not bool((self.added or self.deleted) or self.unchanged)
def sum(self):
"""Return a collection of added + unchanged + deleted."""
- return (self.added or []) +\
- (self.unchanged or []) +\
- (self.deleted or [])
+ return (
+ (self.added or []) + (self.unchanged or []) + (self.deleted or [])
+ )
def non_deleted(self):
"""Return a collection of added + unchanged."""
- return (self.added or []) +\
- (self.unchanged or [])
+ return (self.added or []) + (self.unchanged or [])
def non_added(self):
"""Return a collection of unchanged + deleted."""
- return (self.unchanged or []) +\
- (self.deleted or [])
+ return (self.unchanged or []) + (self.deleted or [])
def has_changes(self):
"""Return True if this :class:`.History` has changes."""
@@ -1385,15 +1600,18 @@ class History(History):
def as_state(self):
return History(
- [(c is not None)
- and instance_state(c) or None
- for c in self.added],
- [(c is not None)
- and instance_state(c) or None
- for c in self.unchanged],
- [(c is not None)
- and instance_state(c) or None
- for c in self.deleted],
+ [
+ (c is not None) and instance_state(c) or None
+ for c in self.added
+ ],
+ [
+ (c is not None) and instance_state(c) or None
+ for c in self.unchanged
+ ],
+ [
+ (c is not None) and instance_state(c) or None
+ for c in self.deleted
+ ],
)
@classmethod
@@ -1464,21 +1682,21 @@ class History(History):
if current is NO_VALUE or current is NEVER_SET:
return cls((), (), ())
- current = getattr(current, '_sa_adapter')
+ current = getattr(current, "_sa_adapter")
if original in (NO_VALUE, NEVER_SET):
return cls(list(current), (), ())
elif original is _NO_HISTORY:
return cls((), list(current), ())
else:
- current_states = [((c is not None) and instance_state(c)
- or None, c)
- for c in current
- ]
- original_states = [((c is not None) and instance_state(c)
- or None, c)
- for c in original
- ]
+ current_states = [
+ ((c is not None) and instance_state(c) or None, c)
+ for c in current
+ ]
+ original_states = [
+ ((c is not None) and instance_state(c) or None, c)
+ for c in original
+ ]
current_set = dict(current_states)
original_set = dict(original_states)
@@ -1486,9 +1704,10 @@ class History(History):
return cls(
[o for s, o in current_states if s not in original_set],
[o for s, o in current_states if s in original_set],
- [o for s, o in original_states if s not in current_set]
+ [o for s, o in original_states if s not in current_set],
)
+
HISTORY_BLANK = History(None, None, None)
@@ -1509,12 +1728,16 @@ def get_history(obj, key, passive=PASSIVE_OFF):
"""
if passive is True:
- util.warn_deprecated("Passing True for 'passive' is deprecated. "
- "Use attributes.PASSIVE_NO_INITIALIZE")
+ util.warn_deprecated(
+ "Passing True for 'passive' is deprecated. "
+ "Use attributes.PASSIVE_NO_INITIALIZE"
+ )
passive = PASSIVE_NO_INITIALIZE
elif passive is False:
- util.warn_deprecated("Passing False for 'passive' is "
- "deprecated. Use attributes.PASSIVE_OFF")
+ util.warn_deprecated(
+ "Passing False for 'passive' is "
+ "deprecated. Use attributes.PASSIVE_OFF"
+ )
passive = PASSIVE_OFF
return get_state_history(instance_state(obj), key, passive)
@@ -1532,38 +1755,46 @@ def has_parent(cls, obj, key, optimistic=False):
def register_attribute(class_, key, **kw):
- comparator = kw.pop('comparator', None)
- parententity = kw.pop('parententity', None)
- doc = kw.pop('doc', None)
- desc = register_descriptor(class_, key,
- comparator, parententity, doc=doc)
+ comparator = kw.pop("comparator", None)
+ parententity = kw.pop("parententity", None)
+ doc = kw.pop("doc", None)
+ desc = register_descriptor(class_, key, comparator, parententity, doc=doc)
register_attribute_impl(class_, key, **kw)
return desc
-def register_attribute_impl(class_, key,
- uselist=False, callable_=None,
- useobject=False,
- impl_class=None, backref=None, **kw):
+def register_attribute_impl(
+ class_,
+ key,
+ uselist=False,
+ callable_=None,
+ useobject=False,
+ impl_class=None,
+ backref=None,
+ **kw
+):
manager = manager_of_class(class_)
if uselist:
- factory = kw.pop('typecallable', None)
+ factory = kw.pop("typecallable", None)
typecallable = manager.instrument_collection_class(
- key, factory or list)
+ key, factory or list
+ )
else:
- typecallable = kw.pop('typecallable', None)
+ typecallable = kw.pop("typecallable", None)
dispatch = manager[key].dispatch
if impl_class:
impl = impl_class(class_, key, typecallable, dispatch, **kw)
elif uselist:
- impl = CollectionAttributeImpl(class_, key, callable_, dispatch,
- typecallable=typecallable, **kw)
+ impl = CollectionAttributeImpl(
+ class_, key, callable_, dispatch, typecallable=typecallable, **kw
+ )
elif useobject:
- impl = ScalarObjectAttributeImpl(class_, key, callable_,
- dispatch, **kw)
+ impl = ScalarObjectAttributeImpl(
+ class_, key, callable_, dispatch, **kw
+ )
else:
impl = ScalarAttributeImpl(class_, key, callable_, dispatch, **kw)
@@ -1576,12 +1807,14 @@ def register_attribute_impl(class_, key,
return manager[key]
-def register_descriptor(class_, key, comparator=None,
- parententity=None, doc=None):
+def register_descriptor(
+ class_, key, comparator=None, parententity=None, doc=None
+):
manager = manager_of_class(class_)
- descriptor = InstrumentedAttribute(class_, key, comparator=comparator,
- parententity=parententity)
+ descriptor = InstrumentedAttribute(
+ class_, key, comparator=comparator, parententity=parententity
+ )
descriptor.__doc__ = doc
diff --git a/lib/sqlalchemy/orm/base.py b/lib/sqlalchemy/orm/base.py
index deddaa5a4..abc572d9a 100644
--- a/lib/sqlalchemy/orm/base.py
+++ b/lib/sqlalchemy/orm/base.py
@@ -15,66 +15,69 @@ from . import exc
import operator
PASSIVE_NO_RESULT = util.symbol(
- 'PASSIVE_NO_RESULT',
+ "PASSIVE_NO_RESULT",
"""Symbol returned by a loader callable or other attribute/history
retrieval operation when a value could not be determined, based
on loader callable flags.
- """
+ """,
)
ATTR_WAS_SET = util.symbol(
- 'ATTR_WAS_SET',
+ "ATTR_WAS_SET",
"""Symbol returned by a loader callable to indicate the
retrieved value, or values, were assigned to their attributes
on the target object.
- """
+ """,
)
ATTR_EMPTY = util.symbol(
- 'ATTR_EMPTY',
- """Symbol used internally to indicate an attribute had no callable."""
+ "ATTR_EMPTY",
+ """Symbol used internally to indicate an attribute had no callable.""",
)
NO_VALUE = util.symbol(
- 'NO_VALUE',
+ "NO_VALUE",
"""Symbol which may be placed as the 'previous' value of an attribute,
indicating no value was loaded for an attribute when it was modified,
and flags indicated we were not to load it.
- """
+ """,
)
NEVER_SET = util.symbol(
- 'NEVER_SET',
+ "NEVER_SET",
"""Symbol which may be placed as the 'previous' value of an attribute
indicating that the attribute had not been assigned to previously.
- """
+ """,
)
NO_CHANGE = util.symbol(
"NO_CHANGE",
"""No callables or SQL should be emitted on attribute access
and no state should change
- """, canonical=0
+ """,
+ canonical=0,
)
CALLABLES_OK = util.symbol(
"CALLABLES_OK",
"""Loader callables can be fired off if a value
is not present.
- """, canonical=1
+ """,
+ canonical=1,
)
SQL_OK = util.symbol(
"SQL_OK",
"""Loader callables can emit SQL at least on scalar value attributes.""",
- canonical=2
+ canonical=2,
)
RELATED_OBJECT_OK = util.symbol(
"RELATED_OBJECT_OK",
"""Callables can use SQL to load related objects as well
as scalar value attributes.
- """, canonical=4
+ """,
+ canonical=4,
)
INIT_OK = util.symbol(
@@ -82,111 +85,116 @@ INIT_OK = util.symbol(
"""Attributes should be initialized with a blank
value (None or an empty collection) upon get, if no other
value can be obtained.
- """, canonical=8
+ """,
+ canonical=8,
)
NON_PERSISTENT_OK = util.symbol(
"NON_PERSISTENT_OK",
"""Callables can be emitted if the parent is not persistent.""",
- canonical=16
+ canonical=16,
)
LOAD_AGAINST_COMMITTED = util.symbol(
"LOAD_AGAINST_COMMITTED",
"""Callables should use committed values as primary/foreign keys during a
load.
- """, canonical=32
+ """,
+ canonical=32,
)
NO_AUTOFLUSH = util.symbol(
"NO_AUTOFLUSH",
"""Loader callables should disable autoflush.""",
- canonical=64
+ canonical=64,
)
NO_RAISE = util.symbol(
"NO_RAISE",
"""Loader callables should not raise any assertions""",
- canonical=128
+ canonical=128,
)
# pre-packaged sets of flags used as inputs
PASSIVE_OFF = util.symbol(
"PASSIVE_OFF",
"Callables can be emitted in all cases.",
- canonical=(RELATED_OBJECT_OK | NON_PERSISTENT_OK |
- INIT_OK | CALLABLES_OK | SQL_OK)
+ canonical=(
+ RELATED_OBJECT_OK | NON_PERSISTENT_OK | INIT_OK | CALLABLES_OK | SQL_OK
+ ),
)
PASSIVE_RETURN_NEVER_SET = util.symbol(
"PASSIVE_RETURN_NEVER_SET",
"""PASSIVE_OFF ^ INIT_OK""",
- canonical=PASSIVE_OFF ^ INIT_OK
+ canonical=PASSIVE_OFF ^ INIT_OK,
)
PASSIVE_NO_INITIALIZE = util.symbol(
"PASSIVE_NO_INITIALIZE",
"PASSIVE_RETURN_NEVER_SET ^ CALLABLES_OK",
- canonical=PASSIVE_RETURN_NEVER_SET ^ CALLABLES_OK
+ canonical=PASSIVE_RETURN_NEVER_SET ^ CALLABLES_OK,
)
PASSIVE_NO_FETCH = util.symbol(
- "PASSIVE_NO_FETCH",
- "PASSIVE_OFF ^ SQL_OK",
- canonical=PASSIVE_OFF ^ SQL_OK
+ "PASSIVE_NO_FETCH", "PASSIVE_OFF ^ SQL_OK", canonical=PASSIVE_OFF ^ SQL_OK
)
PASSIVE_NO_FETCH_RELATED = util.symbol(
"PASSIVE_NO_FETCH_RELATED",
"PASSIVE_OFF ^ RELATED_OBJECT_OK",
- canonical=PASSIVE_OFF ^ RELATED_OBJECT_OK
+ canonical=PASSIVE_OFF ^ RELATED_OBJECT_OK,
)
PASSIVE_ONLY_PERSISTENT = util.symbol(
"PASSIVE_ONLY_PERSISTENT",
"PASSIVE_OFF ^ NON_PERSISTENT_OK",
- canonical=PASSIVE_OFF ^ NON_PERSISTENT_OK
+ canonical=PASSIVE_OFF ^ NON_PERSISTENT_OK,
)
-DEFAULT_MANAGER_ATTR = '_sa_class_manager'
-DEFAULT_STATE_ATTR = '_sa_instance_state'
-_INSTRUMENTOR = ('mapper', 'instrumentor')
+DEFAULT_MANAGER_ATTR = "_sa_class_manager"
+DEFAULT_STATE_ATTR = "_sa_instance_state"
+_INSTRUMENTOR = ("mapper", "instrumentor")
-EXT_CONTINUE = util.symbol('EXT_CONTINUE')
-EXT_STOP = util.symbol('EXT_STOP')
-EXT_SKIP = util.symbol('EXT_SKIP')
+EXT_CONTINUE = util.symbol("EXT_CONTINUE")
+EXT_STOP = util.symbol("EXT_STOP")
+EXT_SKIP = util.symbol("EXT_SKIP")
ONETOMANY = util.symbol(
- 'ONETOMANY',
+ "ONETOMANY",
"""Indicates the one-to-many direction for a :func:`.relationship`.
This symbol is typically used by the internals but may be exposed within
certain API features.
- """)
+ """,
+)
MANYTOONE = util.symbol(
- 'MANYTOONE',
+ "MANYTOONE",
"""Indicates the many-to-one direction for a :func:`.relationship`.
This symbol is typically used by the internals but may be exposed within
certain API features.
- """)
+ """,
+)
MANYTOMANY = util.symbol(
- 'MANYTOMANY',
+ "MANYTOMANY",
"""Indicates the many-to-many direction for a :func:`.relationship`.
This symbol is typically used by the internals but may be exposed within
certain API features.
- """)
+ """,
+)
NOT_EXTENSION = util.symbol(
- 'NOT_EXTENSION',
+ "NOT_EXTENSION",
"""Symbol indicating an :class:`InspectionAttr` that's
not part of sqlalchemy.ext.
Is assigned to the :attr:`.InspectionAttr.extension_type`
attibute.
- """)
+ """,
+)
_never_set = frozenset([NEVER_SET])
@@ -207,6 +215,7 @@ def _generative(*assertions):
assertion(self, fn.__name__)
fn(self, *args[1:], **kw)
return self
+
return generate
@@ -215,9 +224,10 @@ def _generative(*assertions):
def manager_of_class(cls):
return cls.__dict__.get(DEFAULT_MANAGER_ATTR, None)
+
instance_state = operator.attrgetter(DEFAULT_STATE_ATTR)
-instance_dict = operator.attrgetter('__dict__')
+instance_dict = operator.attrgetter("__dict__")
def instance_str(instance):
@@ -232,7 +242,7 @@ def state_str(state):
if state is None:
return "None"
else:
- return '<%s at 0x%x>' % (state.class_.__name__, id(state.obj()))
+ return "<%s at 0x%x>" % (state.class_.__name__, id(state.obj()))
def state_class_str(state):
@@ -243,7 +253,7 @@ def state_class_str(state):
if state is None:
return "None"
else:
- return '<%s>' % (state.class_.__name__, )
+ return "<%s>" % (state.class_.__name__,)
def attribute_str(instance, attribute):
@@ -335,15 +345,15 @@ def _is_mapped_class(entity):
"""
insp = inspection.inspect(entity, False)
- return insp is not None and \
- not insp.is_clause_element and \
- (
- insp.is_mapper or insp.is_aliased_class
- )
+ return (
+ insp is not None
+ and not insp.is_clause_element
+ and (insp.is_mapper or insp.is_aliased_class)
+ )
def _attr_as_key(attr):
- if hasattr(attr, 'key'):
+ if hasattr(attr, "key"):
return attr.key
else:
return expression._column_as_key(attr)
@@ -351,7 +361,7 @@ def _attr_as_key(attr):
def _orm_columns(entity):
insp = inspection.inspect(entity, False)
- if hasattr(insp, 'selectable') and hasattr(insp.selectable, 'c'):
+ if hasattr(insp, "selectable") and hasattr(insp.selectable, "c"):
return [c for c in insp.selectable.c]
else:
return [entity]
@@ -359,8 +369,7 @@ def _orm_columns(entity):
def _is_aliased_class(entity):
insp = inspection.inspect(entity, False)
- return insp is not None and \
- getattr(insp, "is_aliased_class", False)
+ return insp is not None and getattr(insp, "is_aliased_class", False)
def _entity_descriptor(entity, key):
@@ -386,11 +395,11 @@ def _entity_descriptor(entity, key):
return getattr(entity, key)
except AttributeError:
raise sa_exc.InvalidRequestError(
- "Entity '%s' has no property '%s'" %
- (description, key)
+ "Entity '%s' has no property '%s'" % (description, key)
)
-_state_mapper = util.dottedgetter('manager.mapper')
+
+_state_mapper = util.dottedgetter("manager.mapper")
@inspection._inspects(type)
@@ -429,7 +438,8 @@ def class_mapper(class_, configure=True):
if mapper is None:
if not isinstance(class_, type):
raise sa_exc.ArgumentError(
- "Class object expected, got '%r'." % (class_, ))
+ "Class object expected, got '%r'." % (class_,)
+ )
raise exc.UnmappedClassError(class_)
else:
return mapper
@@ -449,6 +459,7 @@ class InspectionAttr(object):
here intact for forwards-compatibility.
"""
+
__slots__ = ()
is_selectable = False
@@ -551,4 +562,5 @@ class _MappedAttribute(object):
attributes.
"""
+
__slots__ = ()
diff --git a/lib/sqlalchemy/orm/collections.py b/lib/sqlalchemy/orm/collections.py
index 54c29bb5e..be9291741 100644
--- a/lib/sqlalchemy/orm/collections.py
+++ b/lib/sqlalchemy/orm/collections.py
@@ -113,9 +113,13 @@ from . import base
from sqlalchemy.util.compat import inspect_getargspec
-__all__ = ['collection', 'collection_adapter',
- 'mapped_collection', 'column_mapped_collection',
- 'attribute_mapped_collection']
+__all__ = [
+ "collection",
+ "collection_adapter",
+ "mapped_collection",
+ "column_mapped_collection",
+ "attribute_mapped_collection",
+]
__instrumentation_mutex = util.threading.Lock()
@@ -172,10 +176,12 @@ class _SerializableColumnGetter(object):
def __call__(self, value):
state = base.instance_state(value)
m = base._state_mapper(state)
- key = [m._get_state_attr_by_column(
- state, state.dict,
- m.mapped_table.columns[k])
- for k in self.colkeys]
+ key = [
+ m._get_state_attr_by_column(
+ state, state.dict, m.mapped_table.columns[k]
+ )
+ for k in self.colkeys
+ ]
if self.composite:
return tuple(key)
else:
@@ -208,16 +214,15 @@ class _SerializableColumnGetterV2(_PlainColumnGetter):
return None
else:
return c.table.key
+
colkeys = [(c.key, _table_key(c)) for c in cols]
return _SerializableColumnGetterV2, (colkeys,)
def _cols(self, mapper):
cols = []
- metadata = getattr(mapper.local_table, 'metadata', None)
+ metadata = getattr(mapper.local_table, "metadata", None)
for (ckey, tkey) in self.colkeys:
- if tkey is None or \
- metadata is None or \
- tkey not in metadata:
+ if tkey is None or metadata is None or tkey not in metadata:
cols.append(mapper.local_table.c[ckey])
else:
cols.append(metadata.tables[tkey].c[ckey])
@@ -237,9 +242,10 @@ def column_mapped_collection(mapping_spec):
after a session flush.
"""
- cols = [expression._only_column_elements(q, "mapping_spec")
- for q in util.to_list(mapping_spec)
- ]
+ cols = [
+ expression._only_column_elements(q, "mapping_spec")
+ for q in util.to_list(mapping_spec)
+ ]
keyfunc = _PlainColumnGetter(cols)
return lambda: MappedCollection(keyfunc)
@@ -253,7 +259,7 @@ class _SerializableAttrGetter(object):
return self.getter(target)
def __reduce__(self):
- return _SerializableAttrGetter, (self.name, )
+ return _SerializableAttrGetter, (self.name,)
def attribute_mapped_collection(attr_name):
@@ -311,6 +317,7 @@ class collection(object):
def popitem(self): ...
"""
+
# Bundled as a class solely for ease of use: packaging, doc strings,
# importability.
@@ -355,7 +362,7 @@ class collection(object):
promulgation to collection events.
"""
- fn._sa_instrument_role = 'appender'
+ fn._sa_instrument_role = "appender"
return fn
@staticmethod
@@ -382,7 +389,7 @@ class collection(object):
promulgation to collection events.
"""
- fn._sa_instrument_role = 'remover'
+ fn._sa_instrument_role = "remover"
return fn
@staticmethod
@@ -396,7 +403,7 @@ class collection(object):
def __iter__(self): ...
"""
- fn._sa_instrument_role = 'iterator'
+ fn._sa_instrument_role = "iterator"
return fn
@staticmethod
@@ -435,7 +442,7 @@ class collection(object):
and :meth:`.AttributeEvents.dispose_collection` handlers.
"""
- fn._sa_instrument_role = 'linker'
+ fn._sa_instrument_role = "linker"
return fn
link = linker
@@ -472,7 +479,7 @@ class collection(object):
validation on the values about to be assigned.
"""
- fn._sa_instrument_role = 'converter'
+ fn._sa_instrument_role = "converter"
return fn
@staticmethod
@@ -491,9 +498,11 @@ class collection(object):
def do_stuff(self, thing, entity=None): ...
"""
+
def decorator(fn):
- fn._sa_instrument_before = ('fire_append_event', arg)
+ fn._sa_instrument_before = ("fire_append_event", arg)
return fn
+
return decorator
@staticmethod
@@ -511,10 +520,12 @@ class collection(object):
def __setitem__(self, index, item): ...
"""
+
def decorator(fn):
- fn._sa_instrument_before = ('fire_append_event', arg)
- fn._sa_instrument_after = 'fire_remove_event'
+ fn._sa_instrument_before = ("fire_append_event", arg)
+ fn._sa_instrument_after = "fire_remove_event"
return fn
+
return decorator
@staticmethod
@@ -533,9 +544,11 @@ class collection(object):
collection.removes_return.
"""
+
def decorator(fn):
- fn._sa_instrument_before = ('fire_remove_event', arg)
+ fn._sa_instrument_before = ("fire_remove_event", arg)
return fn
+
return decorator
@staticmethod
@@ -553,13 +566,15 @@ class collection(object):
collection.remove.
"""
+
def decorator(fn):
- fn._sa_instrument_after = 'fire_remove_event'
+ fn._sa_instrument_after = "fire_remove_event"
return fn
+
return decorator
-collection_adapter = operator.attrgetter('_sa_adapter')
+collection_adapter = operator.attrgetter("_sa_adapter")
"""Fetch the :class:`.CollectionAdapter` for a collection."""
@@ -577,7 +592,13 @@ class CollectionAdapter(object):
"""
__slots__ = (
- 'attr', '_key', '_data', 'owner_state', '_converter', 'invalidated')
+ "attr",
+ "_key",
+ "_data",
+ "owner_state",
+ "_converter",
+ "invalidated",
+ )
def __init__(self, attr, owner_state, data):
self.attr = attr
@@ -676,9 +697,8 @@ class CollectionAdapter(object):
if self.invalidated:
self._warn_invalidated()
return self.attr.fire_append_event(
- self.owner_state,
- self.owner_state.dict,
- item, initiator)
+ self.owner_state, self.owner_state.dict, item, initiator
+ )
else:
return item
@@ -694,9 +714,8 @@ class CollectionAdapter(object):
if self.invalidated:
self._warn_invalidated()
self.attr.fire_remove_event(
- self.owner_state,
- self.owner_state.dict,
- item, initiator)
+ self.owner_state, self.owner_state.dict, item, initiator
+ )
def fire_pre_remove_event(self, initiator=None):
"""Notify that an entity is about to be removed from the collection.
@@ -708,25 +727,26 @@ class CollectionAdapter(object):
if self.invalidated:
self._warn_invalidated()
self.attr.fire_pre_remove_event(
- self.owner_state,
- self.owner_state.dict,
- initiator=initiator)
+ self.owner_state, self.owner_state.dict, initiator=initiator
+ )
def __getstate__(self):
- return {'key': self._key,
- 'owner_state': self.owner_state,
- 'owner_cls': self.owner_state.class_,
- 'data': self.data,
- 'invalidated': self.invalidated}
+ return {
+ "key": self._key,
+ "owner_state": self.owner_state,
+ "owner_cls": self.owner_state.class_,
+ "data": self.data,
+ "invalidated": self.invalidated,
+ }
def __setstate__(self, d):
- self._key = d['key']
- self.owner_state = d['owner_state']
- self._data = weakref.ref(d['data'])
- self._converter = d['data']._sa_converter
- d['data']._sa_adapter = self
- self.invalidated = d['invalidated']
- self.attr = getattr(d['owner_cls'], self._key).impl
+ self._key = d["key"]
+ self.owner_state = d["owner_state"]
+ self._data = weakref.ref(d["data"])
+ self._converter = d["data"]._sa_converter
+ d["data"]._sa_adapter = self
+ self.invalidated = d["invalidated"]
+ self.attr = getattr(d["owner_cls"], self._key).impl
def bulk_replace(values, existing_adapter, new_adapter, initiator=None):
@@ -796,7 +816,7 @@ def prepare_instrumentation(factory):
# Instrument the class if needed.
if __instrumentation_mutex.acquire():
try:
- if getattr(cls, '_sa_instrumented', None) != id(cls):
+ if getattr(cls, "_sa_instrumented", None) != id(cls):
_instrument_class(cls)
finally:
__instrumentation_mutex.release()
@@ -829,10 +849,11 @@ def _instrument_class(cls):
# In the normal call flow, a request for any of the 3 basic collection
# types is transformed into one of our trivial subclasses
# (e.g. InstrumentedList). Catch anything else that sneaks in here...
- if cls.__module__ == '__builtin__':
+ if cls.__module__ == "__builtin__":
raise sa_exc.ArgumentError(
"Can not instrument a built-in type. Use a "
- "subclass, even a trivial one.")
+ "subclass, even a trivial one."
+ )
roles, methods = _locate_roles_and_methods(cls)
@@ -858,25 +879,30 @@ def _locate_roles_and_methods(cls):
continue
# note role declarations
- if hasattr(method, '_sa_instrument_role'):
+ if hasattr(method, "_sa_instrument_role"):
role = method._sa_instrument_role
- assert role in ('appender', 'remover', 'iterator',
- 'linker', 'converter')
+ assert role in (
+ "appender",
+ "remover",
+ "iterator",
+ "linker",
+ "converter",
+ )
roles.setdefault(role, name)
# transfer instrumentation requests from decorated function
# to the combined queue
before, after = None, None
- if hasattr(method, '_sa_instrument_before'):
+ if hasattr(method, "_sa_instrument_before"):
op, argument = method._sa_instrument_before
- assert op in ('fire_append_event', 'fire_remove_event')
+ assert op in ("fire_append_event", "fire_remove_event")
before = op, argument
- if hasattr(method, '_sa_instrument_after'):
+ if hasattr(method, "_sa_instrument_after"):
op = method._sa_instrument_after
- assert op in ('fire_append_event', 'fire_remove_event')
+ assert op in ("fire_append_event", "fire_remove_event")
after = op
if before:
- methods[name] = before + (after, )
+ methods[name] = before + (after,)
elif after:
methods[name] = None, None, after
return roles, methods
@@ -898,8 +924,11 @@ def _setup_canned_roles(cls, roles, methods):
# apply ABC auto-decoration to methods that need it
for method, decorator in decorators.items():
fn = getattr(cls, method, None)
- if (fn and method not in methods and
- not hasattr(fn, '_sa_instrumented')):
+ if (
+ fn
+ and method not in methods
+ and not hasattr(fn, "_sa_instrumented")
+ ):
setattr(cls, method, decorator(fn))
@@ -908,26 +937,31 @@ def _assert_required_roles(cls, roles, methods):
needed
"""
- if 'appender' not in roles or not hasattr(cls, roles['appender']):
+ if "appender" not in roles or not hasattr(cls, roles["appender"]):
raise sa_exc.ArgumentError(
"Type %s must elect an appender method to be "
- "a collection class" % cls.__name__)
- elif (roles['appender'] not in methods and
- not hasattr(getattr(cls, roles['appender']), '_sa_instrumented')):
- methods[roles['appender']] = ('fire_append_event', 1, None)
-
- if 'remover' not in roles or not hasattr(cls, roles['remover']):
+ "a collection class" % cls.__name__
+ )
+ elif roles["appender"] not in methods and not hasattr(
+ getattr(cls, roles["appender"]), "_sa_instrumented"
+ ):
+ methods[roles["appender"]] = ("fire_append_event", 1, None)
+
+ if "remover" not in roles or not hasattr(cls, roles["remover"]):
raise sa_exc.ArgumentError(
"Type %s must elect a remover method to be "
- "a collection class" % cls.__name__)
- elif (roles['remover'] not in methods and
- not hasattr(getattr(cls, roles['remover']), '_sa_instrumented')):
- methods[roles['remover']] = ('fire_remove_event', 1, None)
-
- if 'iterator' not in roles or not hasattr(cls, roles['iterator']):
+ "a collection class" % cls.__name__
+ )
+ elif roles["remover"] not in methods and not hasattr(
+ getattr(cls, roles["remover"]), "_sa_instrumented"
+ ):
+ methods[roles["remover"]] = ("fire_remove_event", 1, None)
+
+ if "iterator" not in roles or not hasattr(cls, roles["iterator"]):
raise sa_exc.ArgumentError(
"Type %s must elect an iterator method to be "
- "a collection class" % cls.__name__)
+ "a collection class" % cls.__name__
+ )
def _set_collection_attributes(cls, roles, methods):
@@ -936,16 +970,20 @@ def _set_collection_attributes(cls, roles, methods):
"""
for method_name, (before, argument, after) in methods.items():
- setattr(cls, method_name,
- _instrument_membership_mutator(getattr(cls, method_name),
- before, argument, after))
+ setattr(
+ cls,
+ method_name,
+ _instrument_membership_mutator(
+ getattr(cls, method_name), before, argument, after
+ ),
+ )
# intern the role map
for role, method_name in roles.items():
- setattr(cls, '_sa_%s' % role, getattr(cls, method_name))
+ setattr(cls, "_sa_%s" % role, getattr(cls, method_name))
cls._sa_adapter = None
- if not hasattr(cls, '_sa_converter'):
+ if not hasattr(cls, "_sa_converter"):
cls._sa_converter = None
cls._sa_instrumented = id(cls)
@@ -972,7 +1010,8 @@ def _instrument_membership_mutator(method, before, argument, after):
if pos_arg is None:
if named_arg not in kw:
raise sa_exc.ArgumentError(
- "Missing argument %s" % argument)
+ "Missing argument %s" % argument
+ )
value = kw[named_arg]
else:
if len(args) > pos_arg:
@@ -981,9 +1020,10 @@ def _instrument_membership_mutator(method, before, argument, after):
value = kw[named_arg]
else:
raise sa_exc.ArgumentError(
- "Missing argument %s" % argument)
+ "Missing argument %s" % argument
+ )
- initiator = kw.pop('_sa_initiator', None)
+ initiator = kw.pop("_sa_initiator", None)
if initiator is False:
executor = None
else:
@@ -1055,6 +1095,7 @@ def _list_decorators():
def append(self, item, _sa_initiator=None):
item = __set(self, item, _sa_initiator)
fn(self, item)
+
_tidy(append)
return append
@@ -1063,6 +1104,7 @@ def _list_decorators():
__del(self, value, _sa_initiator)
# testlib.pragma exempt:__eq__
fn(self, value)
+
_tidy(remove)
return remove
@@ -1070,6 +1112,7 @@ def _list_decorators():
def insert(self, index, value):
value = __set(self, value)
fn(self, index, value)
+
_tidy(insert)
return insert
@@ -1106,10 +1149,12 @@ def _list_decorators():
if len(value) != len(rng):
raise ValueError(
"attempt to assign sequence of size %s to "
- "extended slice of size %s" % (len(value),
- len(rng)))
+ "extended slice of size %s"
+ % (len(value), len(rng))
+ )
for i, item in zip(rng, value):
self.__setitem__(i, item)
+
_tidy(__setitem__)
return __setitem__
@@ -1126,16 +1171,19 @@ def _list_decorators():
for item in self[index]:
__del(self, item)
fn(self, index)
+
_tidy(__delitem__)
return __delitem__
if util.py2k:
+
def __setslice__(fn):
def __setslice__(self, start, end, values):
for value in self[start:end]:
__del(self, value)
values = [__set(self, value) for value in values]
fn(self, start, end, values)
+
_tidy(__setslice__)
return __setslice__
@@ -1144,6 +1192,7 @@ def _list_decorators():
for value in self[start:end]:
__del(self, value)
fn(self, start, end)
+
_tidy(__delslice__)
return __delslice__
@@ -1151,6 +1200,7 @@ def _list_decorators():
def extend(self, iterable):
for value in iterable:
self.append(value)
+
_tidy(extend)
return extend
@@ -1161,6 +1211,7 @@ def _list_decorators():
for value in iterable:
self.append(value)
return self
+
_tidy(__iadd__)
return __iadd__
@@ -1170,15 +1221,18 @@ def _list_decorators():
item = fn(self, index)
__del(self, item)
return item
+
_tidy(pop)
return pop
if not util.py2k:
+
def clear(fn):
def clear(self, index=-1):
for item in self:
__del(self, item)
fn(self)
+
_tidy(clear)
return clear
@@ -1188,7 +1242,7 @@ def _list_decorators():
# desired. hard to imagine a use case for __imul__, though.
l = locals().copy()
- l.pop('_tidy')
+ l.pop("_tidy")
return l
@@ -1199,7 +1253,7 @@ def _dict_decorators():
fn._sa_instrumented = True
fn.__doc__ = getattr(dict, fn.__name__).__doc__
- Unspecified = util.symbol('Unspecified')
+ Unspecified = util.symbol("Unspecified")
def __setitem__(fn):
def __setitem__(self, key, value, _sa_initiator=None):
@@ -1207,6 +1261,7 @@ def _dict_decorators():
__del(self, self[key], _sa_initiator)
value = __set(self, value, _sa_initiator)
fn(self, key, value)
+
_tidy(__setitem__)
return __setitem__
@@ -1215,6 +1270,7 @@ def _dict_decorators():
if key in self:
__del(self, self[key], _sa_initiator)
fn(self, key)
+
_tidy(__delitem__)
return __delitem__
@@ -1223,6 +1279,7 @@ def _dict_decorators():
for key in self:
__del(self, self[key])
fn(self)
+
_tidy(clear)
return clear
@@ -1237,6 +1294,7 @@ def _dict_decorators():
if _to_del:
__del(self, item)
return item
+
_tidy(pop)
return pop
@@ -1246,6 +1304,7 @@ def _dict_decorators():
item = fn(self)
__del(self, item[1])
return item
+
_tidy(popitem)
return popitem
@@ -1256,16 +1315,16 @@ def _dict_decorators():
return default
else:
return self.__getitem__(key)
+
_tidy(setdefault)
return setdefault
def update(fn):
def update(self, __other=Unspecified, **kw):
if __other is not Unspecified:
- if hasattr(__other, 'keys'):
+ if hasattr(__other, "keys"):
for key in list(__other):
- if (key not in self or
- self[key] is not __other[key]):
+ if key not in self or self[key] is not __other[key]:
self[key] = __other[key]
else:
for key, value in __other:
@@ -1274,14 +1333,16 @@ def _dict_decorators():
for key in kw:
if key not in self or self[key] is not kw[key]:
self[key] = kw[key]
+
_tidy(update)
return update
l = locals().copy()
- l.pop('_tidy')
- l.pop('Unspecified')
+ l.pop("_tidy")
+ l.pop("Unspecified")
return l
+
_set_binop_bases = (set, frozenset)
@@ -1293,8 +1354,10 @@ def _set_binops_check_strict(self, obj):
def _set_binops_check_loose(self, obj):
"""Allow anything set-like to participate in set binops."""
- return (isinstance(obj, _set_binop_bases + (self.__class__,)) or
- util.duck_type_collection(obj) == set)
+ return (
+ isinstance(obj, _set_binop_bases + (self.__class__,))
+ or util.duck_type_collection(obj) == set
+ )
def _set_decorators():
@@ -1304,7 +1367,7 @@ def _set_decorators():
fn._sa_instrumented = True
fn.__doc__ = getattr(set, fn.__name__).__doc__
- Unspecified = util.symbol('Unspecified')
+ Unspecified = util.symbol("Unspecified")
def add(fn):
def add(self, value, _sa_initiator=None):
@@ -1312,6 +1375,7 @@ def _set_decorators():
value = __set(self, value, _sa_initiator)
# testlib.pragma exempt:__hash__
fn(self, value)
+
_tidy(add)
return add
@@ -1322,6 +1386,7 @@ def _set_decorators():
__del(self, value, _sa_initiator)
# testlib.pragma exempt:__hash__
fn(self, value)
+
_tidy(discard)
return discard
@@ -1332,6 +1397,7 @@ def _set_decorators():
__del(self, value, _sa_initiator)
# testlib.pragma exempt:__hash__
fn(self, value)
+
_tidy(remove)
return remove
@@ -1343,6 +1409,7 @@ def _set_decorators():
# that will be popped before pop is called.
__del(self, item)
return item
+
_tidy(pop)
return pop
@@ -1350,6 +1417,7 @@ def _set_decorators():
def clear(self):
for item in list(self):
self.remove(item)
+
_tidy(clear)
return clear
@@ -1357,6 +1425,7 @@ def _set_decorators():
def update(self, value):
for item in value:
self.add(item)
+
_tidy(update)
return update
@@ -1367,6 +1436,7 @@ def _set_decorators():
for item in value:
self.add(item)
return self
+
_tidy(__ior__)
return __ior__
@@ -1374,6 +1444,7 @@ def _set_decorators():
def difference_update(self, value):
for item in value:
self.discard(item)
+
_tidy(difference_update)
return difference_update
@@ -1384,6 +1455,7 @@ def _set_decorators():
for item in value:
self.discard(item)
return self
+
_tidy(__isub__)
return __isub__
@@ -1396,6 +1468,7 @@ def _set_decorators():
self.remove(item)
for item in add:
self.add(item)
+
_tidy(intersection_update)
return intersection_update
@@ -1411,6 +1484,7 @@ def _set_decorators():
for item in add:
self.add(item)
return self
+
_tidy(__iand__)
return __iand__
@@ -1423,6 +1497,7 @@ def _set_decorators():
self.remove(item)
for item in add:
self.add(item)
+
_tidy(symmetric_difference_update)
return symmetric_difference_update
@@ -1438,12 +1513,13 @@ def _set_decorators():
for item in add:
self.add(item)
return self
+
_tidy(__ixor__)
return __ixor__
l = locals().copy()
- l.pop('_tidy')
- l.pop('Unspecified')
+ l.pop("_tidy")
+ l.pop("Unspecified")
return l
@@ -1467,18 +1543,17 @@ __canned_instrumentation = {
__interfaces = {
list: (
- {'appender': 'append', 'remover': 'remove',
- 'iterator': '__iter__'}, _list_decorators()
+ {"appender": "append", "remover": "remove", "iterator": "__iter__"},
+ _list_decorators(),
+ ),
+ set: (
+ {"appender": "add", "remover": "remove", "iterator": "__iter__"},
+ _set_decorators(),
),
-
- set: ({'appender': 'add',
- 'remover': 'remove',
- 'iterator': '__iter__'}, _set_decorators()
- ),
-
# decorators are required for dicts and object collections.
- dict: ({'iterator': 'values'}, _dict_decorators()) if util.py3k
- else ({'iterator': 'itervalues'}, _dict_decorators()),
+ dict: ({"iterator": "values"}, _dict_decorators())
+ if util.py3k
+ else ({"iterator": "itervalues"}, _dict_decorators()),
}
@@ -1529,10 +1604,11 @@ class MappedCollection(dict):
"Can not remove '%s': collection holds '%s' for key '%s'. "
"Possible cause: is the MappedCollection key function "
"based on mutable properties or properties that only obtain "
- "values after flush?" %
- (value, self[key], key))
+ "values after flush?" % (value, self[key], key)
+ )
self.__delitem__(key, _sa_initiator)
+
# ensure instrumentation is associated with
# these built-in classes; if a user-defined class
# subclasses these and uses @internally_instrumented,
diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py
index 960b9e5d5..cba4d2141 100644
--- a/lib/sqlalchemy/orm/dependency.py
+++ b/lib/sqlalchemy/orm/dependency.py
@@ -10,8 +10,7 @@
"""
from .. import sql, util, exc as sa_exc
-from . import attributes, exc, sync, unitofwork, \
- util as mapperutil
+from . import attributes, exc, sync, unitofwork, util as mapperutil
from .interfaces import ONETOMANY, MANYTOONE, MANYTOMANY
@@ -41,8 +40,8 @@ class DependencyProcessor(object):
raise sa_exc.ArgumentError(
"Can't build a DependencyProcessor for relationship %s. "
"No target attributes to populate between parent and "
- "child are present" %
- self.prop)
+ "child are present" % self.prop
+ )
@classmethod
def from_relationship(cls, prop):
@@ -70,31 +69,28 @@ class DependencyProcessor(object):
before_delete = unitofwork.ProcessAll(uow, self, True, True)
parent_saves = unitofwork.SaveUpdateAll(
- uow,
- self.parent.primary_base_mapper
+ uow, self.parent.primary_base_mapper
)
child_saves = unitofwork.SaveUpdateAll(
- uow,
- self.mapper.primary_base_mapper
+ uow, self.mapper.primary_base_mapper
)
parent_deletes = unitofwork.DeleteAll(
- uow,
- self.parent.primary_base_mapper
+ uow, self.parent.primary_base_mapper
)
child_deletes = unitofwork.DeleteAll(
- uow,
- self.mapper.primary_base_mapper
+ uow, self.mapper.primary_base_mapper
)
- self.per_property_dependencies(uow,
- parent_saves,
- child_saves,
- parent_deletes,
- child_deletes,
- after_save,
- before_delete
- )
+ self.per_property_dependencies(
+ uow,
+ parent_saves,
+ child_saves,
+ parent_deletes,
+ child_deletes,
+ after_save,
+ before_delete,
+ )
def per_state_flush_actions(self, uow, states, isdelete):
"""establish actions and dependencies related to a flush.
@@ -130,9 +126,7 @@ class DependencyProcessor(object):
# child side is not part of the cycle, so we will link per-state
# actions to the aggregate "saves", "deletes" actions
- child_actions = [
- (child_saves, False), (child_deletes, True)
- ]
+ child_actions = [(child_saves, False), (child_deletes, True)]
child_in_cycles = False
else:
child_in_cycles = True
@@ -140,15 +134,13 @@ class DependencyProcessor(object):
# check if the "parent" side is part of the cycle
if not isdelete:
parent_saves = unitofwork.SaveUpdateAll(
- uow,
- self.parent.base_mapper)
+ uow, self.parent.base_mapper
+ )
parent_deletes = before_delete = None
if parent_saves in uow.cycles:
parent_in_cycles = True
else:
- parent_deletes = unitofwork.DeleteAll(
- uow,
- self.parent.base_mapper)
+ parent_deletes = unitofwork.DeleteAll(uow, self.parent.base_mapper)
parent_saves = after_save = None
if parent_deletes in uow.cycles:
parent_in_cycles = True
@@ -160,17 +152,18 @@ class DependencyProcessor(object):
# by a preprocessor on this state/attribute. In the
# case of deletes we may try to load missing items here as well.
sum_ = state.manager[self.key].impl.get_all_pending(
- state, state.dict,
+ state,
+ state.dict,
self._passive_delete_flag
if isdelete
- else attributes.PASSIVE_NO_INITIALIZE)
+ else attributes.PASSIVE_NO_INITIALIZE,
+ )
if not sum_:
continue
if isdelete:
- before_delete = unitofwork.ProcessState(uow,
- self, True, state)
+ before_delete = unitofwork.ProcessState(uow, self, True, state)
if parent_in_cycles:
parent_deletes = unitofwork.DeleteState(uow, state)
else:
@@ -188,21 +181,28 @@ class DependencyProcessor(object):
if deleted:
child_action = (
unitofwork.DeleteState(uow, child_state),
- True)
+ True,
+ )
else:
child_action = (
unitofwork.SaveUpdateState(uow, child_state),
- False)
+ False,
+ )
child_actions.append(child_action)
# establish dependencies between our possibly per-state
# parent action and our possibly per-state child action.
for child_action, childisdelete in child_actions:
- self.per_state_dependencies(uow, parent_saves,
- parent_deletes,
- child_action,
- after_save, before_delete,
- isdelete, childisdelete)
+ self.per_state_dependencies(
+ uow,
+ parent_saves,
+ parent_deletes,
+ child_action,
+ after_save,
+ before_delete,
+ isdelete,
+ childisdelete,
+ )
def presort_deletes(self, uowcommit, states):
return False
@@ -228,76 +228,74 @@ class DependencyProcessor(object):
# TODO: add a high speed method
# to InstanceState which returns: attribute
# has a non-None value, or had one
- history = uowcommit.get_attribute_history(
- s,
- self.key,
- passive)
+ history = uowcommit.get_attribute_history(s, self.key, passive)
if history and not history.empty():
return True
else:
- return states and \
- not self.prop._is_self_referential and \
- self.mapper in uowcommit.mappers
+ return (
+ states
+ and not self.prop._is_self_referential
+ and self.mapper in uowcommit.mappers
+ )
def _verify_canload(self, state):
if self.prop.uselist and state is None:
raise exc.FlushError(
"Can't flush None value found in "
- "collection %s" % (self.prop, ))
- elif state is not None and \
- not self.mapper._canload(
- state, allow_subtypes=not self.enable_typechecks):
+ "collection %s" % (self.prop,)
+ )
+ elif state is not None and not self.mapper._canload(
+ state, allow_subtypes=not self.enable_typechecks
+ ):
if self.mapper._canload(state, allow_subtypes=True):
- raise exc.FlushError('Attempting to flush an item of type '
- '%(x)s as a member of collection '
- '"%(y)s". Expected an object of type '
- '%(z)s or a polymorphic subclass of '
- 'this type. If %(x)s is a subclass of '
- '%(z)s, configure mapper "%(zm)s" to '
- 'load this subtype polymorphically, or '
- 'set enable_typechecks=False to allow '
- 'any subtype to be accepted for flush. '
- % {
- 'x': state.class_,
- 'y': self.prop,
- 'z': self.mapper.class_,
- 'zm': self.mapper,
- })
+ raise exc.FlushError(
+ "Attempting to flush an item of type "
+ "%(x)s as a member of collection "
+ '"%(y)s". Expected an object of type '
+ "%(z)s or a polymorphic subclass of "
+ "this type. If %(x)s is a subclass of "
+ '%(z)s, configure mapper "%(zm)s" to '
+ "load this subtype polymorphically, or "
+ "set enable_typechecks=False to allow "
+ "any subtype to be accepted for flush. "
+ % {
+ "x": state.class_,
+ "y": self.prop,
+ "z": self.mapper.class_,
+ "zm": self.mapper,
+ }
+ )
else:
raise exc.FlushError(
- 'Attempting to flush an item of type '
- '%(x)s as a member of collection '
+ "Attempting to flush an item of type "
+ "%(x)s as a member of collection "
'"%(y)s". Expected an object of type '
- '%(z)s or a polymorphic subclass of '
- 'this type.' % {
- 'x': state.class_,
- 'y': self.prop,
- 'z': self.mapper.class_,
- })
-
- def _synchronize(self, state, child, associationrow,
- clearkeys, uowcommit):
+ "%(z)s or a polymorphic subclass of "
+ "this type."
+ % {
+ "x": state.class_,
+ "y": self.prop,
+ "z": self.mapper.class_,
+ }
+ )
+
+ def _synchronize(self, state, child, associationrow, clearkeys, uowcommit):
raise NotImplementedError()
def _get_reversed_processed_set(self, uow):
if not self.prop._reverse_property:
return None
- process_key = tuple(sorted(
- [self.key] +
- [p.key for p in self.prop._reverse_property]
- ))
- return uow.memo(
- ('reverse_key', process_key),
- set
+ process_key = tuple(
+ sorted([self.key] + [p.key for p in self.prop._reverse_property])
)
+ return uow.memo(("reverse_key", process_key), set)
def _post_update(self, state, uowcommit, related, is_m2o_delete=False):
for x in related:
if not is_m2o_delete or x is not None:
uowcommit.register_post_update(
- state,
- [r for l, r in self.prop.synchronize_pairs]
+ state, [r for l, r in self.prop.synchronize_pairs]
)
break
@@ -309,114 +307,126 @@ class DependencyProcessor(object):
class OneToManyDP(DependencyProcessor):
-
- def per_property_dependencies(self, uow, parent_saves,
- child_saves,
- parent_deletes,
- child_deletes,
- after_save,
- before_delete,
- ):
+ def per_property_dependencies(
+ self,
+ uow,
+ parent_saves,
+ child_saves,
+ parent_deletes,
+ child_deletes,
+ after_save,
+ before_delete,
+ ):
if self.post_update:
child_post_updates = unitofwork.PostUpdateAll(
- uow,
- self.mapper.primary_base_mapper,
- False)
+ uow, self.mapper.primary_base_mapper, False
+ )
child_pre_updates = unitofwork.PostUpdateAll(
- uow,
- self.mapper.primary_base_mapper,
- True)
-
- uow.dependencies.update([
- (child_saves, after_save),
- (parent_saves, after_save),
- (after_save, child_post_updates),
-
- (before_delete, child_pre_updates),
- (child_pre_updates, parent_deletes),
- (child_pre_updates, child_deletes),
-
- ])
+ uow, self.mapper.primary_base_mapper, True
+ )
+
+ uow.dependencies.update(
+ [
+ (child_saves, after_save),
+ (parent_saves, after_save),
+ (after_save, child_post_updates),
+ (before_delete, child_pre_updates),
+ (child_pre_updates, parent_deletes),
+ (child_pre_updates, child_deletes),
+ ]
+ )
else:
- uow.dependencies.update([
- (parent_saves, after_save),
- (after_save, child_saves),
- (after_save, child_deletes),
-
- (child_saves, parent_deletes),
- (child_deletes, parent_deletes),
-
- (before_delete, child_saves),
- (before_delete, child_deletes),
- ])
-
- def per_state_dependencies(self, uow,
- save_parent,
- delete_parent,
- child_action,
- after_save, before_delete,
- isdelete, childisdelete):
+ uow.dependencies.update(
+ [
+ (parent_saves, after_save),
+ (after_save, child_saves),
+ (after_save, child_deletes),
+ (child_saves, parent_deletes),
+ (child_deletes, parent_deletes),
+ (before_delete, child_saves),
+ (before_delete, child_deletes),
+ ]
+ )
+
+ def per_state_dependencies(
+ self,
+ uow,
+ save_parent,
+ delete_parent,
+ child_action,
+ after_save,
+ before_delete,
+ isdelete,
+ childisdelete,
+ ):
if self.post_update:
child_post_updates = unitofwork.PostUpdateAll(
- uow,
- self.mapper.primary_base_mapper,
- False)
+ uow, self.mapper.primary_base_mapper, False
+ )
child_pre_updates = unitofwork.PostUpdateAll(
- uow,
- self.mapper.primary_base_mapper,
- True)
+ uow, self.mapper.primary_base_mapper, True
+ )
# TODO: this whole block is not covered
# by any tests
if not isdelete:
if childisdelete:
- uow.dependencies.update([
- (child_action, after_save),
- (after_save, child_post_updates),
- ])
+ uow.dependencies.update(
+ [
+ (child_action, after_save),
+ (after_save, child_post_updates),
+ ]
+ )
else:
- uow.dependencies.update([
- (save_parent, after_save),
- (child_action, after_save),
- (after_save, child_post_updates),
- ])
+ uow.dependencies.update(
+ [
+ (save_parent, after_save),
+ (child_action, after_save),
+ (after_save, child_post_updates),
+ ]
+ )
else:
if childisdelete:
- uow.dependencies.update([
- (before_delete, child_pre_updates),
- (child_pre_updates, delete_parent),
- ])
+ uow.dependencies.update(
+ [
+ (before_delete, child_pre_updates),
+ (child_pre_updates, delete_parent),
+ ]
+ )
else:
- uow.dependencies.update([
- (before_delete, child_pre_updates),
- (child_pre_updates, delete_parent),
- ])
+ uow.dependencies.update(
+ [
+ (before_delete, child_pre_updates),
+ (child_pre_updates, delete_parent),
+ ]
+ )
elif not isdelete:
- uow.dependencies.update([
- (save_parent, after_save),
- (after_save, child_action),
- (save_parent, child_action)
- ])
+ uow.dependencies.update(
+ [
+ (save_parent, after_save),
+ (after_save, child_action),
+ (save_parent, child_action),
+ ]
+ )
else:
- uow.dependencies.update([
- (before_delete, child_action),
- (child_action, delete_parent)
- ])
+ uow.dependencies.update(
+ [(before_delete, child_action), (child_action, delete_parent)]
+ )
def presort_deletes(self, uowcommit, states):
# head object is being deleted, and we manage its list of
# child objects the child objects have to have their
# foreign key to the parent set to NULL
- should_null_fks = not self.cascade.delete and \
- not self.passive_deletes == 'all'
+ should_null_fks = (
+ not self.cascade.delete and not self.passive_deletes == "all"
+ )
for state in states:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- self._passive_delete_flag)
+ state, self.key, self._passive_delete_flag
+ )
if history:
for child in history.deleted:
if child is not None and self.hasparent(child) is False:
@@ -429,13 +439,16 @@ class OneToManyDP(DependencyProcessor):
for child in history.unchanged:
if child is not None:
uowcommit.register_object(
- child, operation="delete", prop=self.prop)
+ child, operation="delete", prop=self.prop
+ )
def presort_saves(self, uowcommit, states):
- children_added = uowcommit.memo(('children_added', self), set)
+ children_added = uowcommit.memo(("children_added", self), set)
- should_null_fks = not self.cascade.delete_orphan and \
- not self.passive_deletes == 'all'
+ should_null_fks = (
+ not self.cascade.delete_orphan
+ and not self.passive_deletes == "all"
+ )
for state in states:
pks_changed = self._pks_changed(uowcommit, state)
@@ -445,34 +458,39 @@ class OneToManyDP(DependencyProcessor):
else:
passive = attributes.PASSIVE_OFF
- history = uowcommit.get_attribute_history(
- state,
- self.key,
- passive)
+ history = uowcommit.get_attribute_history(state, self.key, passive)
if history:
for child in history.added:
if child is not None:
- uowcommit.register_object(child, cancel_delete=True,
- operation="add",
- prop=self.prop)
+ uowcommit.register_object(
+ child,
+ cancel_delete=True,
+ operation="add",
+ prop=self.prop,
+ )
children_added.update(history.added)
for child in history.deleted:
if not self.cascade.delete_orphan:
if should_null_fks:
- uowcommit.register_object(child, isdelete=False,
- operation='delete',
- prop=self.prop)
+ uowcommit.register_object(
+ child,
+ isdelete=False,
+ operation="delete",
+ prop=self.prop,
+ )
elif self.hasparent(child) is False:
uowcommit.register_object(
- child, isdelete=True,
- operation="delete", prop=self.prop)
+ child,
+ isdelete=True,
+ operation="delete",
+ prop=self.prop,
+ )
for c, m, st_, dct_ in self.mapper.cascade_iterator(
- 'delete', child):
- uowcommit.register_object(
- st_,
- isdelete=True)
+ "delete", child
+ ):
+ uowcommit.register_object(st_, isdelete=True)
if pks_changed:
if history:
@@ -483,7 +501,8 @@ class OneToManyDP(DependencyProcessor):
False,
self.passive_updates,
operation="pk change",
- prop=self.prop)
+ prop=self.prop,
+ )
def process_deletes(self, uowcommit, states):
# head object is being deleted, and we manage its list of
@@ -492,39 +511,37 @@ class OneToManyDP(DependencyProcessor):
# safely for any cascade but is unnecessary if delete cascade
# is on.
- if self.post_update or not self.passive_deletes == 'all':
- children_added = uowcommit.memo(('children_added', self), set)
+ if self.post_update or not self.passive_deletes == "all":
+ children_added = uowcommit.memo(("children_added", self), set)
for state in states:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- self._passive_delete_flag)
+ state, self.key, self._passive_delete_flag
+ )
if history:
for child in history.deleted:
- if child is not None and \
- self.hasparent(child) is False:
+ if (
+ child is not None
+ and self.hasparent(child) is False
+ ):
self._synchronize(
- state,
- child,
- None, True,
- uowcommit, False)
+ state, child, None, True, uowcommit, False
+ )
if self.post_update and child:
self._post_update(child, uowcommit, [state])
if self.post_update or not self.cascade.delete:
- for child in set(history.unchanged).\
- difference(children_added):
+ for child in set(history.unchanged).difference(
+ children_added
+ ):
if child is not None:
self._synchronize(
- state,
- child,
- None, True,
- uowcommit, False)
+ state, child, None, True, uowcommit, False
+ )
if self.post_update and child:
- self._post_update(child,
- uowcommit,
- [state])
+ self._post_update(
+ child, uowcommit, [state]
+ )
# technically, we can even remove each child from the
# collection here too. but this would be a somewhat
@@ -532,54 +549,66 @@ class OneToManyDP(DependencyProcessor):
# if the old parent wasn't deleted but child was moved.
def process_saves(self, uowcommit, states):
- should_null_fks = not self.cascade.delete_orphan and \
- not self.passive_deletes == 'all'
+ should_null_fks = (
+ not self.cascade.delete_orphan
+ and not self.passive_deletes == "all"
+ )
for state in states:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- attributes.PASSIVE_NO_INITIALIZE)
+ state, self.key, attributes.PASSIVE_NO_INITIALIZE
+ )
if history:
for child in history.added:
- self._synchronize(state, child, None,
- False, uowcommit, False)
+ self._synchronize(
+ state, child, None, False, uowcommit, False
+ )
if child is not None and self.post_update:
self._post_update(child, uowcommit, [state])
for child in history.deleted:
- if should_null_fks and not self.cascade.delete_orphan and \
- not self.hasparent(child):
- self._synchronize(state, child, None, True,
- uowcommit, False)
+ if (
+ should_null_fks
+ and not self.cascade.delete_orphan
+ and not self.hasparent(child)
+ ):
+ self._synchronize(
+ state, child, None, True, uowcommit, False
+ )
if self._pks_changed(uowcommit, state):
for child in history.unchanged:
- self._synchronize(state, child, None,
- False, uowcommit, True)
+ self._synchronize(
+ state, child, None, False, uowcommit, True
+ )
- def _synchronize(self, state, child,
- associationrow, clearkeys, uowcommit,
- pks_changed):
+ def _synchronize(
+ self, state, child, associationrow, clearkeys, uowcommit, pks_changed
+ ):
source = state
dest = child
self._verify_canload(child)
- if dest is None or \
- (not self.post_update and uowcommit.is_deleted(dest)):
+ if dest is None or (
+ not self.post_update and uowcommit.is_deleted(dest)
+ ):
return
if clearkeys:
sync.clear(dest, self.mapper, self.prop.synchronize_pairs)
else:
- sync.populate(source, self.parent, dest, self.mapper,
- self.prop.synchronize_pairs, uowcommit,
- self.passive_updates and pks_changed)
+ sync.populate(
+ source,
+ self.parent,
+ dest,
+ self.mapper,
+ self.prop.synchronize_pairs,
+ uowcommit,
+ self.passive_updates and pks_changed,
+ )
def _pks_changed(self, uowcommit, state):
return sync.source_modified(
- uowcommit,
- state,
- self.parent,
- self.prop.synchronize_pairs)
+ uowcommit, state, self.parent, self.prop.synchronize_pairs
+ )
class ManyToOneDP(DependencyProcessor):
@@ -587,105 +616,110 @@ class ManyToOneDP(DependencyProcessor):
DependencyProcessor.__init__(self, prop)
self.mapper._dependency_processors.append(DetectKeySwitch(prop))
- def per_property_dependencies(self, uow,
- parent_saves,
- child_saves,
- parent_deletes,
- child_deletes,
- after_save,
- before_delete):
+ def per_property_dependencies(
+ self,
+ uow,
+ parent_saves,
+ child_saves,
+ parent_deletes,
+ child_deletes,
+ after_save,
+ before_delete,
+ ):
if self.post_update:
parent_post_updates = unitofwork.PostUpdateAll(
- uow,
- self.parent.primary_base_mapper,
- False)
+ uow, self.parent.primary_base_mapper, False
+ )
parent_pre_updates = unitofwork.PostUpdateAll(
- uow,
- self.parent.primary_base_mapper,
- True)
-
- uow.dependencies.update([
- (child_saves, after_save),
- (parent_saves, after_save),
- (after_save, parent_post_updates),
-
- (after_save, parent_pre_updates),
- (before_delete, parent_pre_updates),
-
- (parent_pre_updates, child_deletes),
- (parent_pre_updates, parent_deletes),
- ])
+ uow, self.parent.primary_base_mapper, True
+ )
+
+ uow.dependencies.update(
+ [
+ (child_saves, after_save),
+ (parent_saves, after_save),
+ (after_save, parent_post_updates),
+ (after_save, parent_pre_updates),
+ (before_delete, parent_pre_updates),
+ (parent_pre_updates, child_deletes),
+ (parent_pre_updates, parent_deletes),
+ ]
+ )
else:
- uow.dependencies.update([
- (child_saves, after_save),
- (after_save, parent_saves),
- (parent_saves, child_deletes),
- (parent_deletes, child_deletes)
- ])
-
- def per_state_dependencies(self, uow,
- save_parent,
- delete_parent,
- child_action,
- after_save, before_delete,
- isdelete, childisdelete):
+ uow.dependencies.update(
+ [
+ (child_saves, after_save),
+ (after_save, parent_saves),
+ (parent_saves, child_deletes),
+ (parent_deletes, child_deletes),
+ ]
+ )
+
+ def per_state_dependencies(
+ self,
+ uow,
+ save_parent,
+ delete_parent,
+ child_action,
+ after_save,
+ before_delete,
+ isdelete,
+ childisdelete,
+ ):
if self.post_update:
if not isdelete:
parent_post_updates = unitofwork.PostUpdateAll(
- uow,
- self.parent.primary_base_mapper,
- False)
+ uow, self.parent.primary_base_mapper, False
+ )
if childisdelete:
- uow.dependencies.update([
- (after_save, parent_post_updates),
- (parent_post_updates, child_action)
- ])
+ uow.dependencies.update(
+ [
+ (after_save, parent_post_updates),
+ (parent_post_updates, child_action),
+ ]
+ )
else:
- uow.dependencies.update([
- (save_parent, after_save),
- (child_action, after_save),
-
- (after_save, parent_post_updates)
- ])
+ uow.dependencies.update(
+ [
+ (save_parent, after_save),
+ (child_action, after_save),
+ (after_save, parent_post_updates),
+ ]
+ )
else:
parent_pre_updates = unitofwork.PostUpdateAll(
- uow,
- self.parent.primary_base_mapper,
- True)
+ uow, self.parent.primary_base_mapper, True
+ )
- uow.dependencies.update([
- (before_delete, parent_pre_updates),
- (parent_pre_updates, delete_parent),
- (parent_pre_updates, child_action)
- ])
+ uow.dependencies.update(
+ [
+ (before_delete, parent_pre_updates),
+ (parent_pre_updates, delete_parent),
+ (parent_pre_updates, child_action),
+ ]
+ )
elif not isdelete:
if not childisdelete:
- uow.dependencies.update([
- (child_action, after_save),
- (after_save, save_parent),
- ])
+ uow.dependencies.update(
+ [(child_action, after_save), (after_save, save_parent)]
+ )
else:
- uow.dependencies.update([
- (after_save, save_parent),
- ])
+ uow.dependencies.update([(after_save, save_parent)])
else:
if childisdelete:
- uow.dependencies.update([
- (delete_parent, child_action)
- ])
+ uow.dependencies.update([(delete_parent, child_action)])
def presort_deletes(self, uowcommit, states):
if self.cascade.delete or self.cascade.delete_orphan:
for state in states:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- self._passive_delete_flag)
+ state, self.key, self._passive_delete_flag
+ )
if history:
if self.cascade.delete_orphan:
todelete = history.sum()
@@ -695,36 +729,42 @@ class ManyToOneDP(DependencyProcessor):
if child is None:
continue
uowcommit.register_object(
- child, isdelete=True,
- operation="delete", prop=self.prop)
- t = self.mapper.cascade_iterator('delete', child)
+ child,
+ isdelete=True,
+ operation="delete",
+ prop=self.prop,
+ )
+ t = self.mapper.cascade_iterator("delete", child)
for c, m, st_, dct_ in t:
- uowcommit.register_object(
- st_, isdelete=True)
+ uowcommit.register_object(st_, isdelete=True)
def presort_saves(self, uowcommit, states):
for state in states:
uowcommit.register_object(state, operation="add", prop=self.prop)
if self.cascade.delete_orphan:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- self._passive_delete_flag)
+ state, self.key, self._passive_delete_flag
+ )
if history:
for child in history.deleted:
if self.hasparent(child) is False:
uowcommit.register_object(
- child, isdelete=True,
- operation="delete", prop=self.prop)
+ child,
+ isdelete=True,
+ operation="delete",
+ prop=self.prop,
+ )
- t = self.mapper.cascade_iterator('delete', child)
+ t = self.mapper.cascade_iterator("delete", child)
for c, m, st_, dct_ in t:
uowcommit.register_object(st_, isdelete=True)
def process_deletes(self, uowcommit, states):
- if self.post_update and \
- not self.cascade.delete_orphan and \
- not self.passive_deletes == 'all':
+ if (
+ self.post_update
+ and not self.cascade.delete_orphan
+ and not self.passive_deletes == "all"
+ ):
# post_update means we have to update our
# row to not reference the child object
@@ -733,55 +773,70 @@ class ManyToOneDP(DependencyProcessor):
self._synchronize(state, None, None, True, uowcommit)
if state and self.post_update:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- self._passive_delete_flag)
+ state, self.key, self._passive_delete_flag
+ )
if history:
self._post_update(
- state, uowcommit, history.sum(),
- is_m2o_delete=True)
+ state, uowcommit, history.sum(), is_m2o_delete=True
+ )
def process_saves(self, uowcommit, states):
for state in states:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- attributes.PASSIVE_NO_INITIALIZE)
+ state, self.key, attributes.PASSIVE_NO_INITIALIZE
+ )
if history:
if history.added:
for child in history.added:
- self._synchronize(state, child, None, False,
- uowcommit, "add")
+ self._synchronize(
+ state, child, None, False, uowcommit, "add"
+ )
elif history.deleted:
self._synchronize(
- state, None, None, True, uowcommit, "delete")
+ state, None, None, True, uowcommit, "delete"
+ )
if self.post_update:
self._post_update(state, uowcommit, history.sum())
- def _synchronize(self, state, child, associationrow,
- clearkeys, uowcommit, operation=None):
- if state is None or \
- (not self.post_update and uowcommit.is_deleted(state)):
+ def _synchronize(
+ self,
+ state,
+ child,
+ associationrow,
+ clearkeys,
+ uowcommit,
+ operation=None,
+ ):
+ if state is None or (
+ not self.post_update and uowcommit.is_deleted(state)
+ ):
return
- if operation is not None and \
- child is not None and \
- not uowcommit.session._contains_state(child):
+ if (
+ operation is not None
+ and child is not None
+ and not uowcommit.session._contains_state(child)
+ ):
util.warn(
"Object of type %s not in session, %s "
- "operation along '%s' won't proceed" %
- (mapperutil.state_class_str(child), operation, self.prop))
+ "operation along '%s' won't proceed"
+ % (mapperutil.state_class_str(child), operation, self.prop)
+ )
return
if clearkeys or child is None:
sync.clear(state, self.parent, self.prop.synchronize_pairs)
else:
self._verify_canload(child)
- sync.populate(child, self.mapper, state,
- self.parent,
- self.prop.synchronize_pairs,
- uowcommit,
- False)
+ sync.populate(
+ child,
+ self.mapper,
+ state,
+ self.parent,
+ self.prop.synchronize_pairs,
+ uowcommit,
+ False,
+ )
class DetectKeySwitch(DependencyProcessor):
@@ -801,20 +856,18 @@ class DetectKeySwitch(DependencyProcessor):
if self.passive_updates:
return
else:
- if False in (prop.passive_updates for
- prop in self.prop._reverse_property):
+ if False in (
+ prop.passive_updates
+ for prop in self.prop._reverse_property
+ ):
return
uow.register_preprocessor(self, False)
def per_property_flush_actions(self, uow):
- parent_saves = unitofwork.SaveUpdateAll(
- uow,
- self.parent.base_mapper)
+ parent_saves = unitofwork.SaveUpdateAll(uow, self.parent.base_mapper)
after_save = unitofwork.ProcessAll(uow, self, False, False)
- uow.dependencies.update([
- (parent_saves, after_save)
- ])
+ uow.dependencies.update([(parent_saves, after_save)])
def per_state_flush_actions(self, uow, states, isdelete):
pass
@@ -848,8 +901,7 @@ class DetectKeySwitch(DependencyProcessor):
def _key_switchers(self, uow, states):
switched, notswitched = uow.memo(
- ('pk_switchers', self),
- lambda: (set(), set())
+ ("pk_switchers", self), lambda: (set(), set())
)
allstates = switched.union(notswitched)
@@ -871,74 +923,86 @@ class DetectKeySwitch(DependencyProcessor):
continue
dict_ = state.dict
related = state.get_impl(self.key).get(
- state, dict_, passive=self._passive_update_flag)
- if related is not attributes.PASSIVE_NO_RESULT and \
- related is not None:
+ state, dict_, passive=self._passive_update_flag
+ )
+ if (
+ related is not attributes.PASSIVE_NO_RESULT
+ and related is not None
+ ):
related_state = attributes.instance_state(dict_[self.key])
if related_state in switchers:
- uowcommit.register_object(state,
- False,
- self.passive_updates)
+ uowcommit.register_object(
+ state, False, self.passive_updates
+ )
sync.populate(
related_state,
- self.mapper, state,
- self.parent, self.prop.synchronize_pairs,
- uowcommit, self.passive_updates)
+ self.mapper,
+ state,
+ self.parent,
+ self.prop.synchronize_pairs,
+ uowcommit,
+ self.passive_updates,
+ )
def _pks_changed(self, uowcommit, state):
return bool(state.key) and sync.source_modified(
- uowcommit, state, self.mapper, self.prop.synchronize_pairs)
+ uowcommit, state, self.mapper, self.prop.synchronize_pairs
+ )
class ManyToManyDP(DependencyProcessor):
+ def per_property_dependencies(
+ self,
+ uow,
+ parent_saves,
+ child_saves,
+ parent_deletes,
+ child_deletes,
+ after_save,
+ before_delete,
+ ):
+
+ uow.dependencies.update(
+ [
+ (parent_saves, after_save),
+ (child_saves, after_save),
+ (after_save, child_deletes),
+ # a rowswitch on the parent from deleted to saved
+ # can make this one occur, as the "save" may remove
+ # an element from the
+ # "deleted" list before we have a chance to
+ # process its child rows
+ (before_delete, parent_saves),
+ (before_delete, parent_deletes),
+ (before_delete, child_deletes),
+ (before_delete, child_saves),
+ ]
+ )
- def per_property_dependencies(self, uow, parent_saves,
- child_saves,
- parent_deletes,
- child_deletes,
- after_save,
- before_delete
- ):
-
- uow.dependencies.update([
- (parent_saves, after_save),
- (child_saves, after_save),
- (after_save, child_deletes),
-
- # a rowswitch on the parent from deleted to saved
- # can make this one occur, as the "save" may remove
- # an element from the
- # "deleted" list before we have a chance to
- # process its child rows
- (before_delete, parent_saves),
-
- (before_delete, parent_deletes),
- (before_delete, child_deletes),
- (before_delete, child_saves),
- ])
-
- def per_state_dependencies(self, uow,
- save_parent,
- delete_parent,
- child_action,
- after_save, before_delete,
- isdelete, childisdelete):
+ def per_state_dependencies(
+ self,
+ uow,
+ save_parent,
+ delete_parent,
+ child_action,
+ after_save,
+ before_delete,
+ isdelete,
+ childisdelete,
+ ):
if not isdelete:
if childisdelete:
- uow.dependencies.update([
- (save_parent, after_save),
- (after_save, child_action),
- ])
+ uow.dependencies.update(
+ [(save_parent, after_save), (after_save, child_action)]
+ )
else:
- uow.dependencies.update([
- (save_parent, after_save),
- (child_action, after_save),
- ])
+ uow.dependencies.update(
+ [(save_parent, after_save), (child_action, after_save)]
+ )
else:
- uow.dependencies.update([
- (before_delete, child_action),
- (before_delete, delete_parent)
- ])
+ uow.dependencies.update(
+ [(before_delete, child_action), (before_delete, delete_parent)]
+ )
def presort_deletes(self, uowcommit, states):
# TODO: no tests fail if this whole
@@ -949,9 +1013,8 @@ class ManyToManyDP(DependencyProcessor):
# returns True
for state in states:
uowcommit.get_attribute_history(
- state,
- self.key,
- self._passive_delete_flag)
+ state, self.key, self._passive_delete_flag
+ )
def presort_saves(self, uowcommit, states):
if not self.passive_updates:
@@ -961,9 +1024,8 @@ class ManyToManyDP(DependencyProcessor):
for state in states:
if self._pks_changed(uowcommit, state):
history = uowcommit.get_attribute_history(
- state,
- self.key,
- attributes.PASSIVE_OFF)
+ state, self.key, attributes.PASSIVE_OFF
+ )
if not self.cascade.delete_orphan:
return
@@ -972,20 +1034,21 @@ class ManyToManyDP(DependencyProcessor):
# if delete_orphan check is turned on.
for state in states:
history = uowcommit.get_attribute_history(
- state,
- self.key,
- attributes.PASSIVE_NO_INITIALIZE)
+ state, self.key, attributes.PASSIVE_NO_INITIALIZE
+ )
if history:
for child in history.deleted:
if self.hasparent(child) is False:
uowcommit.register_object(
- child, isdelete=True,
- operation="delete", prop=self.prop)
+ child,
+ isdelete=True,
+ operation="delete",
+ prop=self.prop,
+ )
for c, m, st_, dct_ in self.mapper.cascade_iterator(
- 'delete',
- child):
- uowcommit.register_object(
- st_, isdelete=True)
+ "delete", child
+ ):
+ uowcommit.register_object(st_, isdelete=True)
def process_deletes(self, uowcommit, states):
secondary_delete = []
@@ -998,21 +1061,23 @@ class ManyToManyDP(DependencyProcessor):
# this history should be cached already, as
# we loaded it in preprocess_deletes
history = uowcommit.get_attribute_history(
- state,
- self.key,
- self._passive_delete_flag)
+ state, self.key, self._passive_delete_flag
+ )
if history:
for child in history.non_added():
- if child is None or \
- (processed is not None and
- (state, child) in processed):
+ if child is None or (
+ processed is not None and (state, child) in processed
+ ):
continue
associationrow = {}
if not self._synchronize(
- state,
- child,
- associationrow,
- False, uowcommit, "delete"):
+ state,
+ child,
+ associationrow,
+ False,
+ uowcommit,
+ "delete",
+ ):
continue
secondary_delete.append(associationrow)
@@ -1021,8 +1086,9 @@ class ManyToManyDP(DependencyProcessor):
if processed is not None:
processed.update(tmp)
- self._run_crud(uowcommit, secondary_insert,
- secondary_update, secondary_delete)
+ self._run_crud(
+ uowcommit, secondary_insert, secondary_update, secondary_delete
+ )
def process_saves(self, uowcommit, states):
secondary_delete = []
@@ -1033,110 +1099,133 @@ class ManyToManyDP(DependencyProcessor):
tmp = set()
for state in states:
- need_cascade_pks = not self.passive_updates and \
- self._pks_changed(uowcommit, state)
+ need_cascade_pks = not self.passive_updates and self._pks_changed(
+ uowcommit, state
+ )
if need_cascade_pks:
passive = attributes.PASSIVE_OFF
else:
passive = attributes.PASSIVE_NO_INITIALIZE
- history = uowcommit.get_attribute_history(state, self.key,
- passive)
+ history = uowcommit.get_attribute_history(state, self.key, passive)
if history:
for child in history.added:
- if (processed is not None and
- (state, child) in processed):
+ if processed is not None and (state, child) in processed:
continue
associationrow = {}
- if not self._synchronize(state,
- child,
- associationrow,
- False, uowcommit, "add"):
+ if not self._synchronize(
+ state, child, associationrow, False, uowcommit, "add"
+ ):
continue
secondary_insert.append(associationrow)
for child in history.deleted:
- if (processed is not None and
- (state, child) in processed):
+ if processed is not None and (state, child) in processed:
continue
associationrow = {}
- if not self._synchronize(state,
- child,
- associationrow,
- False, uowcommit, "delete"):
+ if not self._synchronize(
+ state,
+ child,
+ associationrow,
+ False,
+ uowcommit,
+ "delete",
+ ):
continue
secondary_delete.append(associationrow)
- tmp.update((c, state)
- for c in history.added + history.deleted)
+ tmp.update((c, state) for c in history.added + history.deleted)
if need_cascade_pks:
for child in history.unchanged:
associationrow = {}
- sync.update(state,
- self.parent,
- associationrow,
- "old_",
- self.prop.synchronize_pairs)
- sync.update(child,
- self.mapper,
- associationrow,
- "old_",
- self.prop.secondary_synchronize_pairs)
+ sync.update(
+ state,
+ self.parent,
+ associationrow,
+ "old_",
+ self.prop.synchronize_pairs,
+ )
+ sync.update(
+ child,
+ self.mapper,
+ associationrow,
+ "old_",
+ self.prop.secondary_synchronize_pairs,
+ )
secondary_update.append(associationrow)
if processed is not None:
processed.update(tmp)
- self._run_crud(uowcommit, secondary_insert,
- secondary_update, secondary_delete)
+ self._run_crud(
+ uowcommit, secondary_insert, secondary_update, secondary_delete
+ )
- def _run_crud(self, uowcommit, secondary_insert,
- secondary_update, secondary_delete):
+ def _run_crud(
+ self, uowcommit, secondary_insert, secondary_update, secondary_delete
+ ):
connection = uowcommit.transaction.connection(self.mapper)
if secondary_delete:
associationrow = secondary_delete[0]
- statement = self.secondary.delete(sql.and_(*[
- c == sql.bindparam(c.key, type_=c.type)
- for c in self.secondary.c
- if c.key in associationrow
- ]))
+ statement = self.secondary.delete(
+ sql.and_(
+ *[
+ c == sql.bindparam(c.key, type_=c.type)
+ for c in self.secondary.c
+ if c.key in associationrow
+ ]
+ )
+ )
result = connection.execute(statement, secondary_delete)
- if result.supports_sane_multi_rowcount() and \
- result.rowcount != len(secondary_delete):
+ if result.supports_sane_multi_rowcount() and result.rowcount != len(
+ secondary_delete
+ ):
raise exc.StaleDataError(
"DELETE statement on table '%s' expected to delete "
- "%d row(s); Only %d were matched." %
- (self.secondary.description, len(secondary_delete),
- result.rowcount)
+ "%d row(s); Only %d were matched."
+ % (
+ self.secondary.description,
+ len(secondary_delete),
+ result.rowcount,
+ )
)
if secondary_update:
associationrow = secondary_update[0]
- statement = self.secondary.update(sql.and_(*[
- c == sql.bindparam("old_" + c.key, type_=c.type)
- for c in self.secondary.c
- if c.key in associationrow
- ]))
+ statement = self.secondary.update(
+ sql.and_(
+ *[
+ c == sql.bindparam("old_" + c.key, type_=c.type)
+ for c in self.secondary.c
+ if c.key in associationrow
+ ]
+ )
+ )
result = connection.execute(statement, secondary_update)
- if result.supports_sane_multi_rowcount() and \
- result.rowcount != len(secondary_update):
+ if result.supports_sane_multi_rowcount() and result.rowcount != len(
+ secondary_update
+ ):
raise exc.StaleDataError(
"UPDATE statement on table '%s' expected to update "
- "%d row(s); Only %d were matched." %
- (self.secondary.description, len(secondary_update),
- result.rowcount)
+ "%d row(s); Only %d were matched."
+ % (
+ self.secondary.description,
+ len(secondary_update),
+ result.rowcount,
+ )
)
if secondary_insert:
statement = self.secondary.insert()
connection.execute(statement, secondary_insert)
- def _synchronize(self, state, child, associationrow,
- clearkeys, uowcommit, operation):
+ def _synchronize(
+ self, state, child, associationrow, clearkeys, uowcommit, operation
+ ):
# this checks for None if uselist=True
self._verify_canload(child)
@@ -1150,23 +1239,28 @@ class ManyToManyDP(DependencyProcessor):
if not child.deleted:
util.warn(
"Object of type %s not in session, %s "
- "operation along '%s' won't proceed" %
- (mapperutil.state_class_str(child), operation, self.prop))
+ "operation along '%s' won't proceed"
+ % (mapperutil.state_class_str(child), operation, self.prop)
+ )
return False
- sync.populate_dict(state, self.parent, associationrow,
- self.prop.synchronize_pairs)
- sync.populate_dict(child, self.mapper, associationrow,
- self.prop.secondary_synchronize_pairs)
+ sync.populate_dict(
+ state, self.parent, associationrow, self.prop.synchronize_pairs
+ )
+ sync.populate_dict(
+ child,
+ self.mapper,
+ associationrow,
+ self.prop.secondary_synchronize_pairs,
+ )
return True
def _pks_changed(self, uowcommit, state):
return sync.source_modified(
- uowcommit,
- state,
- self.parent,
- self.prop.synchronize_pairs)
+ uowcommit, state, self.parent, self.prop.synchronize_pairs
+ )
+
_direction_to_processor = {
ONETOMANY: OneToManyDP,
diff --git a/lib/sqlalchemy/orm/deprecated_interfaces.py b/lib/sqlalchemy/orm/deprecated_interfaces.py
index 426288e03..6b51404d0 100644
--- a/lib/sqlalchemy/orm/deprecated_interfaces.py
+++ b/lib/sqlalchemy/orm/deprecated_interfaces.py
@@ -58,23 +58,25 @@ class MapperExtension(object):
@classmethod
def _adapt_instrument_class(cls, self, listener):
- cls._adapt_listener_methods(self, listener, ('instrument_class',))
+ cls._adapt_listener_methods(self, listener, ("instrument_class",))
@classmethod
def _adapt_listener(cls, self, listener):
cls._adapt_listener_methods(
- self, listener,
+ self,
+ listener,
(
- 'init_instance',
- 'init_failed',
- 'reconstruct_instance',
- 'before_insert',
- 'after_insert',
- 'before_update',
- 'after_update',
- 'before_delete',
- 'after_delete'
- ))
+ "init_instance",
+ "init_failed",
+ "reconstruct_instance",
+ "before_insert",
+ "after_insert",
+ "before_update",
+ "after_update",
+ "before_delete",
+ "after_delete",
+ ),
+ )
@classmethod
def _adapt_listener_methods(cls, self, listener, methods):
@@ -84,36 +86,75 @@ class MapperExtension(object):
ls_meth = getattr(listener, meth)
if not util.methods_equivalent(me_meth, ls_meth):
- if meth == 'reconstruct_instance':
+ if meth == "reconstruct_instance":
+
def go(ls_meth):
def reconstruct(instance, ctx):
ls_meth(self, instance)
+
return reconstruct
- event.listen(self.class_manager, 'load',
- go(ls_meth), raw=False, propagate=True)
- elif meth == 'init_instance':
+
+ event.listen(
+ self.class_manager,
+ "load",
+ go(ls_meth),
+ raw=False,
+ propagate=True,
+ )
+ elif meth == "init_instance":
+
def go(ls_meth):
def init_instance(instance, args, kwargs):
- ls_meth(self, self.class_,
- self.class_manager.original_init,
- instance, args, kwargs)
+ ls_meth(
+ self,
+ self.class_,
+ self.class_manager.original_init,
+ instance,
+ args,
+ kwargs,
+ )
+
return init_instance
- event.listen(self.class_manager, 'init',
- go(ls_meth), raw=False, propagate=True)
- elif meth == 'init_failed':
+
+ event.listen(
+ self.class_manager,
+ "init",
+ go(ls_meth),
+ raw=False,
+ propagate=True,
+ )
+ elif meth == "init_failed":
+
def go(ls_meth):
def init_failed(instance, args, kwargs):
util.warn_exception(
- ls_meth, self, self.class_,
+ ls_meth,
+ self,
+ self.class_,
self.class_manager.original_init,
- instance, args, kwargs)
+ instance,
+ args,
+ kwargs,
+ )
return init_failed
- event.listen(self.class_manager, 'init_failure',
- go(ls_meth), raw=False, propagate=True)
+
+ event.listen(
+ self.class_manager,
+ "init_failure",
+ go(ls_meth),
+ raw=False,
+ propagate=True,
+ )
else:
- event.listen(self, "%s" % meth, ls_meth,
- raw=False, retval=True, propagate=True)
+ event.listen(
+ self,
+ "%s" % meth,
+ ls_meth,
+ raw=False,
+ retval=True,
+ propagate=True,
+ )
def instrument_class(self, mapper, class_):
"""Receive a class when the mapper is first constructed, and has
@@ -302,16 +343,16 @@ class SessionExtension(object):
@classmethod
def _adapt_listener(cls, self, listener):
for meth in [
- 'before_commit',
- 'after_commit',
- 'after_rollback',
- 'before_flush',
- 'after_flush',
- 'after_flush_postexec',
- 'after_begin',
- 'after_attach',
- 'after_bulk_update',
- 'after_bulk_delete',
+ "before_commit",
+ "after_commit",
+ "after_rollback",
+ "before_flush",
+ "after_flush",
+ "after_flush_postexec",
+ "after_begin",
+ "after_attach",
+ "after_bulk_update",
+ "after_bulk_delete",
]:
me_meth = getattr(SessionExtension, meth)
ls_meth = getattr(listener, meth)
@@ -450,15 +491,30 @@ class AttributeExtension(object):
@classmethod
def _adapt_listener(cls, self, listener):
- event.listen(self, 'append', listener.append,
- active_history=listener.active_history,
- raw=True, retval=True)
- event.listen(self, 'remove', listener.remove,
- active_history=listener.active_history,
- raw=True, retval=True)
- event.listen(self, 'set', listener.set,
- active_history=listener.active_history,
- raw=True, retval=True)
+ event.listen(
+ self,
+ "append",
+ listener.append,
+ active_history=listener.active_history,
+ raw=True,
+ retval=True,
+ )
+ event.listen(
+ self,
+ "remove",
+ listener.remove,
+ active_history=listener.active_history,
+ raw=True,
+ retval=True,
+ )
+ event.listen(
+ self,
+ "set",
+ listener.set,
+ active_history=listener.active_history,
+ raw=True,
+ retval=True,
+ )
def append(self, state, value, initiator):
"""Receive a collection append event.
diff --git a/lib/sqlalchemy/orm/descriptor_props.py b/lib/sqlalchemy/orm/descriptor_props.py
index fefd2d2a1..37517e84c 100644
--- a/lib/sqlalchemy/orm/descriptor_props.py
+++ b/lib/sqlalchemy/orm/descriptor_props.py
@@ -37,9 +37,11 @@ class DescriptorProperty(MapperProperty):
def __init__(self, key):
self.key = key
- if hasattr(prop, 'get_history'):
- def get_history(self, state, dict_,
- passive=attributes.PASSIVE_OFF):
+ if hasattr(prop, "get_history"):
+
+ def get_history(
+ self, state, dict_, passive=attributes.PASSIVE_OFF
+ ):
return prop.get_history(state, dict_, passive)
if self.descriptor is None:
@@ -48,6 +50,7 @@ class DescriptorProperty(MapperProperty):
self.descriptor = desc
if self.descriptor is None:
+
def fset(obj, value):
setattr(obj, self.name, value)
@@ -57,21 +60,16 @@ class DescriptorProperty(MapperProperty):
def fget(obj):
return getattr(obj, self.name)
- self.descriptor = property(
- fget=fget,
- fset=fset,
- fdel=fdel,
- )
+ self.descriptor = property(fget=fget, fset=fset, fdel=fdel)
- proxy_attr = attributes.create_proxied_attribute(
- self.descriptor)(
- self.parent.class_,
- self.key,
- self.descriptor,
- lambda: self._comparator_factory(mapper),
- doc=self.doc,
- original_property=self
- )
+ proxy_attr = attributes.create_proxied_attribute(self.descriptor)(
+ self.parent.class_,
+ self.key,
+ self.descriptor,
+ lambda: self._comparator_factory(mapper),
+ doc=self.doc,
+ original_property=self,
+ )
proxy_attr.impl = _ProxyImpl(self.key)
mapper.class_manager.instrument_attribute(self.key, proxy_attr)
@@ -149,13 +147,14 @@ class CompositeProperty(DescriptorProperty):
self.attrs = attrs
self.composite_class = class_
- self.active_history = kwargs.get('active_history', False)
- self.deferred = kwargs.get('deferred', False)
- self.group = kwargs.get('group', None)
- self.comparator_factory = kwargs.pop('comparator_factory',
- self.__class__.Comparator)
- if 'info' in kwargs:
- self.info = kwargs.pop('info')
+ self.active_history = kwargs.get("active_history", False)
+ self.deferred = kwargs.get("deferred", False)
+ self.group = kwargs.get("group", None)
+ self.comparator_factory = kwargs.pop(
+ "comparator_factory", self.__class__.Comparator
+ )
+ if "info" in kwargs:
+ self.info = kwargs.pop("info")
util.set_creation_order(self)
self._create_descriptor()
@@ -186,8 +185,7 @@ class CompositeProperty(DescriptorProperty):
# attributes, retrieve their values. This
# ensures they all load.
values = [
- getattr(instance, key)
- for key in self._attribute_keys
+ getattr(instance, key) for key in self._attribute_keys
]
# current expected behavior here is that the composite is
@@ -196,8 +194,7 @@ class CompositeProperty(DescriptorProperty):
# if the composite were created unconditionally,
# but that would be a behavioral change.
if self.key not in dict_ and (
- state.key is not None or
- not _none_set.issuperset(values)
+ state.key is not None or not _none_set.issuperset(values)
):
dict_[self.key] = self.composite_class(*values)
state.manager.dispatch.refresh(state, None, [self.key])
@@ -217,8 +214,8 @@ class CompositeProperty(DescriptorProperty):
setattr(instance, key, None)
else:
for key, value in zip(
- self._attribute_keys,
- value.__composite_values__()):
+ self._attribute_keys, value.__composite_values__()
+ ):
setattr(instance, key, value)
def fdel(instance):
@@ -234,18 +231,14 @@ class CompositeProperty(DescriptorProperty):
@util.memoized_property
def _comparable_elements(self):
- return [
- getattr(self.parent.class_, prop.key)
- for prop in self.props
- ]
+ return [getattr(self.parent.class_, prop.key) for prop in self.props]
@util.memoized_property
def props(self):
props = []
for attr in self.attrs:
if isinstance(attr, str):
- prop = self.parent.get_property(
- attr, _configure_mappers=False)
+ prop = self.parent.get_property(attr, _configure_mappers=False)
elif isinstance(attr, schema.Column):
prop = self.parent._columntoproperty[attr]
elif isinstance(attr, attributes.InstrumentedAttribute):
@@ -254,7 +247,8 @@ class CompositeProperty(DescriptorProperty):
raise sa_exc.ArgumentError(
"Composite expects Column objects or mapped "
"attributes/attribute names as arguments, got: %r"
- % (attr,))
+ % (attr,)
+ )
props.append(prop)
return props
@@ -271,9 +265,7 @@ class CompositeProperty(DescriptorProperty):
prop.active_history = self.active_history
if self.deferred:
prop.deferred = self.deferred
- prop.strategy_key = (
- ("deferred", True),
- ("instrument", True))
+ prop.strategy_key = (("deferred", True), ("instrument", True))
prop.group = self.group
def _setup_event_handlers(self):
@@ -299,8 +291,7 @@ class CompositeProperty(DescriptorProperty):
return
dict_[self.key] = self.composite_class(
- *[state.dict[key] for key in
- self._attribute_keys]
+ *[state.dict[key] for key in self._attribute_keys]
)
def expire_handler(state, keys):
@@ -317,24 +308,27 @@ class CompositeProperty(DescriptorProperty):
state.dict.pop(self.key, None)
- event.listen(self.parent, 'after_insert',
- insert_update_handler, raw=True)
- event.listen(self.parent, 'after_update',
- insert_update_handler, raw=True)
- event.listen(self.parent, 'load',
- load_handler, raw=True, propagate=True)
- event.listen(self.parent, 'refresh',
- refresh_handler, raw=True, propagate=True)
- event.listen(self.parent, 'expire',
- expire_handler, raw=True, propagate=True)
+ event.listen(
+ self.parent, "after_insert", insert_update_handler, raw=True
+ )
+ event.listen(
+ self.parent, "after_update", insert_update_handler, raw=True
+ )
+ event.listen(
+ self.parent, "load", load_handler, raw=True, propagate=True
+ )
+ event.listen(
+ self.parent, "refresh", refresh_handler, raw=True, propagate=True
+ )
+ event.listen(
+ self.parent, "expire", expire_handler, raw=True, propagate=True
+ )
# TODO: need a deserialize hook here
@util.memoized_property
def _attribute_keys(self):
- return [
- prop.key for prop in self.props
- ]
+ return [prop.key for prop in self.props]
def get_history(self, state, dict_, passive=attributes.PASSIVE_OFF):
"""Provided for userland code that uses attributes.get_history()."""
@@ -363,12 +357,10 @@ class CompositeProperty(DescriptorProperty):
return attributes.History(
[self.composite_class(*added)],
(),
- [self.composite_class(*deleted)]
+ [self.composite_class(*deleted)],
)
else:
- return attributes.History(
- (), [self.composite_class(*added)], ()
- )
+ return attributes.History((), [self.composite_class(*added)], ())
def _comparator_factory(self, mapper):
return self.comparator_factory(self, mapper)
@@ -377,12 +369,15 @@ class CompositeProperty(DescriptorProperty):
def __init__(self, property, expr):
self.property = property
super(CompositeProperty.CompositeBundle, self).__init__(
- property.key, *expr)
+ property.key, *expr
+ )
def create_row_processor(self, query, procs, labels):
def proc(row):
return self.property.composite_class(
- *[proc(row) for proc in procs])
+ *[proc(row) for proc in procs]
+ )
+
return proc
class Comparator(PropComparator):
@@ -412,11 +407,13 @@ class CompositeProperty(DescriptorProperty):
def __clause_element__(self):
return expression.ClauseList(
- group=False, *self._comparable_elements)
+ group=False, *self._comparable_elements
+ )
def _query_clause_element(self):
return CompositeProperty.CompositeBundle(
- self.prop, self.__clause_element__())
+ self.prop, self.__clause_element__()
+ )
def _bulk_update_tuples(self, value):
if value is None:
@@ -425,22 +422,18 @@ class CompositeProperty(DescriptorProperty):
values = value.__composite_values__()
else:
raise sa_exc.ArgumentError(
- "Can't UPDATE composite attribute %s to %r" %
- (self.prop, value))
+ "Can't UPDATE composite attribute %s to %r"
+ % (self.prop, value)
+ )
- return zip(
- self._comparable_elements,
- values
- )
+ return zip(self._comparable_elements, values)
@util.memoized_property
def _comparable_elements(self):
if self._adapt_to_entity:
return [
- getattr(
- self._adapt_to_entity.entity,
- prop.key
- ) for prop in self.prop._comparable_elements
+ getattr(self._adapt_to_entity.entity, prop.key)
+ for prop in self.prop._comparable_elements
]
else:
return self.prop._comparable_elements
@@ -451,8 +444,7 @@ class CompositeProperty(DescriptorProperty):
else:
values = other.__composite_values__()
comparisons = [
- a == b
- for a, b in zip(self.prop._comparable_elements, values)
+ a == b for a, b in zip(self.prop._comparable_elements, values)
]
if self._adapt_to_entity:
comparisons = [self.adapter(x) for x in comparisons]
@@ -495,14 +487,16 @@ class ConcreteInheritedProperty(DescriptorProperty):
def __init__(self):
super(ConcreteInheritedProperty, self).__init__()
+
def warn():
- raise AttributeError("Concrete %s does not implement "
- "attribute %r at the instance level. Add "
- "this property explicitly to %s." %
- (self.parent, self.key, self.parent))
+ raise AttributeError(
+ "Concrete %s does not implement "
+ "attribute %r at the instance level. Add "
+ "this property explicitly to %s."
+ % (self.parent, self.key, self.parent)
+ )
class NoninheritedConcreteProp(object):
-
def __set__(s, obj, value):
warn()
@@ -513,15 +507,21 @@ class ConcreteInheritedProperty(DescriptorProperty):
if obj is None:
return self.descriptor
warn()
+
self.descriptor = NoninheritedConcreteProp()
@util.langhelpers.dependency_for("sqlalchemy.orm.properties", add_to_all=True)
class SynonymProperty(DescriptorProperty):
-
- def __init__(self, name, map_column=None,
- descriptor=None, comparator_factory=None,
- doc=None, info=None):
+ def __init__(
+ self,
+ name,
+ map_column=None,
+ descriptor=None,
+ comparator_factory=None,
+ doc=None,
+ info=None,
+ ):
"""Denote an attribute name as a synonym to a mapped property,
in that the attribute will mirror the value and expression behavior
of another attribute.
@@ -639,15 +639,13 @@ class SynonymProperty(DescriptorProperty):
@util.memoized_property
def _proxied_property(self):
attr = getattr(self.parent.class_, self.name)
- if not hasattr(attr, 'property') or not \
- isinstance(attr.property, MapperProperty):
+ if not hasattr(attr, "property") or not isinstance(
+ attr.property, MapperProperty
+ ):
raise sa_exc.InvalidRequestError(
"""synonym() attribute "%s.%s" only supports """
- """ORM mapped attributes, got %r""" % (
- self.parent.class_.__name__,
- self.name,
- attr
- )
+ """ORM mapped attributes, got %r"""
+ % (self.parent.class_.__name__, self.name, attr)
)
return attr.property
@@ -671,23 +669,23 @@ class SynonymProperty(DescriptorProperty):
raise sa_exc.ArgumentError(
"Can't compile synonym '%s': no column on table "
"'%s' named '%s'"
- % (self.name, parent.mapped_table.description, self.key))
- elif parent.mapped_table.c[self.key] in \
- parent._columntoproperty and \
- parent._columntoproperty[
- parent.mapped_table.c[self.key]
- ].key == self.name:
+ % (self.name, parent.mapped_table.description, self.key)
+ )
+ elif (
+ parent.mapped_table.c[self.key] in parent._columntoproperty
+ and parent._columntoproperty[
+ parent.mapped_table.c[self.key]
+ ].key
+ == self.name
+ ):
raise sa_exc.ArgumentError(
"Can't call map_column=True for synonym %r=%r, "
"a ColumnProperty already exists keyed to the name "
- "%r for column %r" %
- (self.key, self.name, self.name, self.key)
+ "%r for column %r"
+ % (self.key, self.name, self.name, self.key)
)
p = properties.ColumnProperty(parent.mapped_table.c[self.key])
- parent._configure_property(
- self.name, p,
- init=init,
- setparent=True)
+ parent._configure_property(self.name, p, init=init, setparent=True)
p._mapped_by_synonym = self.key
self.parent = parent
@@ -698,7 +696,8 @@ class ComparableProperty(DescriptorProperty):
"""Instruments a Python property for use in query expressions."""
def __init__(
- self, comparator_factory, descriptor=None, doc=None, info=None):
+ self, comparator_factory, descriptor=None, doc=None, info=None
+ ):
"""Provides a method of applying a :class:`.PropComparator`
to any Python descriptor attribute.
diff --git a/lib/sqlalchemy/orm/dynamic.py b/lib/sqlalchemy/orm/dynamic.py
index 087e7dcc6..e5c6b80b6 100644
--- a/lib/sqlalchemy/orm/dynamic.py
+++ b/lib/sqlalchemy/orm/dynamic.py
@@ -15,8 +15,13 @@ basic add/delete mutation.
from .. import log, util, exc
from ..sql import operators
from . import (
- attributes, object_session, util as orm_util, strategies,
- object_mapper, exc as orm_exc, properties
+ attributes,
+ object_session,
+ util as orm_util,
+ strategies,
+ object_mapper,
+ exc as orm_exc,
+ properties,
)
from .query import Query
@@ -30,7 +35,8 @@ class DynaLoader(strategies.AbstractRelationshipLoader):
raise exc.InvalidRequestError(
"On relationship %s, 'dynamic' loaders cannot be used with "
"many-to-one/one-to-one relationships and/or "
- "uselist=False." % self.parent_property)
+ "uselist=False." % self.parent_property
+ )
strategies._register_attribute(
self.parent_property,
mapper,
@@ -49,11 +55,20 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
collection = False
dynamic = True
- def __init__(self, class_, key, typecallable,
- dispatch,
- target_mapper, order_by, query_class=None, **kw):
- super(DynamicAttributeImpl, self).\
- __init__(class_, key, typecallable, dispatch, **kw)
+ def __init__(
+ self,
+ class_,
+ key,
+ typecallable,
+ dispatch,
+ target_mapper,
+ order_by,
+ query_class=None,
+ **kw
+ ):
+ super(DynamicAttributeImpl, self).__init__(
+ class_, key, typecallable, dispatch, **kw
+ )
self.target_mapper = target_mapper
self.order_by = order_by
if not query_class:
@@ -66,15 +81,20 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
def get(self, state, dict_, passive=attributes.PASSIVE_OFF):
if not passive & attributes.SQL_OK:
return self._get_collection_history(
- state, attributes.PASSIVE_NO_INITIALIZE).added_items
+ state, attributes.PASSIVE_NO_INITIALIZE
+ ).added_items
else:
return self.query_class(self, state)
- def get_collection(self, state, dict_, user_data=None,
- passive=attributes.PASSIVE_NO_INITIALIZE):
+ def get_collection(
+ self,
+ state,
+ dict_,
+ user_data=None,
+ passive=attributes.PASSIVE_NO_INITIALIZE,
+ ):
if not passive & attributes.SQL_OK:
- return self._get_collection_history(state,
- passive).added_items
+ return self._get_collection_history(state, passive).added_items
else:
history = self._get_collection_history(state, passive)
return history.added_plus_unchanged
@@ -87,8 +107,9 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
def _remove_token(self):
return attributes.Event(self, attributes.OP_REMOVE)
- def fire_append_event(self, state, dict_, value, initiator,
- collection_history=None):
+ def fire_append_event(
+ self, state, dict_, value, initiator, collection_history=None
+ ):
if collection_history is None:
collection_history = self._modified_event(state, dict_)
@@ -100,8 +121,9 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
if self.trackparent and value is not None:
self.sethasparent(attributes.instance_state(value), state, True)
- def fire_remove_event(self, state, dict_, value, initiator,
- collection_history=None):
+ def fire_remove_event(
+ self, state, dict_, value, initiator, collection_history=None
+ ):
if collection_history is None:
collection_history = self._modified_event(state, dict_)
@@ -118,18 +140,24 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
if self.key not in state.committed_state:
state.committed_state[self.key] = CollectionHistory(self, state)
- state._modified_event(dict_,
- self,
- attributes.NEVER_SET)
+ state._modified_event(dict_, self, attributes.NEVER_SET)
# this is a hack to allow the fixtures.ComparableEntity fixture
# to work
dict_[self.key] = True
return state.committed_state[self.key]
- def set(self, state, dict_, value, initiator=None,
- passive=attributes.PASSIVE_OFF,
- check_old=None, pop=False, _adapt=True):
+ def set(
+ self,
+ state,
+ dict_,
+ value,
+ initiator=None,
+ passive=attributes.PASSIVE_OFF,
+ check_old=None,
+ pop=False,
+ _adapt=True,
+ ):
if initiator and initiator.parent_token is self.parent_token:
return
@@ -146,7 +174,8 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
old_collection = collection_history.added_items
else:
old_collection = old_collection.union(
- collection_history.added_items)
+ collection_history.added_items
+ )
idset = util.IdentitySet
constants = old_collection.intersection(new_values)
@@ -155,33 +184,40 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
for member in new_values:
if member in additions:
- self.fire_append_event(state, dict_, member, None,
- collection_history=collection_history)
+ self.fire_append_event(
+ state,
+ dict_,
+ member,
+ None,
+ collection_history=collection_history,
+ )
for member in removals:
- self.fire_remove_event(state, dict_, member, None,
- collection_history=collection_history)
+ self.fire_remove_event(
+ state,
+ dict_,
+ member,
+ None,
+ collection_history=collection_history,
+ )
def delete(self, *args, **kwargs):
raise NotImplementedError()
def set_committed_value(self, state, dict_, value):
- raise NotImplementedError("Dynamic attributes don't support "
- "collection population.")
+ raise NotImplementedError(
+ "Dynamic attributes don't support " "collection population."
+ )
def get_history(self, state, dict_, passive=attributes.PASSIVE_OFF):
c = self._get_collection_history(state, passive)
return c.as_history()
- def get_all_pending(self, state, dict_,
- passive=attributes.PASSIVE_NO_INITIALIZE):
- c = self._get_collection_history(
- state, passive)
- return [
- (attributes.instance_state(x), x)
- for x in
- c.all_items
- ]
+ def get_all_pending(
+ self, state, dict_, passive=attributes.PASSIVE_NO_INITIALIZE
+ ):
+ c = self._get_collection_history(state, passive)
+ return [(attributes.instance_state(x), x) for x in c.all_items]
def _get_collection_history(self, state, passive=attributes.PASSIVE_OFF):
if self.key in state.committed_state:
@@ -194,18 +230,21 @@ class DynamicAttributeImpl(attributes.AttributeImpl):
else:
return c
- def append(self, state, dict_, value, initiator,
- passive=attributes.PASSIVE_OFF):
+ def append(
+ self, state, dict_, value, initiator, passive=attributes.PASSIVE_OFF
+ ):
if initiator is not self:
self.fire_append_event(state, dict_, value, initiator)
- def remove(self, state, dict_, value, initiator,
- passive=attributes.PASSIVE_OFF):
+ def remove(
+ self, state, dict_, value, initiator, passive=attributes.PASSIVE_OFF
+ ):
if initiator is not self:
self.fire_remove_event(state, dict_, value, initiator)
- def pop(self, state, dict_, value, initiator,
- passive=attributes.PASSIVE_OFF):
+ def pop(
+ self, state, dict_, value, initiator, passive=attributes.PASSIVE_OFF
+ ):
self.remove(state, dict_, value, initiator, passive=passive)
@@ -229,30 +268,36 @@ class AppenderMixin(object):
# doesn't fail, and secondary is then in _from_obj[1].
self._from_obj = (prop.mapper.selectable, prop.secondary)
- self._criterion = prop._with_parent(
- instance,
- alias_secondary=False)
+ self._criterion = prop._with_parent(instance, alias_secondary=False)
if self.attr.order_by:
self._order_by = self.attr.order_by
def session(self):
sess = object_session(self.instance)
- if sess is not None and self.autoflush and sess.autoflush \
- and self.instance in sess:
+ if (
+ sess is not None
+ and self.autoflush
+ and sess.autoflush
+ and self.instance in sess
+ ):
sess.flush()
if not orm_util.has_identity(self.instance):
return None
else:
return sess
+
session = property(session, lambda s, x: None)
def __iter__(self):
sess = self.session
if sess is None:
- return iter(self.attr._get_collection_history(
- attributes.instance_state(self.instance),
- attributes.PASSIVE_NO_INITIALIZE).added_items)
+ return iter(
+ self.attr._get_collection_history(
+ attributes.instance_state(self.instance),
+ attributes.PASSIVE_NO_INITIALIZE,
+ ).added_items
+ )
else:
return iter(self._clone(sess))
@@ -261,16 +306,20 @@ class AppenderMixin(object):
if sess is None:
return self.attr._get_collection_history(
attributes.instance_state(self.instance),
- attributes.PASSIVE_NO_INITIALIZE).indexed(index)
+ attributes.PASSIVE_NO_INITIALIZE,
+ ).indexed(index)
else:
return self._clone(sess).__getitem__(index)
def count(self):
sess = self.session
if sess is None:
- return len(self.attr._get_collection_history(
- attributes.instance_state(self.instance),
- attributes.PASSIVE_NO_INITIALIZE).added_items)
+ return len(
+ self.attr._get_collection_history(
+ attributes.instance_state(self.instance),
+ attributes.PASSIVE_NO_INITIALIZE,
+ ).added_items
+ )
else:
return self._clone(sess).count()
@@ -285,8 +334,9 @@ class AppenderMixin(object):
raise orm_exc.DetachedInstanceError(
"Parent instance %s is not bound to a Session, and no "
"contextual session is established; lazy load operation "
- "of attribute '%s' cannot proceed" % (
- orm_util.instance_str(instance), self.attr.key))
+ "of attribute '%s' cannot proceed"
+ % (orm_util.instance_str(instance), self.attr.key)
+ )
if self.query_class:
query = self.query_class(self.attr.target_mapper, session=sess)
@@ -303,17 +353,26 @@ class AppenderMixin(object):
for item in iterator:
self.attr.append(
attributes.instance_state(self.instance),
- attributes.instance_dict(self.instance), item, None)
+ attributes.instance_dict(self.instance),
+ item,
+ None,
+ )
def append(self, item):
self.attr.append(
attributes.instance_state(self.instance),
- attributes.instance_dict(self.instance), item, None)
+ attributes.instance_dict(self.instance),
+ item,
+ None,
+ )
def remove(self, item):
self.attr.remove(
attributes.instance_state(self.instance),
- attributes.instance_dict(self.instance), item, None)
+ attributes.instance_dict(self.instance),
+ item,
+ None,
+ )
class AppenderQuery(AppenderMixin, Query):
@@ -322,8 +381,8 @@ class AppenderQuery(AppenderMixin, Query):
def mixin_user_query(cls):
"""Return a new class with AppenderQuery functionality layered over."""
- name = 'Appender' + cls.__name__
- return type(name, (AppenderMixin, cls), {'query_class': cls})
+ name = "Appender" + cls.__name__
+ return type(name, (AppenderMixin, cls), {"query_class": cls})
class CollectionHistory(object):
@@ -348,8 +407,11 @@ class CollectionHistory(object):
@property
def all_items(self):
- return list(self.added_items.union(
- self.unchanged_items).union(self.deleted_items))
+ return list(
+ self.added_items.union(self.unchanged_items).union(
+ self.deleted_items
+ )
+ )
def as_history(self):
if self._reconcile_collection:
@@ -357,14 +419,12 @@ class CollectionHistory(object):
deleted = self.deleted_items.intersection(self.unchanged_items)
unchanged = self.unchanged_items.difference(deleted)
else:
- added, unchanged, deleted = self.added_items,\
- self.unchanged_items,\
- self.deleted_items
- return attributes.History(
- list(added),
- list(unchanged),
- list(deleted),
- )
+ added, unchanged, deleted = (
+ self.added_items,
+ self.unchanged_items,
+ self.deleted_items,
+ )
+ return attributes.History(list(added), list(unchanged), list(deleted))
def indexed(self, index):
return list(self.added_items)[index]
diff --git a/lib/sqlalchemy/orm/evaluator.py b/lib/sqlalchemy/orm/evaluator.py
index 4abf08ab1..ac031d84f 100644
--- a/lib/sqlalchemy/orm/evaluator.py
+++ b/lib/sqlalchemy/orm/evaluator.py
@@ -14,17 +14,40 @@ from .. import util
class UnevaluatableError(Exception):
pass
-_straight_ops = set(getattr(operators, op)
- for op in ('add', 'mul', 'sub',
- 'div',
- 'mod', 'truediv',
- 'lt', 'le', 'ne', 'gt', 'ge', 'eq'))
-
-_notimplemented_ops = set(getattr(operators, op)
- for op in ('like_op', 'notlike_op', 'ilike_op',
- 'notilike_op', 'between_op', 'in_op',
- 'notin_op', 'endswith_op', 'concat_op'))
+_straight_ops = set(
+ getattr(operators, op)
+ for op in (
+ "add",
+ "mul",
+ "sub",
+ "div",
+ "mod",
+ "truediv",
+ "lt",
+ "le",
+ "ne",
+ "gt",
+ "ge",
+ "eq",
+ )
+)
+
+
+_notimplemented_ops = set(
+ getattr(operators, op)
+ for op in (
+ "like_op",
+ "notlike_op",
+ "ilike_op",
+ "notilike_op",
+ "between_op",
+ "in_op",
+ "notin_op",
+ "endswith_op",
+ "concat_op",
+ )
+)
class EvaluatorCompiler(object):
@@ -35,7 +58,8 @@ class EvaluatorCompiler(object):
meth = getattr(self, "visit_%s" % clause.__visit_name__, None)
if not meth:
raise UnevaluatableError(
- "Cannot evaluate %s" % type(clause).__name__)
+ "Cannot evaluate %s" % type(clause).__name__
+ )
return meth(clause)
def visit_grouping(self, clause):
@@ -51,28 +75,30 @@ class EvaluatorCompiler(object):
return lambda obj: True
def visit_column(self, clause):
- if 'parentmapper' in clause._annotations:
- parentmapper = clause._annotations['parentmapper']
+ if "parentmapper" in clause._annotations:
+ parentmapper = clause._annotations["parentmapper"]
if self.target_cls and not issubclass(
- self.target_cls, parentmapper.class_):
+ self.target_cls, parentmapper.class_
+ ):
raise UnevaluatableError(
- "Can't evaluate criteria against alternate class %s" %
- parentmapper.class_
+ "Can't evaluate criteria against alternate class %s"
+ % parentmapper.class_
)
key = parentmapper._columntoproperty[clause].key
else:
key = clause.key
- if self.target_cls and \
- key in inspect(self.target_cls).column_attrs:
+ if (
+ self.target_cls
+ and key in inspect(self.target_cls).column_attrs
+ ):
util.warn(
"Evaluating non-mapped column expression '%s' onto "
"ORM instances; this is a deprecated use case. Please "
"make use of the actual mapped columns in ORM-evaluated "
- "UPDATE / DELETE expressions." % clause)
- else:
- raise UnevaluatableError(
- "Cannot evaluate column: %s" % clause
+ "UPDATE / DELETE expressions." % clause
)
+ else:
+ raise UnevaluatableError("Cannot evaluate column: %s" % clause)
get_corresponding_attr = operator.attrgetter(key)
return lambda obj: get_corresponding_attr(obj)
@@ -80,6 +106,7 @@ class EvaluatorCompiler(object):
def visit_clauselist(self, clause):
evaluators = list(map(self.process, clause.clauses))
if clause.operator is operators.or_:
+
def evaluate(obj):
has_null = False
for sub_evaluate in evaluators:
@@ -90,7 +117,9 @@ class EvaluatorCompiler(object):
if has_null:
return None
return False
+
elif clause.operator is operators.and_:
+
def evaluate(obj):
for sub_evaluate in evaluators:
value = sub_evaluate(obj)
@@ -99,48 +128,60 @@ class EvaluatorCompiler(object):
return None
return False
return True
+
else:
raise UnevaluatableError(
- "Cannot evaluate clauselist with operator %s" %
- clause.operator)
+ "Cannot evaluate clauselist with operator %s" % clause.operator
+ )
return evaluate
def visit_binary(self, clause):
- eval_left, eval_right = list(map(self.process,
- [clause.left, clause.right]))
+ eval_left, eval_right = list(
+ map(self.process, [clause.left, clause.right])
+ )
operator = clause.operator
if operator is operators.is_:
+
def evaluate(obj):
return eval_left(obj) == eval_right(obj)
+
elif operator is operators.isnot:
+
def evaluate(obj):
return eval_left(obj) != eval_right(obj)
+
elif operator in _straight_ops:
+
def evaluate(obj):
left_val = eval_left(obj)
right_val = eval_right(obj)
if left_val is None or right_val is None:
return None
return operator(eval_left(obj), eval_right(obj))
+
else:
raise UnevaluatableError(
- "Cannot evaluate %s with operator %s" %
- (type(clause).__name__, clause.operator))
+ "Cannot evaluate %s with operator %s"
+ % (type(clause).__name__, clause.operator)
+ )
return evaluate
def visit_unary(self, clause):
eval_inner = self.process(clause.element)
if clause.operator is operators.inv:
+
def evaluate(obj):
value = eval_inner(obj)
if value is None:
return None
return not value
+
return evaluate
raise UnevaluatableError(
- "Cannot evaluate %s with operator %s" %
- (type(clause).__name__, clause.operator))
+ "Cannot evaluate %s with operator %s"
+ % (type(clause).__name__, clause.operator)
+ )
def visit_bindparam(self, clause):
if clause.callable:
diff --git a/lib/sqlalchemy/orm/events.py b/lib/sqlalchemy/orm/events.py
index c414f548e..c2a2d15ee 100644
--- a/lib/sqlalchemy/orm/events.py
+++ b/lib/sqlalchemy/orm/events.py
@@ -20,6 +20,7 @@ from .attributes import QueryableAttribute
from .query import Query
from sqlalchemy.util.compat import inspect_getargspec
+
class InstrumentationEvents(event.Events):
"""Events related to class instrumentation events.
@@ -61,9 +62,11 @@ class InstrumentationEvents(event.Events):
@classmethod
def _listen(cls, event_key, propagate=True, **kw):
- target, identifier, fn = \
- event_key.dispatch_target, event_key.identifier, \
- event_key._listen_fn
+ target, identifier, fn = (
+ event_key.dispatch_target,
+ event_key.identifier,
+ event_key._listen_fn,
+ )
def listen(target_cls, *arg):
listen_cls = target()
@@ -74,16 +77,20 @@ class InstrumentationEvents(event.Events):
def remove(ref):
key = event.registry._EventKey(
- None, identifier, listen,
- instrumentation._instrumentation_factory)
- getattr(instrumentation._instrumentation_factory.dispatch,
- identifier).remove(key)
+ None,
+ identifier,
+ listen,
+ instrumentation._instrumentation_factory,
+ )
+ getattr(
+ instrumentation._instrumentation_factory.dispatch, identifier
+ ).remove(key)
target = weakref.ref(target.class_, remove)
- event_key.\
- with_dispatch_target(instrumentation._instrumentation_factory).\
- with_wrapper(listen).base_listen(**kw)
+ event_key.with_dispatch_target(
+ instrumentation._instrumentation_factory
+ ).with_wrapper(listen).base_listen(**kw)
@classmethod
def _clear(cls):
@@ -193,21 +200,24 @@ class InstanceEvents(event.Events):
@classmethod
def _listen(cls, event_key, raw=False, propagate=False, **kw):
- target, identifier, fn = \
- event_key.dispatch_target, event_key.identifier, \
- event_key._listen_fn
+ target, identifier, fn = (
+ event_key.dispatch_target,
+ event_key.identifier,
+ event_key._listen_fn,
+ )
if not raw:
+
def wrap(state, *arg, **kw):
return fn(state.obj(), *arg, **kw)
+
event_key = event_key.with_wrapper(wrap)
event_key.base_listen(propagate=propagate, **kw)
if propagate:
for mgr in target.subclass_managers(True):
- event_key.with_dispatch_target(mgr).base_listen(
- propagate=True)
+ event_key.with_dispatch_target(mgr).base_listen(propagate=True)
@classmethod
def _clear(cls):
@@ -438,10 +448,13 @@ class _EventsHold(event.RefCollection):
@classmethod
def _listen(
- cls, event_key, raw=False, propagate=False,
- retval=False, **kw):
- target, identifier, fn = \
- event_key.dispatch_target, event_key.identifier, event_key.fn
+ cls, event_key, raw=False, propagate=False, retval=False, **kw
+ ):
+ target, identifier, fn = (
+ event_key.dispatch_target,
+ event_key.identifier,
+ event_key.fn,
+ )
if target.class_ in target.all_holds:
collection = target.all_holds[target.class_]
@@ -460,12 +473,16 @@ class _EventsHold(event.RefCollection):
if subject is not None:
# we are already going through __subclasses__()
# so leave generic propagate flag False
- event_key.with_dispatch_target(subject).\
- listen(raw=raw, propagate=False, retval=retval, **kw)
+ event_key.with_dispatch_target(subject).listen(
+ raw=raw, propagate=False, retval=retval, **kw
+ )
def remove(self, event_key):
- target, identifier, fn = \
- event_key.dispatch_target, event_key.identifier, event_key.fn
+ target, identifier, fn = (
+ event_key.dispatch_target,
+ event_key.identifier,
+ event_key.fn,
+ )
if isinstance(target, _EventsHold):
collection = target.all_holds[target.class_]
@@ -483,8 +500,9 @@ class _EventsHold(event.RefCollection):
# populate(), we rely upon _EventsHold for all event
# assignment, instead of using the generic propagate
# flag.
- event_key.with_dispatch_target(subject).\
- listen(raw=raw, propagate=False, retval=retval)
+ event_key.with_dispatch_target(subject).listen(
+ raw=raw, propagate=False, retval=retval
+ )
class _InstanceEventsHold(_EventsHold):
@@ -594,24 +612,31 @@ class MapperEvents(event.Events):
@classmethod
def _listen(
- cls, event_key, raw=False, retval=False, propagate=False, **kw):
- target, identifier, fn = \
- event_key.dispatch_target, event_key.identifier, \
- event_key._listen_fn
-
- if identifier in ("before_configured", "after_configured") and \
- target is not mapperlib.Mapper:
+ cls, event_key, raw=False, retval=False, propagate=False, **kw
+ ):
+ target, identifier, fn = (
+ event_key.dispatch_target,
+ event_key.identifier,
+ event_key._listen_fn,
+ )
+
+ if (
+ identifier in ("before_configured", "after_configured")
+ and target is not mapperlib.Mapper
+ ):
util.warn(
"'before_configured' and 'after_configured' ORM events "
"only invoke with the mapper() function or Mapper class "
- "as the target.")
+ "as the target."
+ )
if not raw or not retval:
if not raw:
meth = getattr(cls, identifier)
try:
- target_index = \
- inspect_getargspec(meth)[0].index('target') - 1
+ target_index = (
+ inspect_getargspec(meth)[0].index("target") - 1
+ )
except ValueError:
target_index = None
@@ -624,12 +649,14 @@ class MapperEvents(event.Events):
return interfaces.EXT_CONTINUE
else:
return fn(*arg, **kw)
+
event_key = event_key.with_wrapper(wrap)
if propagate:
for mapper in target.self_and_descendants:
event_key.with_dispatch_target(mapper).base_listen(
- propagate=True, **kw)
+ propagate=True, **kw
+ )
else:
event_key.base_listen(**kw)
@@ -1219,15 +1246,14 @@ class SessionEvents(event.Events):
if isinstance(target, scoped_session):
target = target.session_factory
- if not isinstance(target, sessionmaker) and \
- (
- not isinstance(target, type) or
- not issubclass(target, Session)
+ if not isinstance(target, sessionmaker) and (
+ not isinstance(target, type) or not issubclass(target, Session)
):
raise exc.ArgumentError(
"Session event listen on a scoped_session "
"requires that its creation callable "
- "is associated with the Session class.")
+ "is associated with the Session class."
+ )
if isinstance(target, sessionmaker):
return target.class_
@@ -1561,13 +1587,16 @@ class SessionEvents(event.Events):
"""
- @event._legacy_signature("0.9",
- ["session", "query", "query_context", "result"],
- lambda update_context: (
- update_context.session,
- update_context.query,
- update_context.context,
- update_context.result))
+ @event._legacy_signature(
+ "0.9",
+ ["session", "query", "query_context", "result"],
+ lambda update_context: (
+ update_context.session,
+ update_context.query,
+ update_context.context,
+ update_context.result,
+ ),
+ )
def after_bulk_update(self, update_context):
"""Execute after a bulk update operation to the session.
@@ -1587,13 +1616,16 @@ class SessionEvents(event.Events):
"""
- @event._legacy_signature("0.9",
- ["session", "query", "query_context", "result"],
- lambda delete_context: (
- delete_context.session,
- delete_context.query,
- delete_context.context,
- delete_context.result))
+ @event._legacy_signature(
+ "0.9",
+ ["session", "query", "query_context", "result"],
+ lambda delete_context: (
+ delete_context.session,
+ delete_context.query,
+ delete_context.context,
+ delete_context.result,
+ ),
+ )
def after_bulk_delete(self, delete_context):
"""Execute after a bulk delete operation to the session.
@@ -1927,18 +1959,26 @@ class AttributeEvents(event.Events):
return target
@classmethod
- def _listen(cls, event_key, active_history=False,
- raw=False, retval=False,
- propagate=False):
-
- target, identifier, fn = \
- event_key.dispatch_target, event_key.identifier, \
- event_key._listen_fn
+ def _listen(
+ cls,
+ event_key,
+ active_history=False,
+ raw=False,
+ retval=False,
+ propagate=False,
+ ):
+
+ target, identifier, fn = (
+ event_key.dispatch_target,
+ event_key.identifier,
+ event_key._listen_fn,
+ )
if active_history:
target.dispatch._active_history = True
if not raw or not retval:
+
def wrap(target, *arg):
if not raw:
target = target.obj()
@@ -1951,6 +1991,7 @@ class AttributeEvents(event.Events):
return value
else:
return fn(target, *arg)
+
event_key = event_key.with_wrapper(wrap)
event_key.base_listen(propagate=propagate)
@@ -1959,8 +2000,9 @@ class AttributeEvents(event.Events):
manager = instrumentation.manager_of_class(target.class_)
for mgr in manager.subclass_managers(True):
- event_key.with_dispatch_target(
- mgr[target.key]).base_listen(propagate=True)
+ event_key.with_dispatch_target(mgr[target.key]).base_listen(
+ propagate=True
+ )
def append(self, target, value, initiator):
"""Receive a collection append event.
@@ -2315,11 +2357,11 @@ class QueryEvents(event.Events):
"""
@classmethod
- def _listen(
- cls, event_key, retval=False, **kw):
+ def _listen(cls, event_key, retval=False, **kw):
fn = event_key._listen_fn
if not retval:
+
def wrap(*arg, **kw):
if not retval:
query = arg[0]
@@ -2327,6 +2369,7 @@ class QueryEvents(event.Events):
return query
else:
return fn(*arg, **kw)
+
event_key = event_key.with_wrapper(wrap)
event_key.base_listen(**kw)
diff --git a/lib/sqlalchemy/orm/exc.py b/lib/sqlalchemy/orm/exc.py
index eb4baa08d..f0aa02e99 100644
--- a/lib/sqlalchemy/orm/exc.py
+++ b/lib/sqlalchemy/orm/exc.py
@@ -38,6 +38,7 @@ class StaleDataError(sa_exc.SQLAlchemyError):
"""
+
ConcurrentModificationError = StaleDataError
@@ -72,16 +73,19 @@ class UnmappedInstanceError(UnmappedError):
try:
base.class_mapper(type(obj))
name = _safe_cls_name(type(obj))
- msg = ("Class %r is mapped, but this instance lacks "
- "instrumentation. This occurs when the instance "
- "is created before sqlalchemy.orm.mapper(%s) "
- "was called." % (name, name))
+ msg = (
+ "Class %r is mapped, but this instance lacks "
+ "instrumentation. This occurs when the instance "
+ "is created before sqlalchemy.orm.mapper(%s) "
+ "was called." % (name, name)
+ )
except UnmappedClassError:
msg = _default_unmapped(type(obj))
if isinstance(obj, type):
msg += (
- '; was a class (%s) supplied where an instance was '
- 'required?' % _safe_cls_name(obj))
+ "; was a class (%s) supplied where an instance was "
+ "required?" % _safe_cls_name(obj)
+ )
UnmappedError.__init__(self, msg)
def __reduce__(self):
@@ -119,11 +123,14 @@ class ObjectDeletedError(sa_exc.InvalidRequestError):
object.
"""
+
@util.dependencies("sqlalchemy.orm.base")
def __init__(self, base, state, msg=None):
if not msg:
- msg = "Instance '%s' has been deleted, or its "\
+ msg = (
+ "Instance '%s' has been deleted, or its "
"row is otherwise not present." % base.state_str(state)
+ )
sa_exc.InvalidRequestError.__init__(self, msg)
@@ -145,9 +152,9 @@ class MultipleResultsFound(sa_exc.InvalidRequestError):
def _safe_cls_name(cls):
try:
- cls_name = '.'.join((cls.__module__, cls.__name__))
+ cls_name = ".".join((cls.__module__, cls.__name__))
except AttributeError:
- cls_name = getattr(cls, '__name__', None)
+ cls_name = getattr(cls, "__name__", None)
if cls_name is None:
cls_name = repr(cls)
return cls_name
diff --git a/lib/sqlalchemy/orm/identity.py b/lib/sqlalchemy/orm/identity.py
index b03bb0a0d..2487cdb23 100644
--- a/lib/sqlalchemy/orm/identity.py
+++ b/lib/sqlalchemy/orm/identity.py
@@ -11,6 +11,7 @@ from .. import util
from .. import exc as sa_exc
from . import util as orm_util
+
class IdentityMap(object):
def __init__(self):
self._dict = {}
@@ -84,7 +85,6 @@ class IdentityMap(object):
class WeakInstanceDict(IdentityMap):
-
def __getitem__(self, key):
state = self._dict[key]
o = state.obj()
@@ -145,8 +145,9 @@ class WeakInstanceDict(IdentityMap):
raise sa_exc.InvalidRequestError(
"Can't attach instance "
"%s; another instance with key %s is already "
- "present in this session." % (
- orm_util.state_str(state), state.key))
+ "present in this session."
+ % (orm_util.state_str(state), state.key)
+ )
else:
return False
self._dict[key] = state
@@ -253,6 +254,7 @@ class StrongInstanceDict(IdentityMap):
"""
if util.py2k:
+
def itervalues(self):
return self._dict.itervalues()
@@ -282,8 +284,9 @@ class StrongInstanceDict(IdentityMap):
def contains_state(self, state):
return (
- state.key in self and
- attributes.instance_state(self[state.key]) is state)
+ state.key in self
+ and attributes.instance_state(self[state.key]) is state
+ )
def replace(self, state):
if state.key in self._dict:
@@ -303,8 +306,9 @@ class StrongInstanceDict(IdentityMap):
raise sa_exc.InvalidRequestError(
"Can't attach instance "
"%s; another instance with key %s is already "
- "present in this session." % (
- orm_util.state_str(state), state.key))
+ "present in this session."
+ % (orm_util.state_str(state), state.key)
+ )
return False
else:
self._dict[state.key] = state.obj()
diff --git a/lib/sqlalchemy/orm/instrumentation.py b/lib/sqlalchemy/orm/instrumentation.py
index d34326e0f..fa29c3233 100644
--- a/lib/sqlalchemy/orm/instrumentation.py
+++ b/lib/sqlalchemy/orm/instrumentation.py
@@ -59,11 +59,15 @@ class ClassManager(dict):
self.local_attrs = {}
self.originals = {}
- self._bases = [mgr for mgr in [
- manager_of_class(base)
- for base in self.class_.__bases__
- if isinstance(base, type)
- ] if mgr is not None]
+ self._bases = [
+ mgr
+ for mgr in [
+ manager_of_class(base)
+ for base in self.class_.__bases__
+ if isinstance(base, type)
+ ]
+ if mgr is not None
+ ]
for base in self._bases:
self.update(base)
@@ -78,12 +82,13 @@ class ClassManager(dict):
self.manage()
self._instrument_init()
- if '__del__' in class_.__dict__:
- util.warn("__del__() method on class %s will "
- "cause unreachable cycles and memory leaks, "
- "as SQLAlchemy instrumentation often creates "
- "reference cycles. Please remove this method." %
- class_)
+ if "__del__" in class_.__dict__:
+ util.warn(
+ "__del__() method on class %s will "
+ "cause unreachable cycles and memory leaks, "
+ "as SQLAlchemy instrumentation often creates "
+ "reference cycles. Please remove this method." % class_
+ )
def __hash__(self):
return id(self)
@@ -93,7 +98,7 @@ class ClassManager(dict):
@property
def is_mapped(self):
- return 'mapper' in self.__dict__
+ return "mapper" in self.__dict__
@_memoized_key_collection
def _all_key_set(self):
@@ -101,14 +106,19 @@ class ClassManager(dict):
@_memoized_key_collection
def _collection_impl_keys(self):
- return frozenset([
- attr.key for attr in self.values() if attr.impl.collection])
+ return frozenset(
+ [attr.key for attr in self.values() if attr.impl.collection]
+ )
@_memoized_key_collection
def _scalar_loader_impls(self):
- return frozenset([
- attr.impl for attr in
- self.values() if attr.impl.accepts_scalar_loader])
+ return frozenset(
+ [
+ attr.impl
+ for attr in self.values()
+ if attr.impl.accepts_scalar_loader
+ ]
+ )
@util.memoized_property
def mapper(self):
@@ -174,11 +184,11 @@ class ClassManager(dict):
# of such, since this adds method overhead.
self.original_init = self.class_.__init__
self.new_init = _generate_init(self.class_, self)
- self.install_member('__init__', self.new_init)
+ self.install_member("__init__", self.new_init)
def _uninstrument_init(self):
if self.new_init:
- self.uninstall_member('__init__')
+ self.uninstall_member("__init__")
self.new_init = None
@util.memoized_property
@@ -239,8 +249,9 @@ class ClassManager(dict):
yield m
def post_configure_attribute(self, key):
- _instrumentation_factory.dispatch.\
- attribute_instrument(self.class_, key, self[key])
+ _instrumentation_factory.dispatch.attribute_instrument(
+ self.class_, key, self[key]
+ )
def uninstrument_attribute(self, key, propagated=False):
if key not in self:
@@ -272,9 +283,10 @@ class ClassManager(dict):
def install_descriptor(self, key, inst):
if key in (self.STATE_ATTR, self.MANAGER_ATTR):
- raise KeyError("%r: requested attribute name conflicts with "
- "instrumentation attribute of the same name." %
- key)
+ raise KeyError(
+ "%r: requested attribute name conflicts with "
+ "instrumentation attribute of the same name." % key
+ )
setattr(self.class_, key, inst)
def uninstall_descriptor(self, key):
@@ -282,9 +294,10 @@ class ClassManager(dict):
def install_member(self, key, implementation):
if key in (self.STATE_ATTR, self.MANAGER_ATTR):
- raise KeyError("%r: requested attribute name conflicts with "
- "instrumentation attribute of the same name." %
- key)
+ raise KeyError(
+ "%r: requested attribute name conflicts with "
+ "instrumentation attribute of the same name." % key
+ )
self.originals.setdefault(key, getattr(self.class_, key, None))
setattr(self.class_, key, implementation)
@@ -299,7 +312,8 @@ class ClassManager(dict):
def initialize_collection(self, key, state, factory):
user_data = factory()
adapter = collections.CollectionAdapter(
- self.get_impl(key), state, user_data)
+ self.get_impl(key), state, user_data
+ )
return adapter, user_data
def is_instrumented(self, key, search=False):
@@ -343,15 +357,15 @@ class ClassManager(dict):
"""
if hasattr(instance, self.STATE_ATTR):
return False
- elif self.class_ is not instance.__class__ and \
- self.is_mapped:
+ elif self.class_ is not instance.__class__ and self.is_mapped:
# this will create a new ClassManager for the
# subclass, without a mapper. This is likely a
# user error situation but allow the object
# to be constructed, so that it is usable
# in a non-ORM context at least.
- return self._subclass_manager(instance.__class__).\
- _new_state_if_none(instance)
+ return self._subclass_manager(
+ instance.__class__
+ )._new_state_if_none(instance)
else:
state = self._state_constructor(instance, self)
self._state_setter(instance, state)
@@ -371,8 +385,11 @@ class ClassManager(dict):
__nonzero__ = __bool__
def __repr__(self):
- return '<%s of %r at %x>' % (
- self.__class__.__name__, self.class_, id(self))
+ return "<%s of %r at %x>" % (
+ self.__class__.__name__,
+ self.class_,
+ id(self),
+ )
class _SerializeManager(object):
@@ -396,8 +413,8 @@ class _SerializeManager(object):
"Cannot deserialize object of type %r - "
"no mapper() has "
"been configured for this class within the current "
- "Python process!" %
- self.class_)
+ "Python process!" % self.class_,
+ )
elif manager.is_mapped and not manager.mapper.configured:
manager.mapper._configure_all()
@@ -447,6 +464,7 @@ class InstrumentationFactory(object):
if ClassManager.MANAGER_ATTR in class_.__dict__:
delattr(class_, ClassManager.MANAGER_ATTR)
+
# this attribute is replaced by sqlalchemy.ext.instrumentation
# when importred.
_instrumentation_factory = InstrumentationFactory()
@@ -488,8 +506,9 @@ def is_instrumented(instance, key):
applied directly to the class, i.e. no descriptors are required.
"""
- return manager_of_class(instance.__class__).\
- is_instrumented(key, search=True)
+ return manager_of_class(instance.__class__).is_instrumented(
+ key, search=True
+ )
def _generate_init(class_, class_manager):
@@ -518,15 +537,15 @@ def __init__(%(apply_pos)s):
func_text = func_body % func_vars
if util.py2k:
- func = getattr(original__init__, 'im_func', original__init__)
- func_defaults = getattr(func, 'func_defaults', None)
+ func = getattr(original__init__, "im_func", original__init__)
+ func_defaults = getattr(func, "func_defaults", None)
else:
- func_defaults = getattr(original__init__, '__defaults__', None)
- func_kw_defaults = getattr(original__init__, '__kwdefaults__', None)
+ func_defaults = getattr(original__init__, "__defaults__", None)
+ func_kw_defaults = getattr(original__init__, "__kwdefaults__", None)
env = locals().copy()
exec(func_text, env)
- __init__ = env['__init__']
+ __init__ = env["__init__"]
__init__.__doc__ = original__init__.__doc__
__init__._sa_original_init = original__init__
diff --git a/lib/sqlalchemy/orm/interfaces.py b/lib/sqlalchemy/orm/interfaces.py
index 80d0a6303..d7e70c5d7 100644
--- a/lib/sqlalchemy/orm/interfaces.py
+++ b/lib/sqlalchemy/orm/interfaces.py
@@ -22,8 +22,15 @@ from __future__ import absolute_import
from .. import util
from ..sql import operators
-from .base import (ONETOMANY, MANYTOONE, MANYTOMANY,
- EXT_CONTINUE, EXT_STOP, EXT_SKIP, NOT_EXTENSION)
+from .base import (
+ ONETOMANY,
+ MANYTOONE,
+ MANYTOMANY,
+ EXT_CONTINUE,
+ EXT_STOP,
+ EXT_SKIP,
+ NOT_EXTENSION,
+)
from .base import InspectionAttr, InspectionAttrInfo, _MappedAttribute
import collections
from .. import inspect
@@ -33,21 +40,21 @@ from . import path_registry
MapperExtension = SessionExtension = AttributeExtension = None
__all__ = (
- 'AttributeExtension',
- 'EXT_CONTINUE',
- 'EXT_STOP',
- 'EXT_SKIP',
- 'ONETOMANY',
- 'MANYTOMANY',
- 'MANYTOONE',
- 'NOT_EXTENSION',
- 'LoaderStrategy',
- 'MapperExtension',
- 'MapperOption',
- 'MapperProperty',
- 'PropComparator',
- 'SessionExtension',
- 'StrategizedProperty',
+ "AttributeExtension",
+ "EXT_CONTINUE",
+ "EXT_STOP",
+ "EXT_SKIP",
+ "ONETOMANY",
+ "MANYTOMANY",
+ "MANYTOONE",
+ "NOT_EXTENSION",
+ "LoaderStrategy",
+ "MapperExtension",
+ "MapperOption",
+ "MapperProperty",
+ "PropComparator",
+ "SessionExtension",
+ "StrategizedProperty",
)
@@ -64,8 +71,11 @@ class MapperProperty(_MappedAttribute, InspectionAttr, util.MemoizedSlots):
"""
__slots__ = (
- '_configure_started', '_configure_finished', 'parent', 'key',
- 'info'
+ "_configure_started",
+ "_configure_finished",
+ "parent",
+ "key",
+ "info",
)
cascade = frozenset()
@@ -118,15 +128,17 @@ class MapperProperty(_MappedAttribute, InspectionAttr, util.MemoizedSlots):
"""
- def create_row_processor(self, context, path,
- mapper, result, adapter, populators):
+ def create_row_processor(
+ self, context, path, mapper, result, adapter, populators
+ ):
"""Produce row processing functions and append to the given
set of populators lists.
"""
- def cascade_iterator(self, type_, state, visited_instances=None,
- halt_on=None):
+ def cascade_iterator(
+ self, type_, state, visited_instances=None, halt_on=None
+ ):
"""Iterate through instances related to the given instance for
a particular 'cascade', starting with this MapperProperty.
@@ -234,17 +246,28 @@ class MapperProperty(_MappedAttribute, InspectionAttr, util.MemoizedSlots):
"""
- def merge(self, session, source_state, source_dict, dest_state,
- dest_dict, load, _recursive, _resolve_conflict_map):
+ def merge(
+ self,
+ session,
+ source_state,
+ source_dict,
+ dest_state,
+ dest_dict,
+ load,
+ _recursive,
+ _resolve_conflict_map,
+ ):
"""Merge the attribute represented by this ``MapperProperty``
from source to destination object.
"""
def __repr__(self):
- return '<%s at 0x%x; %s>' % (
+ return "<%s at 0x%x; %s>" % (
self.__class__.__name__,
- id(self), getattr(self, 'key', 'no key'))
+ id(self),
+ getattr(self, "key", "no key"),
+ )
class PropComparator(operators.ColumnOperators):
@@ -335,7 +358,7 @@ class PropComparator(operators.ColumnOperators):
"""
- __slots__ = 'prop', 'property', '_parententity', '_adapt_to_entity'
+ __slots__ = "prop", "property", "_parententity", "_adapt_to_entity"
def __init__(self, prop, parentmapper, adapt_to_entity=None):
self.prop = self.property = prop
@@ -467,21 +490,27 @@ class StrategizedProperty(MapperProperty):
"""
__slots__ = (
- '_strategies', 'strategy',
- '_wildcard_token', '_default_path_loader_key'
+ "_strategies",
+ "strategy",
+ "_wildcard_token",
+ "_default_path_loader_key",
)
strategy_wildcard_key = None
def _memoized_attr__wildcard_token(self):
- return ("%s:%s" % (
- self.strategy_wildcard_key, path_registry._WILDCARD_TOKEN), )
+ return (
+ "%s:%s"
+ % (self.strategy_wildcard_key, path_registry._WILDCARD_TOKEN),
+ )
def _memoized_attr__default_path_loader_key(self):
return (
"loader",
- ("%s:%s" % (
- self.strategy_wildcard_key, path_registry._DEFAULT_TOKEN), )
+ (
+ "%s:%s"
+ % (self.strategy_wildcard_key, path_registry._DEFAULT_TOKEN),
+ ),
)
def _get_context_loader(self, context, path):
@@ -496,7 +525,7 @@ class StrategizedProperty(MapperProperty):
for path_key in (
search_path._loader_key,
search_path._wildcard_path_loader_key,
- search_path._default_path_loader_key
+ search_path._default_path_loader_key,
):
if path_key in context.attributes:
load = context.attributes[path_key]
@@ -509,12 +538,12 @@ class StrategizedProperty(MapperProperty):
return self._strategies[key]
except KeyError:
cls = self._strategy_lookup(*key)
- self._strategies[key] = self._strategies[
- cls] = strategy = cls(self, key)
+ self._strategies[key] = self._strategies[cls] = strategy = cls(
+ self, key
+ )
return strategy
- def setup(
- self, context, entity, path, adapter, **kwargs):
+ def setup(self, context, entity, path, adapter, **kwargs):
loader = self._get_context_loader(context, path)
if loader and loader.strategy:
strat = self._get_strategy(loader.strategy)
@@ -523,24 +552,26 @@ class StrategizedProperty(MapperProperty):
strat.setup_query(context, entity, path, loader, adapter, **kwargs)
def create_row_processor(
- self, context, path, mapper,
- result, adapter, populators):
+ self, context, path, mapper, result, adapter, populators
+ ):
loader = self._get_context_loader(context, path)
if loader and loader.strategy:
strat = self._get_strategy(loader.strategy)
else:
strat = self.strategy
strat.create_row_processor(
- context, path, loader,
- mapper, result, adapter, populators)
+ context, path, loader, mapper, result, adapter, populators
+ )
def do_init(self):
self._strategies = {}
self.strategy = self._get_strategy(self.strategy_key)
def post_instrument_class(self, mapper):
- if not self.parent.non_primary and \
- not mapper.class_manager._attr_has_impl(self.key):
+ if (
+ not self.parent.non_primary
+ and not mapper.class_manager._attr_has_impl(self.key)
+ ):
self.strategy.init_class_attribute(mapper)
_all_strategies = collections.defaultdict(dict)
@@ -550,12 +581,13 @@ class StrategizedProperty(MapperProperty):
def decorate(dec_cls):
# ensure each subclass of the strategy has its
# own _strategy_keys collection
- if '_strategy_keys' not in dec_cls.__dict__:
+ if "_strategy_keys" not in dec_cls.__dict__:
dec_cls._strategy_keys = []
key = tuple(sorted(kw.items()))
cls._all_strategies[cls][key] = dec_cls
dec_cls._strategy_keys.append(key)
return dec_cls
+
return decorate
@classmethod
@@ -671,8 +703,14 @@ class LoaderStrategy(object):
"""
- __slots__ = 'parent_property', 'is_class_level', 'parent', 'key', \
- 'strategy_key', 'strategy_opts'
+ __slots__ = (
+ "parent_property",
+ "is_class_level",
+ "parent",
+ "key",
+ "strategy_key",
+ "strategy_opts",
+ )
def __init__(self, parent, strategy_key):
self.parent_property = parent
@@ -695,8 +733,9 @@ class LoaderStrategy(object):
"""
- def create_row_processor(self, context, path, loadopt, mapper,
- result, adapter, populators):
+ def create_row_processor(
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
"""Establish row processing functions for a given QueryContext.
This method fulfills the contract specified by
diff --git a/lib/sqlalchemy/orm/loading.py b/lib/sqlalchemy/orm/loading.py
index 0a6f8023a..96eddcb32 100644
--- a/lib/sqlalchemy/orm/loading.py
+++ b/lib/sqlalchemy/orm/loading.py
@@ -37,32 +37,35 @@ def instances(query, cursor, context):
filtered = query._has_mapper_entities
- single_entity = not query._only_return_tuples and \
- len(query._entities) == 1 and \
- query._entities[0].supports_single_entity
+ single_entity = (
+ not query._only_return_tuples
+ and len(query._entities) == 1
+ and query._entities[0].supports_single_entity
+ )
if filtered:
if single_entity:
filter_fn = id
else:
+
def filter_fn(row):
return tuple(
- id(item)
- if ent.use_id_for_hash
- else item
+ id(item) if ent.use_id_for_hash else item
for ent, item in zip(query._entities, row)
)
try:
- (process, labels) = \
- list(zip(*[
- query_entity.row_processor(query,
- context, cursor)
- for query_entity in query._entities
- ]))
+ (process, labels) = list(
+ zip(
+ *[
+ query_entity.row_processor(query, context, cursor)
+ for query_entity in query._entities
+ ]
+ )
+ )
if not single_entity:
- keyed_tuple = util.lightweight_named_tuple('result', labels)
+ keyed_tuple = util.lightweight_named_tuple("result", labels)
while True:
context.partials = {}
@@ -78,11 +81,12 @@ def instances(query, cursor, context):
proc = process[0]
rows = [proc(row) for row in fetch]
else:
- rows = [keyed_tuple([proc(row) for proc in process])
- for row in fetch]
+ rows = [
+ keyed_tuple([proc(row) for proc in process])
+ for row in fetch
+ ]
- for path, post_load in \
- context.post_load_paths.items():
+ for path, post_load in context.post_load_paths.items():
post_load.invoke(context, path)
if filtered:
@@ -113,19 +117,27 @@ def merge_result(querylib, query, iterator, load=True):
single_entity = len(query._entities) == 1
if single_entity:
if isinstance(query._entities[0], querylib._MapperEntity):
- result = [session._merge(
- attributes.instance_state(instance),
- attributes.instance_dict(instance),
- load=load, _recursive={}, _resolve_conflict_map={})
- for instance in iterator]
+ result = [
+ session._merge(
+ attributes.instance_state(instance),
+ attributes.instance_dict(instance),
+ load=load,
+ _recursive={},
+ _resolve_conflict_map={},
+ )
+ for instance in iterator
+ ]
else:
result = list(iterator)
else:
- mapped_entities = [i for i, e in enumerate(query._entities)
- if isinstance(e, querylib._MapperEntity)]
+ mapped_entities = [
+ i
+ for i, e in enumerate(query._entities)
+ if isinstance(e, querylib._MapperEntity)
+ ]
result = []
keys = [ent._label_name for ent in query._entities]
- keyed_tuple = util.lightweight_named_tuple('result', keys)
+ keyed_tuple = util.lightweight_named_tuple("result", keys)
for row in iterator:
newrow = list(row)
for i in mapped_entities:
@@ -133,7 +145,10 @@ def merge_result(querylib, query, iterator, load=True):
newrow[i] = session._merge(
attributes.instance_state(newrow[i]),
attributes.instance_dict(newrow[i]),
- load=load, _recursive={}, _resolve_conflict_map={})
+ load=load,
+ _recursive={},
+ _resolve_conflict_map={},
+ )
result.append(keyed_tuple(newrow))
return iter(result)
@@ -170,9 +185,9 @@ def get_from_identity(session, key, passive):
return None
-def load_on_ident(query, key,
- refresh_state=None, with_for_update=None,
- only_load_props=None):
+def load_on_ident(
+ query, key, refresh_state=None, with_for_update=None, only_load_props=None
+):
"""Load the given identity key from the database."""
if key is not None:
@@ -182,16 +197,23 @@ def load_on_ident(query, key,
ident = identity_token = None
return load_on_pk_identity(
- query, ident, refresh_state=refresh_state,
+ query,
+ ident,
+ refresh_state=refresh_state,
with_for_update=with_for_update,
only_load_props=only_load_props,
- identity_token=identity_token
+ identity_token=identity_token,
)
-def load_on_pk_identity(query, primary_key_identity,
- refresh_state=None, with_for_update=None,
- only_load_props=None, identity_token=None):
+def load_on_pk_identity(
+ query,
+ primary_key_identity,
+ refresh_state=None,
+ with_for_update=None,
+ only_load_props=None,
+ identity_token=None,
+):
"""Load the given primary key identity from the database."""
@@ -209,22 +231,28 @@ def load_on_pk_identity(query, primary_key_identity,
# None present in ident - turn those comparisons
# into "IS NULL"
if None in primary_key_identity:
- nones = set([
- _get_params[col].key for col, value in
- zip(mapper.primary_key, primary_key_identity)
- if value is None
- ])
- _get_clause = sql_util.adapt_criterion_to_null(
- _get_clause, nones)
+ nones = set(
+ [
+ _get_params[col].key
+ for col, value in zip(
+ mapper.primary_key, primary_key_identity
+ )
+ if value is None
+ ]
+ )
+ _get_clause = sql_util.adapt_criterion_to_null(_get_clause, nones)
_get_clause = q._adapt_clause(_get_clause, True, False)
q._criterion = _get_clause
- params = dict([
- (_get_params[primary_key].key, id_val)
- for id_val, primary_key
- in zip(primary_key_identity, mapper.primary_key)
- ])
+ params = dict(
+ [
+ (_get_params[primary_key].key, id_val)
+ for id_val, primary_key in zip(
+ primary_key_identity, mapper.primary_key
+ )
+ ]
+ )
q._params = params
@@ -243,7 +271,8 @@ def load_on_pk_identity(query, primary_key_identity,
version_check=version_check,
only_load_props=only_load_props,
refresh_state=refresh_state,
- identity_token=identity_token)
+ identity_token=identity_token,
+ )
q._order_by = None
try:
@@ -253,27 +282,31 @@ def load_on_pk_identity(query, primary_key_identity,
def _setup_entity_query(
- context, mapper, query_entity,
- path, adapter, column_collection,
- with_polymorphic=None, only_load_props=None,
- polymorphic_discriminator=None, **kw):
+ context,
+ mapper,
+ query_entity,
+ path,
+ adapter,
+ column_collection,
+ with_polymorphic=None,
+ only_load_props=None,
+ polymorphic_discriminator=None,
+ **kw
+):
if with_polymorphic:
poly_properties = mapper._iterate_polymorphic_properties(
- with_polymorphic)
+ with_polymorphic
+ )
else:
poly_properties = mapper._polymorphic_properties
quick_populators = {}
- path.set(
- context.attributes,
- "memoized_setups",
- quick_populators)
+ path.set(context.attributes, "memoized_setups", quick_populators)
for value in poly_properties:
- if only_load_props and \
- value.key not in only_load_props:
+ if only_load_props and value.key not in only_load_props:
continue
value.setup(
context,
@@ -286,9 +319,10 @@ def _setup_entity_query(
**kw
)
- if polymorphic_discriminator is not None and \
- polymorphic_discriminator \
- is not mapper.polymorphic_on:
+ if (
+ polymorphic_discriminator is not None
+ and polymorphic_discriminator is not mapper.polymorphic_on
+ ):
if adapter:
pd = adapter.columns[polymorphic_discriminator]
@@ -298,10 +332,16 @@ def _setup_entity_query(
def _instance_processor(
- mapper, context, result, path, adapter,
- only_load_props=None, refresh_state=None,
- polymorphic_discriminator=None,
- _polymorphic_from=None):
+ mapper,
+ context,
+ result,
+ path,
+ adapter,
+ only_load_props=None,
+ refresh_state=None,
+ polymorphic_discriminator=None,
+ _polymorphic_from=None,
+):
"""Produce a mapper level row processor callable
which processes rows into mapped instances."""
@@ -322,11 +362,11 @@ def _instance_processor(
props = mapper._prop_set
if only_load_props is not None:
- props = props.intersection(
- mapper._props[k] for k in only_load_props)
+ props = props.intersection(mapper._props[k] for k in only_load_props)
quick_populators = path.get(
- context.attributes, "memoized_setups", _none_set)
+ context.attributes, "memoized_setups", _none_set
+ )
for prop in props:
if prop in quick_populators:
@@ -334,7 +374,8 @@ def _instance_processor(
col = quick_populators[prop]
if col is _DEFER_FOR_STATE:
populators["new"].append(
- (prop.key, prop._deferred_column_loader))
+ (prop.key, prop._deferred_column_loader)
+ )
elif col is _SET_DEFERRED_EXPIRED:
# note that in this path, we are no longer
# searching in the result to see if the column might
@@ -366,14 +407,19 @@ def _instance_processor(
# will iterate through all of its columns
# to see if one fits
prop.create_row_processor(
- context, path, mapper, result, adapter, populators)
+ context, path, mapper, result, adapter, populators
+ )
else:
prop.create_row_processor(
- context, path, mapper, result, adapter, populators)
+ context, path, mapper, result, adapter, populators
+ )
propagate_options = context.propagate_options
- load_path = context.query._current_path + path \
- if context.query._current_path.path else path
+ load_path = (
+ context.query._current_path + path
+ if context.query._current_path.path
+ else path
+ )
session_identity_map = context.session.identity_map
@@ -391,18 +437,18 @@ def _instance_processor(
identity_token = context.identity_token
if not refresh_state and _polymorphic_from is not None:
- key = ('loader', path.path)
- if (
- key in context.attributes and
- context.attributes[key].strategy ==
- (('selectinload_polymorphic', True), )
+ key = ("loader", path.path)
+ if key in context.attributes and context.attributes[key].strategy == (
+ ("selectinload_polymorphic", True),
):
selectin_load_via = mapper._should_selectin_load(
- context.attributes[key].local_opts['entities'],
- _polymorphic_from)
+ context.attributes[key].local_opts["entities"],
+ _polymorphic_from,
+ )
else:
selectin_load_via = mapper._should_selectin_load(
- None, _polymorphic_from)
+ None, _polymorphic_from
+ )
if selectin_load_via and selectin_load_via is not _polymorphic_from:
# only_load_props goes w/ refresh_state only, and in a refresh
@@ -413,9 +459,13 @@ def _instance_processor(
callable_ = _load_subclass_via_in(context, path, selectin_load_via)
PostLoad.callable_for_path(
- context, load_path, selectin_load_via.mapper,
+ context,
+ load_path,
+ selectin_load_via.mapper,
+ selectin_load_via,
+ callable_,
selectin_load_via,
- callable_, selectin_load_via)
+ )
post_load = PostLoad.for_context(context, load_path, only_load_props)
@@ -425,8 +475,9 @@ def _instance_processor(
# super-rare condition; a refresh is being called
# on a non-instance-key instance; this is meant to only
# occur within a flush()
- refresh_identity_key = \
- mapper._identity_key_from_state(refresh_state)
+ refresh_identity_key = mapper._identity_key_from_state(
+ refresh_state
+ )
else:
refresh_identity_key = None
@@ -452,7 +503,7 @@ def _instance_processor(
identitykey = (
identity_class,
tuple([row[column] for column in pk_cols]),
- identity_token
+ identity_token,
)
instance = session_identity_map.get(identitykey)
@@ -507,8 +558,16 @@ def _instance_processor(
state.load_path = load_path
_populate_full(
- context, row, state, dict_, isnew, load_path,
- loaded_instance, populate_existing, populators)
+ context,
+ row,
+ state,
+ dict_,
+ isnew,
+ load_path,
+ loaded_instance,
+ populate_existing,
+ populators,
+ )
if isnew:
if loaded_instance:
@@ -518,7 +577,8 @@ def _instance_processor(
loaded_as_persistent(context.session, state.obj())
elif refresh_evt:
state.manager.dispatch.refresh(
- state, context, only_load_props)
+ state, context, only_load_props
+ )
if populate_existing or state.modified:
if refresh_state and only_load_props:
@@ -542,13 +602,19 @@ def _instance_processor(
# and add to the "context.partials" collection.
to_load = _populate_partial(
- context, row, state, dict_, isnew, load_path,
- unloaded, populators)
+ context,
+ row,
+ state,
+ dict_,
+ isnew,
+ load_path,
+ unloaded,
+ populators,
+ )
if isnew:
if refresh_evt:
- state.manager.dispatch.refresh(
- state, context, to_load)
+ state.manager.dispatch.refresh(state, context, to_load)
state._commit(dict_, to_load)
@@ -561,8 +627,14 @@ def _instance_processor(
# if we are doing polymorphic, dispatch to a different _instance()
# method specific to the subclass mapper
_instance = _decorate_polymorphic_switch(
- _instance, context, mapper, result, path,
- polymorphic_discriminator, adapter)
+ _instance,
+ context,
+ mapper,
+ result,
+ path,
+ polymorphic_discriminator,
+ adapter,
+ )
return _instance
@@ -581,14 +653,13 @@ def _load_subclass_via_in(context, path, entity):
orig_query = context.query
q2 = q._with_lazyload_options(
- (enable_opt, ) + orig_query._with_options + (disable_opt, ),
- path.parent, cache_path=path
+ (enable_opt,) + orig_query._with_options + (disable_opt,),
+ path.parent,
+ cache_path=path,
)
if orig_query._populate_existing:
- q2.add_criteria(
- lambda q: q.populate_existing()
- )
+ q2.add_criteria(lambda q: q.populate_existing())
q2(context.session).params(
primary_keys=[
@@ -601,8 +672,16 @@ def _load_subclass_via_in(context, path, entity):
def _populate_full(
- context, row, state, dict_, isnew, load_path,
- loaded_instance, populate_existing, populators):
+ context,
+ row,
+ state,
+ dict_,
+ isnew,
+ load_path,
+ loaded_instance,
+ populate_existing,
+ populators,
+):
if isnew:
# first time we are seeing a row with this identity.
state.runid = context.runid
@@ -650,8 +729,8 @@ def _populate_full(
def _populate_partial(
- context, row, state, dict_, isnew, load_path,
- unloaded, populators):
+ context, row, state, dict_, isnew, load_path, unloaded, populators
+):
if not isnew:
to_load = context.partials[state]
@@ -693,19 +772,32 @@ def _validate_version_id(mapper, state, dict_, row, adapter):
if adapter:
version_id_col = adapter.columns[version_id_col]
- if mapper._get_state_attr_by_column(
- state, dict_, mapper.version_id_col) != row[version_id_col]:
+ if (
+ mapper._get_state_attr_by_column(state, dict_, mapper.version_id_col)
+ != row[version_id_col]
+ ):
raise orm_exc.StaleDataError(
"Instance '%s' has version id '%s' which "
"does not match database-loaded version id '%s'."
- % (state_str(state), mapper._get_state_attr_by_column(
- state, dict_, mapper.version_id_col),
- row[version_id_col]))
+ % (
+ state_str(state),
+ mapper._get_state_attr_by_column(
+ state, dict_, mapper.version_id_col
+ ),
+ row[version_id_col],
+ )
+ )
def _decorate_polymorphic_switch(
- instance_fn, context, mapper, result, path,
- polymorphic_discriminator, adapter):
+ instance_fn,
+ context,
+ mapper,
+ result,
+ path,
+ polymorphic_discriminator,
+ adapter,
+):
if polymorphic_discriminator is not None:
polymorphic_on = polymorphic_discriminator
else:
@@ -721,19 +813,22 @@ def _decorate_polymorphic_switch(
sub_mapper = mapper.polymorphic_map[discriminator]
except KeyError:
raise AssertionError(
- "No such polymorphic_identity %r is defined" %
- discriminator)
+ "No such polymorphic_identity %r is defined" % discriminator
+ )
else:
if sub_mapper is mapper:
return None
return _instance_processor(
- sub_mapper, context, result,
- path, adapter, _polymorphic_from=mapper)
+ sub_mapper,
+ context,
+ result,
+ path,
+ adapter,
+ _polymorphic_from=mapper,
+ )
- polymorphic_instances = util.PopulateDict(
- configure_subclass_mapper
- )
+ polymorphic_instances = util.PopulateDict(configure_subclass_mapper)
def polymorphic_instance(row):
discriminator = row[polymorphic_on]
@@ -742,6 +837,7 @@ def _decorate_polymorphic_switch(
if _instance:
return _instance(row)
return instance_fn(row)
+
return polymorphic_instance
@@ -749,7 +845,8 @@ class PostLoad(object):
"""Track loaders and states for "post load" operations.
"""
- __slots__ = 'loaders', 'states', 'load_keys'
+
+ __slots__ = "loaders", "states", "load_keys"
def __init__(self):
self.loaders = {}
@@ -770,8 +867,7 @@ class PostLoad(object):
for token, limit_to_mapper, loader, arg, kw in self.loaders.values():
states = [
(state, overwrite)
- for state, overwrite
- in self.states.items()
+ for state, overwrite in self.states.items()
if state.manager.mapper.isa(limit_to_mapper)
]
if states:
@@ -787,13 +883,15 @@ class PostLoad(object):
@classmethod
def path_exists(self, context, path, key):
- return path.path in context.post_load_paths and \
- key in context.post_load_paths[path.path].loaders
+ return (
+ path.path in context.post_load_paths
+ and key in context.post_load_paths[path.path].loaders
+ )
@classmethod
def callable_for_path(
- cls, context, path, limit_to_mapper, token,
- loader_callable, *arg, **kw):
+ cls, context, path, limit_to_mapper, token, loader_callable, *arg, **kw
+ ):
if path.path in context.post_load_paths:
pl = context.post_load_paths[path.path]
else:
@@ -809,8 +907,8 @@ def load_scalar_attributes(mapper, state, attribute_names):
if not session:
raise orm_exc.DetachedInstanceError(
"Instance %s is not bound to a Session; "
- "attribute refresh operation cannot proceed" %
- (state_str(state)))
+ "attribute refresh operation cannot proceed" % (state_str(state))
+ )
has_key = bool(state.key)
@@ -833,13 +931,12 @@ def load_scalar_attributes(mapper, state, attribute_names):
statement = mapper._optimized_get_statement(state, attribute_names)
if statement is not None:
result = load_on_ident(
- session.query(mapper).
- options(
- strategy_options.Load(mapper).undefer("*")
- ).from_statement(statement),
+ session.query(mapper)
+ .options(strategy_options.Load(mapper).undefer("*"))
+ .from_statement(statement),
None,
only_load_props=attribute_names,
- refresh_state=state
+ refresh_state=state,
)
if result is False:
@@ -850,30 +947,34 @@ def load_scalar_attributes(mapper, state, attribute_names):
# 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]
+ 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))
+ "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):
+ if (
+ _none_set.issubset(identity_key) and not mapper.allow_partial_pks
+ ) or _none_set.issuperset(identity_key):
util.warn_limited(
"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))
+ state_str(state),
+ )
return
result = load_on_ident(
session.query(mapper),
identity_key,
refresh_state=state,
- only_load_props=attribute_names)
+ only_load_props=attribute_names,
+ )
# if instance is pending, a refresh operation
# may not complete (even if PK attributes are assigned)
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index fa731f729..ea8890788 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -26,12 +26,21 @@ from ..sql import expression, visitors, operators, util as sql_util
from . import instrumentation, attributes, exc as orm_exc, loading
from . import properties
from . import util as orm_util
-from .interfaces import MapperProperty, InspectionAttr, _MappedAttribute, \
- EXT_SKIP
-
-
-from .base import _class_to_mapper, _state_mapper, class_mapper, \
- state_str, _INSTRUMENTOR
+from .interfaces import (
+ MapperProperty,
+ InspectionAttr,
+ _MappedAttribute,
+ EXT_SKIP,
+)
+
+
+from .base import (
+ _class_to_mapper,
+ _state_mapper,
+ class_mapper,
+ state_str,
+ _INSTRUMENTOR,
+)
from .path_registry import PathRegistry
import sys
@@ -46,7 +55,7 @@ _memoized_configured_property = util.group_expirable_memoized_property()
# a constant returned by _get_attr_by_column to indicate
# this mapper is not handling an attribute for a particular
# column
-NO_ATTRIBUTE = util.symbol('NO_ATTRIBUTE')
+NO_ATTRIBUTE = util.symbol("NO_ATTRIBUTE")
# lock used to synchronize the "mapper configure" step
_CONFIGURE_MUTEX = util.threading.RLock()
@@ -90,38 +99,39 @@ class Mapper(InspectionAttr):
_new_mappers = False
_dispose_called = False
- def __init__(self,
- class_,
- local_table=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,
- concrete=False,
- with_polymorphic=None,
- polymorphic_load=None,
- allow_partial_pks=True,
- batch=True,
- column_prefix=None,
- include_properties=None,
- exclude_properties=None,
- passive_updates=True,
- passive_deletes=False,
- confirm_deleted_rows=True,
- eager_defaults=False,
- legacy_is_orphan=False,
- _compiled_cache_size=100,
- ):
+ def __init__(
+ self,
+ class_,
+ local_table=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,
+ concrete=False,
+ with_polymorphic=None,
+ polymorphic_load=None,
+ allow_partial_pks=True,
+ batch=True,
+ column_prefix=None,
+ include_properties=None,
+ exclude_properties=None,
+ passive_updates=True,
+ passive_deletes=False,
+ confirm_deleted_rows=True,
+ eager_defaults=False,
+ legacy_is_orphan=False,
+ _compiled_cache_size=100,
+ ):
r"""Return a new :class:`~.Mapper` object.
This function is typically used behind the scenes
@@ -588,7 +598,7 @@ class Mapper(InspectionAttr):
"""
- self.class_ = util.assert_arg_type(class_, type, 'class_')
+ self.class_ = util.assert_arg_type(class_, type, "class_")
self.class_manager = None
@@ -600,7 +610,8 @@ class Mapper(InspectionAttr):
util.warn_deprecated(
"Mapper.order_by is deprecated."
"Use Query.order_by() in order to affect the ordering of ORM "
- "result sets.")
+ "result sets."
+ )
else:
self.order_by = order_by
@@ -631,7 +642,8 @@ class Mapper(InspectionAttr):
self.eager_defaults = eager_defaults
self.column_prefix = column_prefix
self.polymorphic_on = expression._clause_element_as_expr(
- polymorphic_on)
+ polymorphic_on
+ )
self._dependency_processors = []
self.validators = util.immutabledict()
self.passive_updates = passive_updates
@@ -974,14 +986,16 @@ class Mapper(InspectionAttr):
self.inherits = class_mapper(self.inherits, configure=False)
if not issubclass(self.class_, self.inherits.class_):
raise sa_exc.ArgumentError(
- "Class '%s' does not inherit from '%s'" %
- (self.class_.__name__, self.inherits.class_.__name__))
+ "Class '%s' does not inherit from '%s'"
+ % (self.class_.__name__, self.inherits.class_.__name__)
+ )
if self.non_primary != self.inherits.non_primary:
np = not self.non_primary and "primary" or "non-primary"
raise sa_exc.ArgumentError(
"Inheritance of %s mapper for class '%s' is "
- "only allowed from a %s mapper" %
- (np, self.class_.__name__, np))
+ "only allowed from a %s mapper"
+ % (np, self.class_.__name__, np)
+ )
# inherit_condition is optional.
if self.local_table is None:
self.local_table = self.inherits.local_table
@@ -1000,18 +1014,19 @@ class Mapper(InspectionAttr):
# full table which could pull in other stuff we don't
# want (allows test/inheritance.InheritTest4 to pass)
self.inherit_condition = sql_util.join_condition(
- self.inherits.local_table,
- self.local_table)
+ self.inherits.local_table, self.local_table
+ )
self.mapped_table = sql.join(
self.inherits.mapped_table,
self.local_table,
- self.inherit_condition)
+ self.inherit_condition,
+ )
fks = util.to_set(self.inherit_foreign_keys)
- self._inherits_equated_pairs = \
- sql_util.criterion_as_pairs(
- self.mapped_table.onclause,
- consider_as_foreign_keys=fks)
+ self._inherits_equated_pairs = sql_util.criterion_as_pairs(
+ self.mapped_table.onclause,
+ consider_as_foreign_keys=fks,
+ )
else:
self.mapped_table = self.local_table
@@ -1023,21 +1038,27 @@ class Mapper(InspectionAttr):
if self.version_id_col is None:
self.version_id_col = self.inherits.version_id_col
self.version_id_generator = self.inherits.version_id_generator
- elif self.inherits.version_id_col is not None and \
- self.version_id_col is not self.inherits.version_id_col:
+ elif (
+ self.inherits.version_id_col is not None
+ and self.version_id_col is not self.inherits.version_id_col
+ ):
util.warn(
"Inheriting version_id_col '%s' does not match inherited "
"version_id_col '%s' and will not automatically populate "
"the inherited versioning column. "
"version_id_col should only be specified on "
- "the base-most mapper that includes versioning." %
- (self.version_id_col.description,
- self.inherits.version_id_col.description)
+ "the base-most mapper that includes versioning."
+ % (
+ self.version_id_col.description,
+ self.inherits.version_id_col.description,
+ )
)
- if self.order_by is False and \
- not self.concrete and \
- self.inherits.order_by is not False:
+ if (
+ self.order_by is False
+ and not self.concrete
+ and self.inherits.order_by is not False
+ ):
self.order_by = self.inherits.order_by
self.polymorphic_map = self.inherits.polymorphic_map
@@ -1045,8 +1066,9 @@ class Mapper(InspectionAttr):
self.inherits._inheriting_mappers.append(self)
self.base_mapper = self.inherits.base_mapper
self.passive_updates = self.inherits.passive_updates
- self.passive_deletes = self.inherits.passive_deletes or \
- self.passive_deletes
+ self.passive_deletes = (
+ self.inherits.passive_deletes or self.passive_deletes
+ )
self._all_tables = self.inherits._all_tables
if self.polymorphic_identity is not None:
@@ -1054,25 +1076,30 @@ class Mapper(InspectionAttr):
util.warn(
"Reassigning polymorphic association for identity %r "
"from %r to %r: Check for duplicate use of %r as "
- "value for polymorphic_identity." %
- (self.polymorphic_identity,
- self.polymorphic_map[self.polymorphic_identity],
- self, self.polymorphic_identity)
+ "value for polymorphic_identity."
+ % (
+ self.polymorphic_identity,
+ self.polymorphic_map[self.polymorphic_identity],
+ self,
+ self.polymorphic_identity,
+ )
)
self.polymorphic_map[self.polymorphic_identity] = self
if self.polymorphic_load and self.concrete:
raise exc.ArgumentError(
"polymorphic_load is not currently supported "
- "with concrete table inheritance")
- if self.polymorphic_load == 'inline':
+ "with concrete table inheritance"
+ )
+ if self.polymorphic_load == "inline":
self.inherits._add_with_polymorphic_subclass(self)
- elif self.polymorphic_load == 'selectin':
+ elif self.polymorphic_load == "selectin":
pass
elif self.polymorphic_load is not None:
raise sa_exc.ArgumentError(
- "unknown argument for polymorphic_load: %r" %
- self.polymorphic_load)
+ "unknown argument for polymorphic_load: %r"
+ % self.polymorphic_load
+ )
else:
self._all_tables = set()
@@ -1084,15 +1111,16 @@ class Mapper(InspectionAttr):
if self.mapped_table is None:
raise sa_exc.ArgumentError(
- "Mapper '%s' does not have a mapped_table specified."
- % self)
+ "Mapper '%s' does not have a mapped_table specified." % self
+ )
def _set_with_polymorphic(self, with_polymorphic):
- if with_polymorphic == '*':
- self.with_polymorphic = ('*', None)
+ if with_polymorphic == "*":
+ self.with_polymorphic = ("*", None)
elif isinstance(with_polymorphic, (tuple, list)):
if isinstance(
- with_polymorphic[0], util.string_types + (tuple, list)):
+ with_polymorphic[0], util.string_types + (tuple, list)
+ ):
self.with_polymorphic = with_polymorphic
else:
self.with_polymorphic = (with_polymorphic, None)
@@ -1109,11 +1137,13 @@ class Mapper(InspectionAttr):
"SELECT from a subquery that does not have an alias."
)
- if self.with_polymorphic and \
- isinstance(self.with_polymorphic[1],
- expression.SelectBase):
- self.with_polymorphic = (self.with_polymorphic[0],
- self.with_polymorphic[1].alias())
+ if self.with_polymorphic and isinstance(
+ self.with_polymorphic[1], expression.SelectBase
+ ):
+ self.with_polymorphic = (
+ self.with_polymorphic[0],
+ self.with_polymorphic[1].alias(),
+ )
if self.configured:
self._expire_memoizations()
@@ -1122,12 +1152,9 @@ class Mapper(InspectionAttr):
subcl = mapper.class_
if self.with_polymorphic is None:
self._set_with_polymorphic((subcl,))
- elif self.with_polymorphic[0] != '*':
+ elif self.with_polymorphic[0] != "*":
self._set_with_polymorphic(
- (
- self.with_polymorphic[0] + (subcl, ),
- self.with_polymorphic[1]
- )
+ (self.with_polymorphic[0] + (subcl,), self.with_polymorphic[1])
)
def _set_concrete_base(self, mapper):
@@ -1152,9 +1179,9 @@ class Mapper(InspectionAttr):
self._all_tables = self.inherits._all_tables
for key, prop in mapper._props.items():
- if key not in self._props and \
- not self._should_exclude(key, key, local=False,
- column=None):
+ if key not in self._props and not self._should_exclude(
+ key, key, local=False, column=None
+ ):
self._adapt_inherited_property(key, prop, False)
def _set_polymorphic_on(self, polymorphic_on):
@@ -1166,8 +1193,13 @@ class Mapper(InspectionAttr):
if self.inherits:
self.dispatch._update(self.inherits.dispatch)
super_extensions = set(
- chain(*[m._deprecated_extensions
- for m in self.inherits.iterate_to_root()]))
+ chain(
+ *[
+ m._deprecated_extensions
+ for m in self.inherits.iterate_to_root()
+ ]
+ )
+ )
else:
super_extensions = set()
@@ -1178,8 +1210,13 @@ class Mapper(InspectionAttr):
def _configure_listeners(self):
if self.inherits:
super_extensions = set(
- chain(*[m._deprecated_extensions
- for m in self.inherits.iterate_to_root()]))
+ chain(
+ *[
+ m._deprecated_extensions
+ for m in self.inherits.iterate_to_root()
+ ]
+ )
+ )
else:
super_extensions = set()
@@ -1206,7 +1243,8 @@ class Mapper(InspectionAttr):
raise sa_exc.InvalidRequestError(
"Class %s has no primary mapper configured. Configure "
"a primary mapper first before setting up a non primary "
- "Mapper." % self.class_)
+ "Mapper." % self.class_
+ )
self.class_manager = manager
self._identity_class = manager.mapper._identity_class
_mapper_registry[self] = True
@@ -1219,12 +1257,13 @@ class Mapper(InspectionAttr):
"Class '%s' already has a primary mapper defined. "
"Use non_primary=True to "
"create a non primary Mapper. clear_mappers() will "
- "remove *all* current mappers from all classes." %
- self.class_)
+ "remove *all* current mappers from all classes."
+ % self.class_
+ )
# else:
- # a ClassManager may already exist as
- # ClassManager.instrument_attribute() creates
- # new managers for each subclass if they don't yet exist.
+ # a ClassManager may already exist as
+ # ClassManager.instrument_attribute() creates
+ # new managers for each subclass if they don't yet exist.
_mapper_registry[self] = True
@@ -1239,33 +1278,35 @@ class Mapper(InspectionAttr):
manager.mapper = self
manager.deferred_scalar_loader = util.partial(
- loading.load_scalar_attributes, self)
+ loading.load_scalar_attributes, self
+ )
# The remaining members can be added by any mapper,
# e_name None or not.
if manager.info.get(_INSTRUMENTOR, False):
return
- event.listen(manager, 'first_init', _event_on_first_init, raw=True)
- event.listen(manager, 'init', _event_on_init, raw=True)
+ event.listen(manager, "first_init", _event_on_first_init, raw=True)
+ event.listen(manager, "init", _event_on_init, raw=True)
for key, method in util.iterate_attributes(self.class_):
- if key == '__init__' and hasattr(method, '_sa_original_init'):
+ if key == "__init__" and hasattr(method, "_sa_original_init"):
method = method._sa_original_init
if isinstance(method, types.MethodType):
method = method.im_func
if isinstance(method, types.FunctionType):
- if hasattr(method, '__sa_reconstructor__'):
+ if hasattr(method, "__sa_reconstructor__"):
self._reconstructor = method
- event.listen(manager, 'load', _event_on_load, raw=True)
- elif hasattr(method, '__sa_validators__'):
+ event.listen(manager, "load", _event_on_load, raw=True)
+ elif hasattr(method, "__sa_validators__"):
validation_opts = method.__sa_validation_opts__
for name in method.__sa_validators__:
if name in self.validators:
raise sa_exc.InvalidRequestError(
"A validation function for mapped "
- "attribute %r on mapper %s already exists." %
- (name, self))
+ "attribute %r on mapper %s already exists."
+ % (name, self)
+ )
self.validators = self.validators.union(
{name: (method, validation_opts)}
)
@@ -1283,13 +1324,15 @@ class Mapper(InspectionAttr):
self.configured = True
self._dispose_called = True
- if hasattr(self, '_configure_failed'):
+ if hasattr(self, "_configure_failed"):
del self._configure_failed
- if not self.non_primary and \
- self.class_manager is not None and \
- self.class_manager.is_mapped and \
- self.class_manager.mapper is self:
+ if (
+ not self.non_primary
+ and self.class_manager is not None
+ and self.class_manager.is_mapped
+ and self.class_manager.mapper is self
+ ):
instrumentation.unregister_class(self.class_)
def _configure_pks(self):
@@ -1298,9 +1341,9 @@ class Mapper(InspectionAttr):
self._pks_by_table = {}
self._cols_by_table = {}
- all_cols = util.column_set(chain(*[
- col.proxy_set for col in
- self._columntoproperty]))
+ all_cols = util.column_set(
+ chain(*[col.proxy_set for col in self._columntoproperty])
+ )
pk_cols = util.column_set(c for c in all_cols if c.primary_key)
@@ -1311,12 +1354,12 @@ class Mapper(InspectionAttr):
if t.primary_key and pk_cols.issuperset(t.primary_key):
# ordering is important since it determines the ordering of
# mapper.primary_key (and therefore query.get())
- self._pks_by_table[t] = \
- util.ordered_column_set(t.primary_key).\
- intersection(pk_cols)
- self._cols_by_table[t] = \
- util.ordered_column_set(t.c).\
- intersection(all_cols)
+ self._pks_by_table[t] = util.ordered_column_set(
+ t.primary_key
+ ).intersection(pk_cols)
+ self._cols_by_table[t] = util.ordered_column_set(t.c).intersection(
+ all_cols
+ )
# if explicit PK argument sent, add those columns to the
# primary key mappings
@@ -1327,22 +1370,30 @@ class Mapper(InspectionAttr):
self._pks_by_table[k.table].add(k)
# otherwise, see that we got a full PK for the mapped table
- elif self.mapped_table not in self._pks_by_table or \
- len(self._pks_by_table[self.mapped_table]) == 0:
+ elif (
+ self.mapped_table not in self._pks_by_table
+ or len(self._pks_by_table[self.mapped_table]) == 0
+ ):
raise sa_exc.ArgumentError(
"Mapper %s could not assemble any primary "
- "key columns for mapped table '%s'" %
- (self, self.mapped_table.description))
- elif self.local_table not in self._pks_by_table and \
- isinstance(self.local_table, schema.Table):
- util.warn("Could not assemble any primary "
- "keys for locally mapped table '%s' - "
- "no rows will be persisted in this Table."
- % self.local_table.description)
-
- if self.inherits and \
- not self.concrete and \
- not self._primary_key_argument:
+ "key columns for mapped table '%s'"
+ % (self, self.mapped_table.description)
+ )
+ elif self.local_table not in self._pks_by_table and isinstance(
+ self.local_table, schema.Table
+ ):
+ util.warn(
+ "Could not assemble any primary "
+ "keys for locally mapped table '%s' - "
+ "no rows will be persisted in this Table."
+ % self.local_table.description
+ )
+
+ if (
+ self.inherits
+ and not self.concrete
+ and not self._primary_key_argument
+ ):
# if inheriting, the "primary key" for this mapper is
# that of the inheriting (unless concrete or explicit)
self.primary_key = self.inherits.primary_key
@@ -1351,19 +1402,24 @@ class Mapper(InspectionAttr):
# reduce to the minimal set of columns
if self._primary_key_argument:
primary_key = sql_util.reduce_columns(
- [self.mapped_table.corresponding_column(c) for c in
- self._primary_key_argument],
- ignore_nonexistent_tables=True)
+ [
+ self.mapped_table.corresponding_column(c)
+ for c in self._primary_key_argument
+ ],
+ ignore_nonexistent_tables=True,
+ )
else:
primary_key = sql_util.reduce_columns(
self._pks_by_table[self.mapped_table],
- ignore_nonexistent_tables=True)
+ ignore_nonexistent_tables=True,
+ )
if len(primary_key) == 0:
raise sa_exc.ArgumentError(
"Mapper %s could not assemble any primary "
- "key columns for mapped table '%s'" %
- (self, self.mapped_table.description))
+ "key columns for mapped table '%s'"
+ % (self, self.mapped_table.description)
+ )
self.primary_key = tuple(primary_key)
self._log("Identified primary key columns: %s", primary_key)
@@ -1373,9 +1429,12 @@ class Mapper(InspectionAttr):
self._readonly_props = set(
self._columntoproperty[col]
for col in self._columntoproperty
- if self._columntoproperty[col] not in self._identity_key_props and
- (not hasattr(col, 'table') or
- col.table not in self._cols_by_table))
+ if self._columntoproperty[col] not in self._identity_key_props
+ and (
+ not hasattr(col, "table")
+ or col.table not in self._cols_by_table
+ )
+ )
def _configure_properties(self):
# Column and other ClauseElement objects which are mapped
@@ -1397,9 +1456,9 @@ class Mapper(InspectionAttr):
# pull properties from the inherited mapper if any.
if self.inherits:
for key, prop in self.inherits._props.items():
- if key not in self._props and \
- not self._should_exclude(key, key, local=False,
- column=None):
+ if key not in self._props and not self._should_exclude(
+ key, key, local=False, column=None
+ ):
self._adapt_inherited_property(key, prop, False)
# create properties for each column in the mapped table,
@@ -1408,12 +1467,13 @@ class Mapper(InspectionAttr):
if column in self._columntoproperty:
continue
- column_key = (self.column_prefix or '') + column.key
+ column_key = (self.column_prefix or "") + column.key
if self._should_exclude(
- column.key, column_key,
+ column.key,
+ column_key,
local=self.local_table.c.contains_column(column),
- column=column
+ column=column,
):
continue
@@ -1423,10 +1483,9 @@ class Mapper(InspectionAttr):
if column in mapper._columntoproperty:
column_key = mapper._columntoproperty[column].key
- self._configure_property(column_key,
- column,
- init=False,
- setparent=True)
+ self._configure_property(
+ column_key, column, init=False, setparent=True
+ )
def _configure_polymorphic_setter(self, init=False):
"""Configure an attribute on the mapper representing the
@@ -1453,7 +1512,8 @@ class Mapper(InspectionAttr):
raise sa_exc.ArgumentError(
"Can't determine polymorphic_on "
"value '%s' - no attribute is "
- "mapped to this name." % self.polymorphic_on)
+ "mapped to this name." % self.polymorphic_on
+ )
if self.polymorphic_on in self._columntoproperty:
# polymorphic_on is a column that is already mapped
@@ -1462,12 +1522,14 @@ class Mapper(InspectionAttr):
elif isinstance(self.polymorphic_on, MapperProperty):
# polymorphic_on is directly a MapperProperty,
# ensure it's a ColumnProperty
- if not isinstance(self.polymorphic_on,
- properties.ColumnProperty):
+ if not isinstance(
+ self.polymorphic_on, properties.ColumnProperty
+ ):
raise sa_exc.ArgumentError(
"Only direct column-mapped "
"property or SQL expression "
- "can be passed for polymorphic_on")
+ "can be passed for polymorphic_on"
+ )
prop = self.polymorphic_on
elif not expression._is_column(self.polymorphic_on):
# polymorphic_on is not a Column and not a ColumnProperty;
@@ -1484,7 +1546,8 @@ class Mapper(InspectionAttr):
# 2. a totally standalone SQL expression which we'd
# hope is compatible with this mapper's mapped_table
col = self.mapped_table.corresponding_column(
- self.polymorphic_on)
+ self.polymorphic_on
+ )
if col is None:
# polymorphic_on doesn't derive from any
# column/expression isn't present in the mapped
@@ -1500,14 +1563,16 @@ class Mapper(InspectionAttr):
instrument = False
col = self.polymorphic_on
if isinstance(col, schema.Column) and (
- self.with_polymorphic is None or
- self.with_polymorphic[1].
- corresponding_column(col) is None):
+ self.with_polymorphic is None
+ or self.with_polymorphic[1].corresponding_column(col)
+ is None
+ ):
raise sa_exc.InvalidRequestError(
"Could not map polymorphic_on column "
"'%s' to the mapped table - polymorphic "
"loads will not function properly"
- % col.description)
+ % col.description
+ )
else:
# column/expression that polymorphic_on derives from
# is present in our mapped table
@@ -1518,16 +1583,15 @@ class Mapper(InspectionAttr):
# polymorphic_union.
# we'll make a separate ColumnProperty for it.
instrument = True
- key = getattr(col, 'key', None)
+ key = getattr(col, "key", None)
if key:
if self._should_exclude(col.key, col.key, False, col):
raise sa_exc.InvalidRequestError(
"Cannot exclude or override the "
- "discriminator column %r" %
- col.key)
+ "discriminator column %r" % col.key
+ )
else:
- self.polymorphic_on = col = \
- col.label("_sa_polymorphic_on")
+ self.polymorphic_on = col = col.label("_sa_polymorphic_on")
key = col.key
prop = properties.ColumnProperty(col, _instrument=instrument)
@@ -1551,43 +1615,51 @@ class Mapper(InspectionAttr):
if self.mapped_table is mapper.mapped_table:
self.polymorphic_on = mapper.polymorphic_on
else:
- self.polymorphic_on = \
- self.mapped_table.corresponding_column(
- mapper.polymorphic_on)
+ self.polymorphic_on = self.mapped_table.corresponding_column(
+ mapper.polymorphic_on
+ )
# we can use the parent mapper's _set_polymorphic_identity
# directly; it ensures the polymorphic_identity of the
# instance's mapper is used so is portable to subclasses.
if self.polymorphic_on is not None:
- self._set_polymorphic_identity = \
+ self._set_polymorphic_identity = (
mapper._set_polymorphic_identity
- self._validate_polymorphic_identity = \
+ )
+ self._validate_polymorphic_identity = (
mapper._validate_polymorphic_identity
+ )
else:
self._set_polymorphic_identity = None
return
if setter:
+
def _set_polymorphic_identity(state):
dict_ = state.dict
state.get_impl(polymorphic_key).set(
- state, dict_,
+ state,
+ dict_,
state.manager.mapper.polymorphic_identity,
- None)
+ None,
+ )
def _validate_polymorphic_identity(mapper, state, dict_):
- if polymorphic_key in dict_ and \
- dict_[polymorphic_key] not in \
- mapper._acceptable_polymorphic_identities:
+ if (
+ polymorphic_key in dict_
+ and dict_[polymorphic_key]
+ not in mapper._acceptable_polymorphic_identities
+ ):
util.warn_limited(
"Flushing object %s with "
"incompatible polymorphic identity %r; the "
"object may not refresh and/or load correctly",
- (state_str(state), dict_[polymorphic_key])
+ (state_str(state), dict_[polymorphic_key]),
)
self._set_polymorphic_identity = _set_polymorphic_identity
- self._validate_polymorphic_identity = \
+ self._validate_polymorphic_identity = (
_validate_polymorphic_identity
+ )
else:
self._set_polymorphic_identity = None
@@ -1628,16 +1700,20 @@ class Mapper(InspectionAttr):
# mapper and we don't map this. don't trip user-defined
# descriptors that might have side effects when invoked.
implementing_attribute = self.class_manager._get_class_attr_mro(
- key, prop)
- if implementing_attribute is prop or (isinstance(
- implementing_attribute,
- attributes.InstrumentedAttribute) and
- implementing_attribute._parententity is prop.parent
+ key, prop
+ )
+ if implementing_attribute is prop or (
+ isinstance(
+ implementing_attribute, attributes.InstrumentedAttribute
+ )
+ and implementing_attribute._parententity is prop.parent
):
self._configure_property(
key,
properties.ConcreteInheritedProperty(),
- init=init, setparent=True)
+ init=init,
+ setparent=True,
+ )
def _configure_property(self, key, prop, init=True, setparent=True):
self._log("_configure_property(%s, %s)", key, prop.__class__.__name__)
@@ -1659,7 +1735,8 @@ class Mapper(InspectionAttr):
for m2 in path:
m2.mapped_table._reset_exported()
col = self.mapped_table.corresponding_column(
- prop.columns[0])
+ prop.columns[0]
+ )
break
path.append(m)
@@ -1670,26 +1747,30 @@ class Mapper(InspectionAttr):
# column is coming in after _readonly_props was
# initialized; check for 'readonly'
- if hasattr(self, '_readonly_props') and \
- (not hasattr(col, 'table') or
- col.table not in self._cols_by_table):
+ if hasattr(self, "_readonly_props") and (
+ not hasattr(col, "table")
+ or col.table not in self._cols_by_table
+ ):
self._readonly_props.add(prop)
else:
# if column is coming in after _cols_by_table was
# initialized, ensure the col is in the right set
- if hasattr(self, '_cols_by_table') and \
- col.table in self._cols_by_table and \
- col not in self._cols_by_table[col.table]:
+ if (
+ hasattr(self, "_cols_by_table")
+ and col.table in self._cols_by_table
+ and col not in self._cols_by_table[col.table]
+ ):
self._cols_by_table[col.table].add(col)
# if this properties.ColumnProperty represents the "polymorphic
# discriminator" column, mark it. We'll need this when rendering
# columns in SELECT statements.
- if not hasattr(prop, '_is_polymorphic_discriminator'):
- prop._is_polymorphic_discriminator = \
- (col is self.polymorphic_on or
- prop.columns[0] is self.polymorphic_on)
+ if not hasattr(prop, "_is_polymorphic_discriminator"):
+ prop._is_polymorphic_discriminator = (
+ col is self.polymorphic_on
+ or prop.columns[0] is self.polymorphic_on
+ )
self.columns[key] = col
for col in prop.columns + prop._orig_columns:
@@ -1701,8 +1782,9 @@ class Mapper(InspectionAttr):
if setparent:
prop.set_parent(self, init)
- if key in self._props and \
- getattr(self._props[key], '_mapped_by_synonym', False):
+ if key in self._props and getattr(
+ self._props[key], "_mapped_by_synonym", False
+ ):
syn = self._props[key]._mapped_by_synonym
raise sa_exc.ArgumentError(
"Can't call map_column=True for synonym %r=%r, "
@@ -1710,20 +1792,22 @@ class Mapper(InspectionAttr):
"%r for column %r" % (syn, key, key, syn)
)
- if key in self._props and \
- not isinstance(prop, properties.ColumnProperty) and \
- not isinstance(
- self._props[key],
- (
- properties.ColumnProperty,
- properties.ConcreteInheritedProperty)
- ):
- util.warn("Property %s on %s being replaced with new "
- "property %s; the old property will be discarded" % (
- self._props[key],
- self,
- prop,
- ))
+ if (
+ key in self._props
+ and not isinstance(prop, properties.ColumnProperty)
+ and not isinstance(
+ self._props[key],
+ (
+ properties.ColumnProperty,
+ properties.ConcreteInheritedProperty,
+ ),
+ )
+ ):
+ util.warn(
+ "Property %s on %s being replaced with new "
+ "property %s; the old property will be discarded"
+ % (self._props[key], self, prop)
+ )
oldprop = self._props[key]
self._path_registry.pop(oldprop, None)
@@ -1753,23 +1837,29 @@ class Mapper(InspectionAttr):
if not expression._is_column(column):
raise sa_exc.ArgumentError(
"%s=%r is not an instance of MapperProperty or Column"
- % (key, prop))
+ % (key, prop)
+ )
prop = self._props.get(key, None)
if isinstance(prop, properties.ColumnProperty):
if (
- not self._inherits_equated_pairs or
- (prop.columns[0], column) not in self._inherits_equated_pairs
- ) and \
- not prop.columns[0].shares_lineage(column) and \
- prop.columns[0] is not self.version_id_col and \
- column is not self.version_id_col:
+ (
+ not self._inherits_equated_pairs
+ or (prop.columns[0], column)
+ not in self._inherits_equated_pairs
+ )
+ and not prop.columns[0].shares_lineage(column)
+ and prop.columns[0] is not self.version_id_col
+ and column is not self.version_id_col
+ ):
warn_only = prop.parent is not self
- msg = ("Implicitly combining column %s with column "
- "%s under attribute '%s'. Please configure one "
- "or more attributes for these same-named columns "
- "explicitly." % (prop.columns[-1], column, key))
+ msg = (
+ "Implicitly combining column %s with column "
+ "%s under attribute '%s'. Please configure one "
+ "or more attributes for these same-named columns "
+ "explicitly." % (prop.columns[-1], column, key)
+ )
if warn_only:
util.warn(msg)
else:
@@ -1779,11 +1869,14 @@ class Mapper(InspectionAttr):
# mapper. make a copy and append our column to it
prop = prop.copy()
prop.columns.insert(0, column)
- self._log("inserting column to existing list "
- "in properties.ColumnProperty %s" % (key))
+ self._log(
+ "inserting column to existing list "
+ "in properties.ColumnProperty %s" % (key)
+ )
return prop
- elif prop is None or isinstance(prop,
- properties.ConcreteInheritedProperty):
+ elif prop is None or isinstance(
+ prop, properties.ConcreteInheritedProperty
+ ):
mapped_column = []
for c in columns:
mc = self.mapped_table.corresponding_column(c)
@@ -1802,7 +1895,8 @@ class Mapper(InspectionAttr):
"column '%s' is not represented in the mapper's "
"table. Use the `column_property()` function to "
"force this column to be mapped as a read-only "
- "attribute." % (key, self, c))
+ "attribute." % (key, self, c)
+ )
mapped_column.append(mc)
return properties.ColumnProperty(*mapped_column)
else:
@@ -1815,8 +1909,8 @@ class Mapper(InspectionAttr):
"(including its availability as a foreign key), "
"use the 'include_properties' or 'exclude_properties' "
"mapper arguments to control specifically which table "
- "columns get mapped." %
- (key, self, column.key, prop))
+ "columns get mapped." % (key, self, column.key, prop)
+ )
def _post_configure_properties(self):
"""Call the ``init()`` method on all ``MapperProperties``
@@ -1867,34 +1961,35 @@ class Mapper(InspectionAttr):
@property
def _log_desc(self):
- return "(" + self.class_.__name__ + \
- "|" + \
- (self.local_table is not None and
- self.local_table.description or
- str(self.local_table)) +\
- (self.non_primary and
- "|non-primary" or "") + ")"
+ return (
+ "("
+ + self.class_.__name__
+ + "|"
+ + (
+ self.local_table is not None
+ and self.local_table.description
+ or str(self.local_table)
+ )
+ + (self.non_primary and "|non-primary" or "")
+ + ")"
+ )
def _log(self, msg, *args):
- self.logger.info(
- "%s " + msg, *((self._log_desc,) + args)
- )
+ self.logger.info("%s " + msg, *((self._log_desc,) + args))
def _log_debug(self, msg, *args):
- self.logger.debug(
- "%s " + msg, *((self._log_desc,) + args)
- )
+ self.logger.debug("%s " + msg, *((self._log_desc,) + args))
def __repr__(self):
- return '<Mapper at 0x%x; %s>' % (
- id(self), self.class_.__name__)
+ return "<Mapper at 0x%x; %s>" % (id(self), self.class_.__name__)
def __str__(self):
return "Mapper|%s|%s%s" % (
self.class_.__name__,
- self.local_table is not None and
- self.local_table.description or None,
- self.non_primary and "|non-primary" or ""
+ self.local_table is not None
+ and self.local_table.description
+ or None,
+ self.non_primary and "|non-primary" or "",
)
def _is_orphan(self, state):
@@ -1904,7 +1999,8 @@ class Mapper(InspectionAttr):
orphan_possible = True
has_parent = attributes.manager_of_class(cls).has_parent(
- state, key, optimistic=state.has_identity)
+ state, key, optimistic=state.has_identity
+ )
if self.legacy_is_orphan and has_parent:
return False
@@ -1930,7 +2026,8 @@ class Mapper(InspectionAttr):
return self._props[key]
except KeyError:
raise sa_exc.InvalidRequestError(
- "Mapper '%s' has no property '%s'" % (self, key))
+ "Mapper '%s' has no property '%s'" % (self, key)
+ )
def get_property_by_column(self, column):
"""Given a :class:`.Column` object, return the
@@ -1953,7 +2050,7 @@ class Mapper(InspectionAttr):
selectable, if present. This helps some more legacy-ish mappings.
"""
- if spec == '*':
+ if spec == "*":
mappers = list(self.self_and_descendants)
elif spec:
mappers = set()
@@ -1961,8 +2058,8 @@ class Mapper(InspectionAttr):
m = _class_to_mapper(m)
if not m.isa(self):
raise sa_exc.InvalidRequestError(
- "%r does not inherit from %r" %
- (m, self))
+ "%r does not inherit from %r" % (m, self)
+ )
if selectable is None:
mappers.update(m.iterate_to_root())
@@ -1973,8 +2070,9 @@ class Mapper(InspectionAttr):
mappers = []
if selectable is not None:
- tables = set(sql_util.find_tables(selectable,
- include_aliases=True))
+ tables = set(
+ sql_util.find_tables(selectable, include_aliases=True)
+ )
mappers = [m for m in mappers if m.local_table in tables]
return mappers
@@ -1991,25 +2089,26 @@ class Mapper(InspectionAttr):
if m.concrete:
raise sa_exc.InvalidRequestError(
"'with_polymorphic()' requires 'selectable' argument "
- "when concrete-inheriting mappers are used.")
+ "when concrete-inheriting mappers are used."
+ )
elif not m.single:
if innerjoin:
- from_obj = from_obj.join(m.local_table,
- m.inherit_condition)
+ from_obj = from_obj.join(
+ m.local_table, m.inherit_condition
+ )
else:
- from_obj = from_obj.outerjoin(m.local_table,
- m.inherit_condition)
+ from_obj = from_obj.outerjoin(
+ m.local_table, m.inherit_condition
+ )
return from_obj
@_memoized_configured_property
def _single_table_criterion(self):
- if self.single and \
- self.inherits and \
- self.polymorphic_on is not None:
+ if self.single and self.inherits and self.polymorphic_on is not None:
return self.polymorphic_on.in_(
- m.polymorphic_identity
- for m in self.self_and_descendants)
+ m.polymorphic_identity for m in self.self_and_descendants
+ )
else:
return None
@@ -2031,8 +2130,8 @@ class Mapper(InspectionAttr):
return selectable
else:
return self._selectable_from_mappers(
- self._mappers_from_spec(spec, selectable),
- False)
+ self._mappers_from_spec(spec, selectable), False
+ )
with_polymorphic_mappers = _with_polymorphic_mappers
"""The list of :class:`.Mapper` objects included in the
@@ -2046,9 +2145,8 @@ class Mapper(InspectionAttr):
(
table,
frozenset(
- col for col in columns
- if col.type.should_evaluate_none
- )
+ col for col in columns if col.type.should_evaluate_none
+ ),
)
for table, columns in self._cols_by_table.items()
)
@@ -2059,10 +2157,13 @@ class Mapper(InspectionAttr):
(
table,
frozenset(
- col.key for col in columns
- if not col.primary_key and
- not col.server_default and not col.default
- and not col.type.should_evaluate_none)
+ col.key
+ for col in columns
+ if not col.primary_key
+ and not col.server_default
+ and not col.default
+ and not col.type.should_evaluate_none
+ ),
)
for table, columns in self._cols_by_table.items()
)
@@ -2073,9 +2174,8 @@ class Mapper(InspectionAttr):
(
table,
dict(
- (self._columntoproperty[col].key, col)
- for col in columns
- )
+ (self._columntoproperty[col].key, col) for col in columns
+ ),
)
for table, columns in self._cols_by_table.items()
)
@@ -2083,10 +2183,7 @@ class Mapper(InspectionAttr):
@_memoized_configured_property
def _pk_keys_by_table(self):
return dict(
- (
- table,
- frozenset([col.key for col in pks])
- )
+ (table, frozenset([col.key for col in pks]))
for table, pks in self._pks_by_table.items()
)
@@ -2095,7 +2192,7 @@ class Mapper(InspectionAttr):
return dict(
(
table,
- frozenset([self._columntoproperty[col].key for col in pks])
+ frozenset([self._columntoproperty[col].key for col in pks]),
)
for table, pks in self._pks_by_table.items()
)
@@ -2105,9 +2202,13 @@ class Mapper(InspectionAttr):
return dict(
(
table,
- frozenset([
- col.key for col in columns
- if col.server_default is not None])
+ frozenset(
+ [
+ col.key
+ for col in columns
+ if col.server_default is not None
+ ]
+ ),
)
for table, columns in self._cols_by_table.items()
)
@@ -2119,11 +2220,9 @@ class Mapper(InspectionAttr):
for table, columns in self._cols_by_table.items():
for col in columns:
if (
- (
- col.server_default is not None or
- col.server_onupdate is not None
- ) and col in self._columntoproperty
- ):
+ col.server_default is not None
+ or col.server_onupdate is not None
+ ) and col in self._columntoproperty:
result.add(self._columntoproperty[col].key)
return result
@@ -2133,9 +2232,13 @@ class Mapper(InspectionAttr):
return dict(
(
table,
- frozenset([
- col.key for col in columns
- if col.server_onupdate is not None])
+ frozenset(
+ [
+ col.key
+ for col in columns
+ if col.server_onupdate is not None
+ ]
+ ),
)
for table, columns in self._cols_by_table.items()
)
@@ -2152,8 +2255,9 @@ class Mapper(InspectionAttr):
"""
return self._with_polymorphic_selectable
- def _with_polymorphic_args(self, spec=None, selectable=False,
- innerjoin=False):
+ def _with_polymorphic_args(
+ self, spec=None, selectable=False, innerjoin=False
+ ):
if self.with_polymorphic:
if not spec:
spec = self.with_polymorphic[0]
@@ -2165,13 +2269,15 @@ class Mapper(InspectionAttr):
if selectable is not None:
return mappers, selectable
else:
- return mappers, self._selectable_from_mappers(mappers,
- innerjoin)
+ return mappers, self._selectable_from_mappers(mappers, innerjoin)
@_memoized_configured_property
def _polymorphic_properties(self):
- return list(self._iterate_polymorphic_properties(
- self._with_polymorphic_mappers))
+ return list(
+ self._iterate_polymorphic_properties(
+ self._with_polymorphic_mappers
+ )
+ )
def _iterate_polymorphic_properties(self, mappers=None):
"""Return an iterator of MapperProperty objects which will render into
@@ -2187,14 +2293,17 @@ class Mapper(InspectionAttr):
# from other mappers, as these are sometimes dependent on that
# mapper's polymorphic selectable (which we don't want rendered)
for c in util.unique_list(
- chain(*[
- list(mapper.iterate_properties) for mapper in
- [self] + mappers
- ])
+ chain(
+ *[
+ list(mapper.iterate_properties)
+ for mapper in [self] + mappers
+ ]
+ )
):
- if getattr(c, '_is_polymorphic_discriminator', False) and \
- (self.polymorphic_on is None or
- c.columns[0] is not self.polymorphic_on):
+ if getattr(c, "_is_polymorphic_discriminator", False) and (
+ self.polymorphic_on is None
+ or c.columns[0] is not self.polymorphic_on
+ ):
continue
yield c
@@ -2282,7 +2391,8 @@ class Mapper(InspectionAttr):
"""
return util.ImmutableProperties(
- dict(self.class_manager._all_sqla_attributes()))
+ dict(self.class_manager._all_sqla_attributes())
+ )
@_memoized_configured_property
def synonyms(self):
@@ -2351,10 +2461,11 @@ class Mapper(InspectionAttr):
def _filter_properties(self, type_):
if Mapper._new_mappers:
configure_mappers()
- return util.ImmutableProperties(util.OrderedDict(
- (k, v) for k, v in self._props.items()
- if isinstance(v, type_)
- ))
+ return util.ImmutableProperties(
+ util.OrderedDict(
+ (k, v) for k, v in self._props.items() if isinstance(v, type_)
+ )
+ )
@_memoized_configured_property
def _get_clause(self):
@@ -2363,10 +2474,14 @@ class Mapper(InspectionAttr):
by primary key.
"""
- params = [(primary_key, sql.bindparam(None, type_=primary_key.type))
- for primary_key in self.primary_key]
- return sql.and_(*[k == v for (k, v) in params]), \
- util.column_dict(params)
+ params = [
+ (primary_key, sql.bindparam(None, type_=primary_key.type))
+ for primary_key in self.primary_key
+ ]
+ return (
+ sql.and_(*[k == v for (k, v) in params]),
+ util.column_dict(params),
+ )
@_memoized_configured_property
def _equivalent_columns(self):
@@ -2401,18 +2516,24 @@ class Mapper(InspectionAttr):
result[binary.right].add(binary.left)
else:
result[binary.right] = util.column_set((binary.left,))
+
for mapper in self.base_mapper.self_and_descendants:
if mapper.inherit_condition is not None:
visitors.traverse(
- mapper.inherit_condition, {},
- {'binary': visit_binary})
+ mapper.inherit_condition, {}, {"binary": visit_binary}
+ )
return result
def _is_userland_descriptor(self, obj):
- if isinstance(obj, (_MappedAttribute,
- instrumentation.ClassManager,
- expression.ColumnElement)):
+ if isinstance(
+ obj,
+ (
+ _MappedAttribute,
+ instrumentation.ClassManager,
+ expression.ColumnElement,
+ ),
+ ):
return False
else:
return True
@@ -2429,26 +2550,29 @@ class Mapper(InspectionAttr):
# check for class-bound attributes and/or descriptors,
# either local or from an inherited class
if local:
- if self.class_.__dict__.get(assigned_name, None) is not None \
- and self._is_userland_descriptor(
- self.class_.__dict__[assigned_name]):
+ if self.class_.__dict__.get(
+ assigned_name, None
+ ) is not None and self._is_userland_descriptor(
+ self.class_.__dict__[assigned_name]
+ ):
return True
else:
attr = self.class_manager._get_class_attr_mro(assigned_name, None)
if attr is not None and self._is_userland_descriptor(attr):
return True
- if self.include_properties is not None and \
- name not in self.include_properties and \
- (column is None or column not in self.include_properties):
+ if (
+ self.include_properties is not None
+ and name not in self.include_properties
+ and (column is None or column not in self.include_properties)
+ ):
self._log("not including property %s" % (name))
return True
- if self.exclude_properties is not None and \
- (
- name in self.exclude_properties or
- (column is not None and column in self.exclude_properties)
- ):
+ if self.exclude_properties is not None and (
+ name in self.exclude_properties
+ or (column is not None and column in self.exclude_properties)
+ ):
self._log("excluding property %s" % (name))
return True
@@ -2545,8 +2669,11 @@ class Mapper(InspectionAttr):
if adapter:
pk_cols = [adapter.columns[c] for c in pk_cols]
- return self._identity_class, \
- tuple(row[column] for column in pk_cols), identity_token
+ return (
+ self._identity_class,
+ tuple(row[column] for column in pk_cols),
+ identity_token,
+ )
def identity_key_from_primary_key(self, primary_key, identity_token=None):
"""Return an identity-map key for use in storing/retrieving an
@@ -2574,14 +2701,20 @@ class Mapper(InspectionAttr):
return self._identity_key_from_state(state, attributes.PASSIVE_OFF)
def _identity_key_from_state(
- self, state, passive=attributes.PASSIVE_RETURN_NEVER_SET):
+ self, state, passive=attributes.PASSIVE_RETURN_NEVER_SET
+ ):
dict_ = state.dict
manager = state.manager
- return self._identity_class, tuple([
- manager[prop.key].
- impl.get(state, dict_, passive)
- for prop in self._identity_key_props
- ]), state.identity_token
+ return (
+ self._identity_class,
+ tuple(
+ [
+ manager[prop.key].impl.get(state, dict_, passive)
+ for prop in self._identity_key_props
+ ]
+ ),
+ state.identity_token,
+ )
def primary_key_from_instance(self, instance):
"""Return the list of primary key values for the given
@@ -2595,7 +2728,8 @@ class Mapper(InspectionAttr):
"""
state = attributes.instance_state(instance)
identity_key = self._identity_key_from_state(
- state, attributes.PASSIVE_OFF)
+ state, attributes.PASSIVE_OFF
+ )
return identity_key[1]
@_memoized_configured_property
@@ -2621,8 +2755,8 @@ class Mapper(InspectionAttr):
return {prop.key for prop in self._all_pk_props}
def _get_state_attr_by_column(
- self, state, dict_, column,
- passive=attributes.PASSIVE_RETURN_NEVER_SET):
+ self, state, dict_, column, passive=attributes.PASSIVE_RETURN_NEVER_SET
+ ):
prop = self._columntoproperty[column]
return state.manager[prop.key].impl.get(state, dict_, passive=passive)
@@ -2638,15 +2772,17 @@ class Mapper(InspectionAttr):
state = attributes.instance_state(obj)
dict_ = attributes.instance_dict(obj)
return self._get_committed_state_attr_by_column(
- state, dict_, column, passive=attributes.PASSIVE_OFF)
+ state, dict_, column, passive=attributes.PASSIVE_OFF
+ )
def _get_committed_state_attr_by_column(
- self, state, dict_, column,
- passive=attributes.PASSIVE_RETURN_NEVER_SET):
+ self, state, dict_, column, passive=attributes.PASSIVE_RETURN_NEVER_SET
+ ):
prop = self._columntoproperty[column]
- return state.manager[prop.key].impl.\
- get_committed_value(state, dict_, passive=passive)
+ return state.manager[prop.key].impl.get_committed_value(
+ state, dict_, passive=passive
+ )
def _optimized_get_statement(self, state, attribute_names):
"""assemble a WHERE clause which retrieves a given state by primary
@@ -2660,11 +2796,15 @@ class Mapper(InspectionAttr):
"""
props = self._props
- tables = set(chain(
- *[sql_util.find_tables(c, check_columns=True)
- for key in attribute_names
- for c in props[key].columns]
- ))
+ tables = set(
+ chain(
+ *[
+ sql_util.find_tables(c, check_columns=True)
+ for key in attribute_names
+ for c in props[key].columns
+ ]
+ )
+ )
if self.base_mapper.local_table in tables:
return None
@@ -2680,22 +2820,28 @@ class Mapper(InspectionAttr):
if leftcol.table not in tables:
leftval = self._get_committed_state_attr_by_column(
- state, state.dict,
+ state,
+ state.dict,
leftcol,
- passive=attributes.PASSIVE_NO_INITIALIZE)
+ passive=attributes.PASSIVE_NO_INITIALIZE,
+ )
if leftval in orm_util._none_set:
raise ColumnsNotAvailable()
- binary.left = sql.bindparam(None, leftval,
- type_=binary.right.type)
+ binary.left = sql.bindparam(
+ None, leftval, type_=binary.right.type
+ )
elif rightcol.table not in tables:
rightval = self._get_committed_state_attr_by_column(
- state, state.dict,
+ state,
+ state.dict,
rightcol,
- passive=attributes.PASSIVE_NO_INITIALIZE)
+ passive=attributes.PASSIVE_NO_INITIALIZE,
+ )
if rightval in orm_util._none_set:
raise ColumnsNotAvailable()
- binary.right = sql.bindparam(None, rightval,
- type_=binary.right.type)
+ binary.right = sql.bindparam(
+ None, rightval, type_=binary.right.type
+ )
allconds = []
@@ -2704,15 +2850,17 @@ class Mapper(InspectionAttr):
for mapper in reversed(list(self.iterate_to_root())):
if mapper.local_table in tables:
start = True
- elif not isinstance(mapper.local_table,
- expression.TableClause):
+ elif not isinstance(
+ mapper.local_table, expression.TableClause
+ ):
return None
if start and not mapper.single:
- allconds.append(visitors.cloned_traverse(
- mapper.inherit_condition,
- {},
- {'binary': visit_binary}
- )
+ allconds.append(
+ visitors.cloned_traverse(
+ mapper.inherit_condition,
+ {},
+ {"binary": visit_binary},
+ )
)
except ColumnsNotAvailable:
return None
@@ -2730,8 +2878,7 @@ class Mapper(InspectionAttr):
for m in self.iterate_to_root():
yield m
- if m is not prev and prev not in \
- m._with_polymorphic_mappers:
+ if m is not prev and prev not in m._with_polymorphic_mappers:
break
prev = m
@@ -2743,7 +2890,7 @@ class Mapper(InspectionAttr):
# common case, takes place for all polymorphic loads
mapper = polymorphic_from
for m in self._iterate_to_target_viawpoly(mapper):
- if m.polymorphic_load == 'selectin':
+ if m.polymorphic_load == "selectin":
return m
else:
# uncommon case, selectin load options were used
@@ -2752,15 +2899,17 @@ class Mapper(InspectionAttr):
for entity in enabled_via_opt.union([polymorphic_from]):
mapper = entity.mapper
for m in self._iterate_to_target_viawpoly(mapper):
- if m.polymorphic_load == 'selectin' or \
- m in enabled_via_opt_mappers:
+ if (
+ m.polymorphic_load == "selectin"
+ or m in enabled_via_opt_mappers
+ ):
return enabled_via_opt_mappers.get(m, m)
return None
@util.dependencies(
- "sqlalchemy.ext.baked",
- "sqlalchemy.orm.strategy_options")
+ "sqlalchemy.ext.baked", "sqlalchemy.orm.strategy_options"
+ )
def _subclass_load_via_in(self, baked, strategy_options, entity):
"""Assemble a BakedQuery that can load the columns local to
this subclass as a SELECT with IN.
@@ -2768,10 +2917,8 @@ class Mapper(InspectionAttr):
"""
assert self.inherits
- polymorphic_prop = self._columntoproperty[
- self.polymorphic_on]
- keep_props = set(
- [polymorphic_prop] + self._identity_key_props)
+ polymorphic_prop = self._columntoproperty[self.polymorphic_on]
+ keep_props = set([polymorphic_prop] + self._identity_key_props)
disable_opt = strategy_options.Load(entity)
enable_opt = strategy_options.Load(entity)
@@ -2781,16 +2928,14 @@ class Mapper(InspectionAttr):
# "enable" options, to turn on the properties that we want to
# load by default (subject to options from the query)
enable_opt.set_generic_strategy(
- (prop.key, ),
- dict(prop.strategy_key)
+ (prop.key,), dict(prop.strategy_key)
)
else:
# "disable" options, to turn off the properties from the
# superclass that we *don't* want to load, applied after
# the options from the query to override them
disable_opt.set_generic_strategy(
- (prop.key, ),
- {"do_nothing": True}
+ (prop.key,), {"do_nothing": True}
)
if len(self.primary_key) > 1:
@@ -2802,22 +2947,21 @@ class Mapper(InspectionAttr):
assert entity.mapper is self
q = baked.BakedQuery(
self._compiled_cache,
- lambda session: session.query(entity).
- select_entity_from(entity.selectable)._adapt_all_clauses(),
- (self, )
+ lambda session: session.query(entity)
+ .select_entity_from(entity.selectable)
+ ._adapt_all_clauses(),
+ (self,),
)
q.spoil()
else:
q = baked.BakedQuery(
self._compiled_cache,
lambda session: session.query(self),
- (self, )
+ (self,),
)
q += lambda q: q.filter(
- in_expr.in_(
- sql.bindparam('primary_keys', expanding=True)
- )
+ in_expr.in_(sql.bindparam("primary_keys", expanding=True))
).order_by(*self.primary_key)
return q, enable_opt, disable_opt
@@ -2856,8 +3000,9 @@ class Mapper(InspectionAttr):
assert state.mapper.isa(self)
- visitables = deque([(deque(state.mapper._props.values()), prp,
- state, state.dict)])
+ visitables = deque(
+ [(deque(state.mapper._props.values()), prp, state, state.dict)]
+ )
while visitables:
iterator, item_type, parent_state, parent_dict = visitables[-1]
@@ -2869,21 +3014,28 @@ class Mapper(InspectionAttr):
prop = iterator.popleft()
if type_ not in prop.cascade:
continue
- queue = deque(prop.cascade_iterator(
- type_, parent_state, parent_dict,
- visited_states, halt_on))
+ queue = deque(
+ prop.cascade_iterator(
+ type_,
+ parent_state,
+ parent_dict,
+ visited_states,
+ halt_on,
+ )
+ )
if queue:
visitables.append((queue, mpp, None, None))
elif item_type is mpp:
- instance, instance_mapper, corresponding_state, \
- corresponding_dict = iterator.popleft()
- yield instance, instance_mapper, \
- corresponding_state, corresponding_dict
+ instance, instance_mapper, corresponding_state, corresponding_dict = (
+ iterator.popleft()
+ )
+ yield instance, instance_mapper, corresponding_state, corresponding_dict
visitables.append(
(
deque(instance_mapper._props.values()),
- prp, corresponding_state,
- corresponding_dict
+ prp,
+ corresponding_state,
+ corresponding_dict,
)
)
@@ -2903,10 +3055,9 @@ class Mapper(InspectionAttr):
for table, mapper in table_to_mapper.items():
super_ = mapper.inherits
if super_:
- extra_dependencies.extend([
- (super_table, table)
- for super_table in super_.tables
- ])
+ extra_dependencies.extend(
+ [(super_table, table) for super_table in super_.tables]
+ )
def skip(fk):
# attempt to skip dependencies that are not
@@ -2916,22 +3067,27 @@ class Mapper(InspectionAttr):
# not what we mean to sort on here.
parent = table_to_mapper.get(fk.parent.table)
dep = table_to_mapper.get(fk.column.table)
- if parent is not None and \
- dep is not None and \
- dep is not parent and \
- dep.inherit_condition is not None:
+ if (
+ parent is not None
+ and dep is not None
+ and dep is not parent
+ and dep.inherit_condition is not None
+ ):
cols = set(sql_util._find_columns(dep.inherit_condition))
if parent.inherit_condition is not None:
- cols = cols.union(sql_util._find_columns(
- parent.inherit_condition))
+ cols = cols.union(
+ sql_util._find_columns(parent.inherit_condition)
+ )
return fk.parent not in cols and fk.column not in cols
else:
return fk.parent not in cols
return False
- sorted_ = sql_util.sort_tables(table_to_mapper,
- skip_fn=skip,
- extra_dependencies=extra_dependencies)
+ sorted_ = sql_util.sort_tables(
+ table_to_mapper,
+ skip_fn=skip,
+ extra_dependencies=extra_dependencies,
+ )
ret = util.OrderedDict()
for t in sorted_:
@@ -2955,12 +3111,12 @@ class Mapper(InspectionAttr):
for table in self._sorted_tables:
cols = set(table.c)
for m in self.iterate_to_root():
- if m._inherits_equated_pairs and \
- cols.intersection(
- util.reduce(set.union,
- [l.proxy_set for l, r in
- m._inherits_equated_pairs])
- ):
+ if m._inherits_equated_pairs and cols.intersection(
+ util.reduce(
+ set.union,
+ [l.proxy_set for l, r in m._inherits_equated_pairs],
+ )
+ ):
result[table].append((m, m._inherits_equated_pairs))
return result
@@ -3034,13 +3190,14 @@ def configure_mappers():
if run_configure is EXT_SKIP:
continue
- if getattr(mapper, '_configure_failed', False):
+ if getattr(mapper, "_configure_failed", False):
e = sa_exc.InvalidRequestError(
"One or more mappers failed to initialize - "
"can't proceed with initialization of other "
"mappers. Triggering mapper: '%s'. "
"Original exception was: %s"
- % (mapper, mapper._configure_failed))
+ % (mapper, mapper._configure_failed)
+ )
e._configure_failed = mapper._configure_failed
raise e
@@ -3049,10 +3206,11 @@ def configure_mappers():
mapper._post_configure_properties()
mapper._expire_memoizations()
mapper.dispatch.mapper_configured(
- mapper, mapper.class_)
+ mapper, mapper.class_
+ )
except Exception:
exc = sys.exc_info()[1]
- if not hasattr(exc, '_configure_failed'):
+ if not hasattr(exc, "_configure_failed"):
mapper._configure_failed = exc
raise
@@ -3127,16 +3285,17 @@ def validates(*names, **kw):
:ref:`simple_validators` - usage examples for :func:`.validates`
"""
- include_removes = kw.pop('include_removes', False)
- include_backrefs = kw.pop('include_backrefs', True)
+ include_removes = kw.pop("include_removes", False)
+ include_backrefs = kw.pop("include_backrefs", True)
def wrap(fn):
fn.__sa_validators__ = names
fn.__sa_validation_opts__ = {
"include_removes": include_removes,
- "include_backrefs": include_backrefs
+ "include_backrefs": include_backrefs,
}
return fn
+
return wrap
@@ -3180,7 +3339,7 @@ def _event_on_init(state, args, kwargs):
class _ColumnMapping(dict):
"""Error reporting helper for mapper._columntoproperty."""
- __slots__ = 'mapper',
+ __slots__ = ("mapper",)
def __init__(self, mapper):
self.mapper = mapper
@@ -3190,8 +3349,10 @@ class _ColumnMapping(dict):
if prop:
raise orm_exc.UnmappedColumnError(
"Column '%s.%s' is not available, due to "
- "conflicting property '%s':%r" % (
- column.table.name, column.name, column.key, prop))
+ "conflicting property '%s':%r"
+ % (column.table.name, column.name, column.key, prop)
+ )
raise orm_exc.UnmappedColumnError(
- "No column %s is configured on mapper %s..." %
- (column, self.mapper))
+ "No column %s is configured on mapper %s..."
+ % (column, self.mapper)
+ )
diff --git a/lib/sqlalchemy/orm/path_registry.py b/lib/sqlalchemy/orm/path_registry.py
index bb4e2eda5..f33c209cc 100644
--- a/lib/sqlalchemy/orm/path_registry.py
+++ b/lib/sqlalchemy/orm/path_registry.py
@@ -56,8 +56,7 @@ class PathRegistry(object):
is_root = False
def __eq__(self, other):
- return other is not None and \
- self.path == other.path
+ return other is not None and self.path == other.path
def set(self, attributes, key, value):
log.debug("set '%s' on path '%s' to '%s'", key, self, value)
@@ -87,11 +86,8 @@ class PathRegistry(object):
yield path[i], path[i + 1]
def contains_mapper(self, mapper):
- for path_mapper in [
- self.path[i] for i in range(0, len(self.path), 2)
- ]:
- if path_mapper.is_mapper and \
- path_mapper.isa(mapper):
+ for path_mapper in [self.path[i] for i in range(0, len(self.path), 2)]:
+ if path_mapper.is_mapper and path_mapper.isa(mapper):
return True
else:
return False
@@ -100,40 +96,49 @@ class PathRegistry(object):
return (key, self.path) in attributes
def __reduce__(self):
- return _unreduce_path, (self.serialize(), )
+ return _unreduce_path, (self.serialize(),)
def serialize(self):
path = self.path
- return list(zip(
- [m.class_ for m in [path[i] for i in range(0, len(path), 2)]],
- [path[i].key for i in range(1, len(path), 2)] + [None]
- ))
+ return list(
+ zip(
+ [m.class_ for m in [path[i] for i in range(0, len(path), 2)]],
+ [path[i].key for i in range(1, len(path), 2)] + [None],
+ )
+ )
@classmethod
def deserialize(cls, path):
if path is None:
return None
- p = tuple(chain(*[(class_mapper(mcls),
- class_mapper(mcls).attrs[key]
- if key is not None else None)
- for mcls, key in path]))
+ p = tuple(
+ chain(
+ *[
+ (
+ class_mapper(mcls),
+ class_mapper(mcls).attrs[key]
+ if key is not None
+ else None,
+ )
+ for mcls, key in path
+ ]
+ )
+ )
if p and p[-1] is None:
p = p[0:-1]
return cls.coerce(p)
@classmethod
def per_mapper(cls, mapper):
- return EntityRegistry(
- cls.root, mapper
- )
+ return EntityRegistry(cls.root, mapper)
@classmethod
def coerce(cls, raw):
return util.reduce(lambda prev, next: prev[next], raw, cls.root)
def token(self, token):
- if token.endswith(':' + _WILDCARD_TOKEN):
+ if token.endswith(":" + _WILDCARD_TOKEN):
return TokenRegistry(self, token)
elif token.endswith(":" + _DEFAULT_TOKEN):
return TokenRegistry(self.root, token)
@@ -141,12 +146,10 @@ class PathRegistry(object):
raise exc.ArgumentError("invalid token: %s" % token)
def __add__(self, other):
- return util.reduce(
- lambda prev, next: prev[next],
- other.path, self)
+ return util.reduce(lambda prev, next: prev[next], other.path, self)
def __repr__(self):
- return "%s(%r)" % (self.__class__.__name__, self.path, )
+ return "%s(%r)" % (self.__class__.__name__, self.path)
class RootRegistry(PathRegistry):
@@ -154,6 +157,7 @@ class RootRegistry(PathRegistry):
paths are maintained per-root-mapper.
"""
+
path = ()
has_entity = False
is_aliased_class = False
@@ -162,6 +166,7 @@ class RootRegistry(PathRegistry):
def __getitem__(self, entity):
return entity._path_registry
+
PathRegistry.root = RootRegistry()
@@ -194,8 +199,10 @@ class PropRegistry(PathRegistry):
if not insp.is_aliased_class or insp._use_mapper_path:
parent = parent.parent[prop.parent]
elif insp.is_aliased_class and insp.with_polymorphic_mappers:
- if prop.parent is not insp.mapper and \
- prop.parent in insp.with_polymorphic_mappers:
+ if (
+ prop.parent is not insp.mapper
+ and prop.parent in insp.with_polymorphic_mappers
+ ):
subclass_entity = parent[-1]._entity_for_mapper(prop.parent)
parent = parent.parent[subclass_entity]
@@ -205,15 +212,13 @@ class PropRegistry(PathRegistry):
self._wildcard_path_loader_key = (
"loader",
- self.parent.path + self.prop._wildcard_token
+ self.parent.path + self.prop._wildcard_token,
)
self._default_path_loader_key = self.prop._default_path_loader_key
self._loader_key = ("loader", self.path)
def __str__(self):
- return " -> ".join(
- str(elem) for elem in self.path
- )
+ return " -> ".join(str(elem) for elem in self.path)
@util.memoized_property
def has_entity(self):
@@ -235,9 +240,7 @@ class PropRegistry(PathRegistry):
if isinstance(entity, (int, slice)):
return self.path[entity]
else:
- return EntityRegistry(
- self, entity
- )
+ return EntityRegistry(self, entity)
class EntityRegistry(PathRegistry, dict):
@@ -258,6 +261,7 @@ class EntityRegistry(PathRegistry, dict):
def __bool__(self):
return True
+
__nonzero__ = __bool__
def __getitem__(self, entity):
diff --git a/lib/sqlalchemy/orm/persistence.py b/lib/sqlalchemy/orm/persistence.py
index 7f9b7db0c..dc86a60e5 100644
--- a/lib/sqlalchemy/orm/persistence.py
+++ b/lib/sqlalchemy/orm/persistence.py
@@ -25,8 +25,13 @@ from . import loading
def _bulk_insert(
- mapper, mappings, session_transaction, isstates, return_defaults,
- render_nulls):
+ mapper,
+ mappings,
+ session_transaction,
+ isstates,
+ return_defaults,
+ render_nulls,
+):
base_mapper = mapper.base_mapper
cached_connections = _cached_connection_dict(base_mapper)
@@ -34,7 +39,8 @@ def _bulk_insert(
if session_transaction.session.connection_callable:
raise NotImplementedError(
"connection_callable / per-instance sharding "
- "not supported in bulk_insert()")
+ "not supported in bulk_insert()"
+ )
if isstates:
if return_defaults:
@@ -51,22 +57,33 @@ def _bulk_insert(
continue
records = (
- (None, state_dict, params, mapper,
- connection, value_params, has_all_pks, has_all_defaults)
- for
- state, state_dict, params, mp,
- conn, value_params, has_all_pks,
- has_all_defaults in _collect_insert_commands(table, (
- (None, mapping, mapper, connection)
- for mapping in mappings),
- bulk=True, return_defaults=return_defaults,
- render_nulls=render_nulls
+ (
+ None,
+ state_dict,
+ params,
+ mapper,
+ connection,
+ value_params,
+ has_all_pks,
+ has_all_defaults,
+ )
+ for state, state_dict, params, mp, conn, value_params, has_all_pks, has_all_defaults in _collect_insert_commands(
+ table,
+ ((None, mapping, mapper, connection) for mapping in mappings),
+ bulk=True,
+ return_defaults=return_defaults,
+ render_nulls=render_nulls,
)
)
- _emit_insert_statements(base_mapper, None,
- cached_connections,
- super_mapper, table, records,
- bookkeeping=return_defaults)
+ _emit_insert_statements(
+ base_mapper,
+ None,
+ cached_connections,
+ super_mapper,
+ table,
+ records,
+ bookkeeping=return_defaults,
+ )
if return_defaults and isstates:
identity_cls = mapper._identity_class
@@ -74,12 +91,13 @@ def _bulk_insert(
for state, dict_ in states:
state.key = (
identity_cls,
- tuple([dict_[key] for key in identity_props])
+ tuple([dict_[key] for key in identity_props]),
)
-def _bulk_update(mapper, mappings, session_transaction,
- isstates, update_changed_only):
+def _bulk_update(
+ mapper, mappings, session_transaction, isstates, update_changed_only
+):
base_mapper = mapper.base_mapper
cached_connections = _cached_connection_dict(base_mapper)
@@ -91,9 +109,8 @@ def _bulk_update(mapper, mappings, session_transaction,
def _changed_dict(mapper, state):
return dict(
(k, v)
- for k, v in state.dict.items() if k in state.committed_state or k
- in search_keys
-
+ for k, v in state.dict.items()
+ if k in state.committed_state or k in search_keys
)
if isstates:
@@ -107,7 +124,8 @@ def _bulk_update(mapper, mappings, session_transaction,
if session_transaction.session.connection_callable:
raise NotImplementedError(
"connection_callable / per-instance sharding "
- "not supported in bulk_update()")
+ "not supported in bulk_update()"
+ )
connection = session_transaction.connection(base_mapper)
@@ -115,21 +133,38 @@ def _bulk_update(mapper, mappings, session_transaction,
if not mapper.isa(super_mapper):
continue
- records = _collect_update_commands(None, table, (
- (None, mapping, mapper, connection,
- (mapping[mapper._version_id_prop.key]
- if mapper._version_id_prop else None))
- for mapping in mappings
- ), bulk=True)
+ records = _collect_update_commands(
+ None,
+ table,
+ (
+ (
+ None,
+ mapping,
+ mapper,
+ connection,
+ (
+ mapping[mapper._version_id_prop.key]
+ if mapper._version_id_prop
+ else None
+ ),
+ )
+ for mapping in mappings
+ ),
+ bulk=True,
+ )
- _emit_update_statements(base_mapper, None,
- cached_connections,
- super_mapper, table, records,
- bookkeeping=False)
+ _emit_update_statements(
+ base_mapper,
+ None,
+ cached_connections,
+ super_mapper,
+ table,
+ records,
+ bookkeeping=False,
+ )
-def save_obj(
- base_mapper, states, uowtransaction, single=False):
+def save_obj(base_mapper, states, uowtransaction, single=False):
"""Issue ``INSERT`` and/or ``UPDATE`` statements for a list
of objects.
@@ -150,19 +185,21 @@ def save_obj(
states_to_insert = []
cached_connections = _cached_connection_dict(base_mapper)
- for (state, dict_, mapper, connection,
- has_identity,
- row_switch, update_version_id) in _organize_states_for_save(
- base_mapper, states, uowtransaction
- ):
+ for (
+ state,
+ dict_,
+ mapper,
+ connection,
+ has_identity,
+ row_switch,
+ update_version_id,
+ ) in _organize_states_for_save(base_mapper, states, uowtransaction):
if has_identity or row_switch:
states_to_update.append(
(state, dict_, mapper, connection, update_version_id)
)
else:
- states_to_insert.append(
- (state, dict_, mapper, connection)
- )
+ states_to_insert.append((state, dict_, mapper, connection))
for table, mapper in base_mapper._sorted_tables.items():
if table not in mapper._pks_by_table:
@@ -170,18 +207,30 @@ def save_obj(
insert = _collect_insert_commands(table, states_to_insert)
update = _collect_update_commands(
- uowtransaction, table, states_to_update)
+ uowtransaction, table, states_to_update
+ )
- _emit_update_statements(base_mapper, uowtransaction,
- cached_connections,
- mapper, table, update)
+ _emit_update_statements(
+ base_mapper,
+ uowtransaction,
+ cached_connections,
+ mapper,
+ table,
+ update,
+ )
- _emit_insert_statements(base_mapper, uowtransaction,
- cached_connections,
- mapper, table, insert)
+ _emit_insert_statements(
+ base_mapper,
+ uowtransaction,
+ cached_connections,
+ mapper,
+ table,
+ insert,
+ )
_finalize_insert_update_commands(
- base_mapper, uowtransaction,
+ base_mapper,
+ uowtransaction,
chain(
(
(state, state_dict, mapper, connection, False)
@@ -189,10 +238,9 @@ def save_obj(
),
(
(state, state_dict, mapper, connection, True)
- for state, state_dict, mapper, connection,
- update_version_id in states_to_update
- )
- )
+ for state, state_dict, mapper, connection, update_version_id in states_to_update
+ ),
+ ),
)
@@ -203,9 +251,9 @@ def post_update(base_mapper, states, uowtransaction, post_update_cols):
"""
cached_connections = _cached_connection_dict(base_mapper)
- states_to_update = list(_organize_states_for_post_update(
- base_mapper,
- states, uowtransaction))
+ states_to_update = list(
+ _organize_states_for_post_update(base_mapper, states, uowtransaction)
+ )
for table, mapper in base_mapper._sorted_tables.items():
if table not in mapper._pks_by_table:
@@ -213,25 +261,32 @@ def post_update(base_mapper, states, uowtransaction, post_update_cols):
update = (
(
- state, state_dict, sub_mapper, connection,
+ state,
+ state_dict,
+ sub_mapper,
+ connection,
mapper._get_committed_state_attr_by_column(
state, state_dict, mapper.version_id_col
- ) if mapper.version_id_col is not None else None
+ )
+ if mapper.version_id_col is not None
+ else None,
)
- for
- state, state_dict, sub_mapper, connection in states_to_update
+ for state, state_dict, sub_mapper, connection in states_to_update
if table in sub_mapper._pks_by_table
)
update = _collect_post_update_commands(
- base_mapper, uowtransaction,
- table, update,
- post_update_cols
+ base_mapper, uowtransaction, table, update, post_update_cols
)
- _emit_post_update_statements(base_mapper, uowtransaction,
- cached_connections,
- mapper, table, update)
+ _emit_post_update_statements(
+ base_mapper,
+ uowtransaction,
+ cached_connections,
+ mapper,
+ table,
+ update,
+ )
def delete_obj(base_mapper, states, uowtransaction):
@@ -244,10 +299,9 @@ def delete_obj(base_mapper, states, uowtransaction):
cached_connections = _cached_connection_dict(base_mapper)
- states_to_delete = list(_organize_states_for_delete(
- base_mapper,
- states,
- uowtransaction))
+ states_to_delete = list(
+ _organize_states_for_delete(base_mapper, states, uowtransaction)
+ )
table_to_mapper = base_mapper._sorted_tables
@@ -258,14 +312,26 @@ def delete_obj(base_mapper, states, uowtransaction):
elif mapper.inherits and mapper.passive_deletes:
continue
- delete = _collect_delete_commands(base_mapper, uowtransaction,
- table, states_to_delete)
+ delete = _collect_delete_commands(
+ base_mapper, uowtransaction, table, states_to_delete
+ )
- _emit_delete_statements(base_mapper, uowtransaction,
- cached_connections, mapper, table, delete)
+ _emit_delete_statements(
+ base_mapper,
+ uowtransaction,
+ cached_connections,
+ mapper,
+ table,
+ delete,
+ )
- for state, state_dict, mapper, connection, \
- update_version_id in states_to_delete:
+ for (
+ state,
+ state_dict,
+ mapper,
+ connection,
+ update_version_id,
+ ) in states_to_delete:
mapper.dispatch.after_delete(mapper, connection, state)
@@ -282,8 +348,8 @@ def _organize_states_for_save(base_mapper, states, uowtransaction):
"""
for state, dict_, mapper, connection in _connections_for_states(
- base_mapper, uowtransaction,
- states):
+ base_mapper, uowtransaction, states
+ ):
has_identity = bool(state.key)
@@ -304,25 +370,29 @@ def _organize_states_for_save(base_mapper, states, uowtransaction):
# no instance_key attached to it), and another instance
# with the same identity key already exists as persistent.
# convert to an UPDATE if so.
- if not has_identity and \
- instance_key in uowtransaction.session.identity_map:
- instance = \
- uowtransaction.session.identity_map[instance_key]
+ if (
+ not has_identity
+ and instance_key in uowtransaction.session.identity_map
+ ):
+ instance = uowtransaction.session.identity_map[instance_key]
existing = attributes.instance_state(instance)
if not uowtransaction.was_already_deleted(existing):
if not uowtransaction.is_deleted(existing):
raise orm_exc.FlushError(
"New instance %s with identity key %s conflicts "
- "with persistent instance %s" %
- (state_str(state), instance_key,
- state_str(existing)))
+ "with persistent instance %s"
+ % (state_str(state), instance_key, state_str(existing))
+ )
base_mapper._log_debug(
"detected row switch for identity %s. "
"will update %s, remove %s from "
- "transaction", instance_key,
- state_str(state), state_str(existing))
+ "transaction",
+ instance_key,
+ state_str(state),
+ state_str(existing),
+ )
# remove the "delete" flag from the existing element
uowtransaction.remove_state_actions(existing)
@@ -332,14 +402,21 @@ def _organize_states_for_save(base_mapper, states, uowtransaction):
update_version_id = mapper._get_committed_state_attr_by_column(
row_switch if row_switch else state,
row_switch.dict if row_switch else dict_,
- mapper.version_id_col)
+ mapper.version_id_col,
+ )
- yield (state, dict_, mapper, connection,
- has_identity, row_switch, update_version_id)
+ yield (
+ state,
+ dict_,
+ mapper,
+ connection,
+ has_identity,
+ row_switch,
+ update_version_id,
+ )
-def _organize_states_for_post_update(base_mapper, states,
- uowtransaction):
+def _organize_states_for_post_update(base_mapper, states, uowtransaction):
"""Make an initial pass across a set of states for UPDATE
corresponding to post_update.
@@ -360,26 +437,28 @@ def _organize_states_for_delete(base_mapper, states, uowtransaction):
"""
for state, dict_, mapper, connection in _connections_for_states(
- base_mapper, uowtransaction,
- states):
+ base_mapper, uowtransaction, states
+ ):
mapper.dispatch.before_delete(mapper, connection, state)
if mapper.version_id_col is not None:
- update_version_id = \
- mapper._get_committed_state_attr_by_column(
- state, dict_,
- mapper.version_id_col)
+ update_version_id = mapper._get_committed_state_attr_by_column(
+ state, dict_, mapper.version_id_col
+ )
else:
update_version_id = None
- yield (
- state, dict_, mapper, connection, update_version_id)
+ yield (state, dict_, mapper, connection, update_version_id)
def _collect_insert_commands(
- table, states_to_insert,
- bulk=False, return_defaults=False, render_nulls=False):
+ table,
+ states_to_insert,
+ bulk=False,
+ return_defaults=False,
+ render_nulls=False,
+):
"""Identify sets of values to use in INSERT statements for a
list of states.
@@ -400,10 +479,16 @@ def _collect_insert_commands(
col = propkey_to_col[propkey]
if value is None and col not in eval_none and not render_nulls:
continue
- elif not bulk and hasattr(value, '__clause_element__') or \
- isinstance(value, sql.ClauseElement):
- value_params[col.key] = value.__clause_element__() \
- if hasattr(value, '__clause_element__') else value
+ elif (
+ not bulk
+ and hasattr(value, "__clause_element__")
+ or isinstance(value, sql.ClauseElement)
+ ):
+ value_params[col.key] = (
+ value.__clause_element__()
+ if hasattr(value, "__clause_element__")
+ else value
+ )
else:
params[col.key] = value
@@ -414,8 +499,11 @@ def _collect_insert_commands(
# which might be worth removing, as it should not be necessary
# and also produces confusion, given that "missing" and None
# now have distinct meanings
- for colkey in mapper._insert_cols_as_none[table].\
- difference(params).difference(value_params):
+ for colkey in (
+ mapper._insert_cols_as_none[table]
+ .difference(params)
+ .difference(value_params)
+ ):
params[colkey] = None
if not bulk or return_defaults:
@@ -424,28 +512,38 @@ def _collect_insert_commands(
has_all_pks = mapper._pk_keys_by_table[table].issubset(params)
if mapper.base_mapper.eager_defaults:
- has_all_defaults = mapper._server_default_cols[table].\
- issubset(params)
+ has_all_defaults = mapper._server_default_cols[table].issubset(
+ params
+ )
else:
has_all_defaults = True
else:
has_all_defaults = has_all_pks = True
- if mapper.version_id_generator is not False \
- and mapper.version_id_col is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]:
- params[mapper.version_id_col.key] = \
- mapper.version_id_generator(None)
+ if (
+ mapper.version_id_generator is not False
+ and mapper.version_id_col is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ ):
+ params[mapper.version_id_col.key] = mapper.version_id_generator(
+ None
+ )
yield (
- state, state_dict, params, mapper,
- connection, value_params, has_all_pks,
- has_all_defaults)
+ state,
+ state_dict,
+ params,
+ mapper,
+ connection,
+ value_params,
+ has_all_pks,
+ has_all_defaults,
+ )
def _collect_update_commands(
- uowtransaction, table, states_to_update,
- bulk=False):
+ uowtransaction, table, states_to_update, bulk=False
+):
"""Identify sets of values to use in UPDATE statements for a
list of states.
@@ -457,8 +555,13 @@ def _collect_update_commands(
"""
- for state, state_dict, mapper, connection, \
- update_version_id in states_to_update:
+ for (
+ state,
+ state_dict,
+ mapper,
+ connection,
+ update_version_id,
+ ) in states_to_update:
if table not in mapper._pks_by_table:
continue
@@ -474,36 +577,48 @@ def _collect_update_commands(
# look at mapper attribute keys for pk
params = dict(
(propkey_to_col[propkey].key, state_dict[propkey])
- for propkey in
- set(propkey_to_col).intersection(state_dict).difference(
- mapper._pk_attr_keys_by_table[table])
+ for propkey in set(propkey_to_col)
+ .intersection(state_dict)
+ .difference(mapper._pk_attr_keys_by_table[table])
)
has_all_defaults = True
else:
params = {}
for propkey in set(propkey_to_col).intersection(
- state.committed_state):
+ state.committed_state
+ ):
value = state_dict[propkey]
col = propkey_to_col[propkey]
- if hasattr(value, '__clause_element__') or \
- isinstance(value, sql.ClauseElement):
- value_params[col] = value.__clause_element__() \
- if hasattr(value, '__clause_element__') else value
+ if hasattr(value, "__clause_element__") or isinstance(
+ value, sql.ClauseElement
+ ):
+ value_params[col] = (
+ value.__clause_element__()
+ if hasattr(value, "__clause_element__")
+ else value
+ )
# guard against values that generate non-__nonzero__
# objects for __eq__()
- elif state.manager[propkey].impl.is_equal(
- value, state.committed_state[propkey]) is not True:
+ elif (
+ state.manager[propkey].impl.is_equal(
+ value, state.committed_state[propkey]
+ )
+ is not True
+ ):
params[col.key] = value
if mapper.base_mapper.eager_defaults:
- has_all_defaults = mapper._server_onupdate_default_cols[table].\
- issubset(params)
+ has_all_defaults = mapper._server_onupdate_default_cols[
+ table
+ ].issubset(params)
else:
has_all_defaults = True
- if update_version_id is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]:
+ if (
+ update_version_id is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ ):
if not bulk and not (params or value_params):
# HACK: check for history in other tables, in case the
@@ -511,10 +626,9 @@ def _collect_update_commands(
# where the version_id_col is. This logic was lost
# from 0.9 -> 1.0.0 and restored in 1.0.6.
for prop in mapper._columntoproperty.values():
- history = (
- state.manager[prop.key].impl.get_history(
- state, state_dict,
- attributes.PASSIVE_NO_INITIALIZE))
+ history = state.manager[prop.key].impl.get_history(
+ state, state_dict, attributes.PASSIVE_NO_INITIALIZE
+ )
if history.added:
break
else:
@@ -525,8 +639,9 @@ def _collect_update_commands(
no_params = not params and not value_params
params[col._label] = update_version_id
- if (bulk or col.key not in params) and \
- mapper.version_id_generator is not False:
+ if (
+ bulk or col.key not in params
+ ) and mapper.version_id_generator is not False:
val = mapper.version_id_generator(update_version_id)
params[col.key] = val
elif mapper.version_id_generator is False and no_params:
@@ -545,9 +660,9 @@ def _collect_update_commands(
# look at mapper attribute keys for pk
pk_params = dict(
(propkey_to_col[propkey]._label, state_dict.get(propkey))
- for propkey in
- set(propkey_to_col).
- intersection(mapper._pk_attr_keys_by_table[table])
+ for propkey in set(propkey_to_col).intersection(
+ mapper._pk_attr_keys_by_table[table]
+ )
)
else:
pk_params = {}
@@ -555,12 +670,15 @@ def _collect_update_commands(
propkey = mapper._columntoproperty[col].key
history = state.manager[propkey].impl.get_history(
- state, state_dict, attributes.PASSIVE_OFF)
+ state, state_dict, attributes.PASSIVE_OFF
+ )
if history.added:
- if not history.deleted or \
- ("pk_cascaded", state, col) in \
- uowtransaction.attributes:
+ if (
+ not history.deleted
+ or ("pk_cascaded", state, col)
+ in uowtransaction.attributes
+ ):
pk_params[col._label] = history.added[0]
params.pop(col.key, None)
else:
@@ -573,24 +691,38 @@ def _collect_update_commands(
if pk_params[col._label] is None:
raise orm_exc.FlushError(
"Can't update table %s using NULL for primary "
- "key value on column %s" % (table, col))
+ "key value on column %s" % (table, col)
+ )
if params or value_params:
params.update(pk_params)
yield (
- state, state_dict, params, mapper,
- connection, value_params, has_all_defaults, has_all_pks)
+ state,
+ state_dict,
+ params,
+ mapper,
+ connection,
+ value_params,
+ has_all_defaults,
+ has_all_pks,
+ )
-def _collect_post_update_commands(base_mapper, uowtransaction, table,
- states_to_update, post_update_cols):
+def _collect_post_update_commands(
+ base_mapper, uowtransaction, table, states_to_update, post_update_cols
+):
"""Identify sets of values to use in UPDATE statements for a
list of states within a post_update operation.
"""
- for state, state_dict, mapper, connection, \
- update_version_id in states_to_update:
+ for (
+ state,
+ state_dict,
+ mapper,
+ connection,
+ update_version_id,
+ ) in states_to_update:
# assert table in mapper._pks_by_table
@@ -600,100 +732,128 @@ def _collect_post_update_commands(base_mapper, uowtransaction, table,
for col in mapper._cols_by_table[table]:
if col in pks:
- params[col._label] = \
- mapper._get_state_attr_by_column(
- state,
- state_dict, col, passive=attributes.PASSIVE_OFF)
+ params[col._label] = mapper._get_state_attr_by_column(
+ state, state_dict, col, passive=attributes.PASSIVE_OFF
+ )
elif col in post_update_cols or col.onupdate is not None:
prop = mapper._columntoproperty[col]
history = state.manager[prop.key].impl.get_history(
- state, state_dict,
- attributes.PASSIVE_NO_INITIALIZE)
+ state, state_dict, attributes.PASSIVE_NO_INITIALIZE
+ )
if history.added:
value = history.added[0]
params[col.key] = value
hasdata = True
if hasdata:
- if update_version_id is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]:
+ if (
+ update_version_id is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ ):
col = mapper.version_id_col
params[col._label] = update_version_id
- if bool(state.key) and col.key not in params and \
- mapper.version_id_generator is not False:
+ if (
+ bool(state.key)
+ and col.key not in params
+ and mapper.version_id_generator is not False
+ ):
val = mapper.version_id_generator(update_version_id)
params[col.key] = val
yield state, state_dict, mapper, connection, params
-def _collect_delete_commands(base_mapper, uowtransaction, table,
- states_to_delete):
+def _collect_delete_commands(
+ base_mapper, uowtransaction, table, states_to_delete
+):
"""Identify values to use in DELETE statements for a list of
states to be deleted."""
- for state, state_dict, mapper, connection, \
- update_version_id in states_to_delete:
+ for (
+ state,
+ state_dict,
+ mapper,
+ connection,
+ update_version_id,
+ ) in states_to_delete:
if table not in mapper._pks_by_table:
continue
params = {}
for col in mapper._pks_by_table[table]:
- params[col.key] = \
- value = \
- mapper._get_committed_state_attr_by_column(
- state, state_dict, col)
+ params[
+ col.key
+ ] = value = mapper._get_committed_state_attr_by_column(
+ state, state_dict, col
+ )
if value is None:
raise orm_exc.FlushError(
"Can't delete from table %s "
"using NULL for primary "
- "key value on column %s" % (table, col))
+ "key value on column %s" % (table, col)
+ )
- if update_version_id is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]:
+ if (
+ update_version_id is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ ):
params[mapper.version_id_col.key] = update_version_id
yield params, connection
-def _emit_update_statements(base_mapper, uowtransaction,
- cached_connections, mapper, table, update,
- bookkeeping=True):
+def _emit_update_statements(
+ base_mapper,
+ uowtransaction,
+ cached_connections,
+ mapper,
+ table,
+ update,
+ bookkeeping=True,
+):
"""Emit UPDATE statements corresponding to value lists collected
by _collect_update_commands()."""
- needs_version_id = mapper.version_id_col is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]
+ needs_version_id = (
+ mapper.version_id_col is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ )
def update_stmt():
clause = sql.and_()
for col in mapper._pks_by_table[table]:
- clause.clauses.append(col == sql.bindparam(col._label,
- type_=col.type))
+ clause.clauses.append(
+ col == sql.bindparam(col._label, type_=col.type)
+ )
if needs_version_id:
clause.clauses.append(
- mapper.version_id_col == sql.bindparam(
+ mapper.version_id_col
+ == sql.bindparam(
mapper.version_id_col._label,
- type_=mapper.version_id_col.type))
+ type_=mapper.version_id_col.type,
+ )
+ )
stmt = table.update(clause)
return stmt
- cached_stmt = base_mapper._memo(('update', table), update_stmt)
-
- for (connection, paramkeys, hasvalue, has_all_defaults, has_all_pks), \
- records in groupby(
- update,
- lambda rec: (
- rec[4], # connection
- set(rec[2]), # set of parameter keys
- bool(rec[5]), # whether or not we have "value" parameters
- rec[6], # has_all_defaults
- rec[7] # has all pks
- )
+ cached_stmt = base_mapper._memo(("update", table), update_stmt)
+
+ for (
+ (connection, paramkeys, hasvalue, has_all_defaults, has_all_pks),
+ records,
+ ) in groupby(
+ update,
+ lambda rec: (
+ rec[4], # connection
+ set(rec[2]), # set of parameter keys
+ bool(rec[5]), # whether or not we have "value" parameters
+ rec[6], # has_all_defaults
+ rec[7], # has all pks
+ ),
):
rows = 0
records = list(records)
@@ -704,8 +864,11 @@ def _emit_update_statements(base_mapper, uowtransaction,
if not has_all_pks:
statement = statement.return_defaults()
return_defaults = True
- elif bookkeeping and not has_all_defaults and \
- mapper.base_mapper.eager_defaults:
+ elif (
+ bookkeeping
+ and not has_all_defaults
+ and mapper.base_mapper.eager_defaults
+ ):
statement = statement.return_defaults()
return_defaults = True
elif mapper.version_id_col is not None:
@@ -718,17 +881,24 @@ def _emit_update_statements(base_mapper, uowtransaction,
else connection.dialect.supports_sane_rowcount_returning
)
- assert_multirow = assert_singlerow and \
- connection.dialect.supports_sane_multi_rowcount
+ assert_multirow = (
+ assert_singlerow
+ and connection.dialect.supports_sane_multi_rowcount
+ )
allow_multirow = has_all_defaults and not needs_version_id
if hasvalue:
- for state, state_dict, params, mapper, \
- connection, value_params, \
- has_all_defaults, has_all_pks in records:
- c = connection.execute(
- statement.values(value_params),
- params)
+ for (
+ state,
+ state_dict,
+ params,
+ mapper,
+ connection,
+ value_params,
+ has_all_defaults,
+ has_all_pks,
+ ) in records:
+ c = connection.execute(statement.values(value_params), params)
if bookkeeping:
_postfetch(
mapper,
@@ -738,17 +908,26 @@ def _emit_update_statements(base_mapper, uowtransaction,
state_dict,
c,
c.context.compiled_parameters[0],
- value_params)
+ value_params,
+ )
rows += c.rowcount
check_rowcount = assert_singlerow
else:
if not allow_multirow:
check_rowcount = assert_singlerow
- for state, state_dict, params, mapper, \
- connection, value_params, has_all_defaults, \
- has_all_pks in records:
- c = cached_connections[connection].\
- execute(statement, params)
+ for (
+ state,
+ state_dict,
+ params,
+ mapper,
+ connection,
+ value_params,
+ has_all_defaults,
+ has_all_pks,
+ ) in records:
+ c = cached_connections[connection].execute(
+ statement, params
+ )
# TODO: why with bookkeeping=False?
if bookkeeping:
@@ -760,24 +939,32 @@ def _emit_update_statements(base_mapper, uowtransaction,
state_dict,
c,
c.context.compiled_parameters[0],
- value_params)
+ value_params,
+ )
rows += c.rowcount
else:
multiparams = [rec[2] for rec in records]
check_rowcount = assert_multirow or (
- assert_singlerow and
- len(multiparams) == 1
+ assert_singlerow and len(multiparams) == 1
)
- c = cached_connections[connection].\
- execute(statement, multiparams)
+ c = cached_connections[connection].execute(
+ statement, multiparams
+ )
rows += c.rowcount
- for state, state_dict, params, mapper, \
- connection, value_params, \
- has_all_defaults, has_all_pks in records:
+ for (
+ state,
+ state_dict,
+ params,
+ mapper,
+ connection,
+ value_params,
+ has_all_defaults,
+ has_all_pks,
+ ) in records:
if bookkeeping:
_postfetch(
mapper,
@@ -787,59 +974,85 @@ def _emit_update_statements(base_mapper, uowtransaction,
state_dict,
c,
c.context.compiled_parameters[0],
- value_params)
+ value_params,
+ )
if check_rowcount:
if rows != len(records):
raise orm_exc.StaleDataError(
"UPDATE statement on table '%s' expected to "
- "update %d row(s); %d were matched." %
- (table.description, len(records), rows))
+ "update %d row(s); %d were matched."
+ % (table.description, len(records), rows)
+ )
elif needs_version_id:
- util.warn("Dialect %s does not support updated rowcount "
- "- versioning cannot be verified." %
- c.dialect.dialect_description)
+ util.warn(
+ "Dialect %s does not support updated rowcount "
+ "- versioning cannot be verified."
+ % c.dialect.dialect_description
+ )
-def _emit_insert_statements(base_mapper, uowtransaction,
- cached_connections, mapper, table, insert,
- bookkeeping=True):
+def _emit_insert_statements(
+ base_mapper,
+ uowtransaction,
+ cached_connections,
+ mapper,
+ table,
+ insert,
+ bookkeeping=True,
+):
"""Emit INSERT statements corresponding to value lists collected
by _collect_insert_commands()."""
- cached_stmt = base_mapper._memo(('insert', table), table.insert)
-
- for (connection, pkeys, hasvalue, has_all_pks, has_all_defaults), \
- records in groupby(
- insert,
- lambda rec: (
- rec[4], # connection
- set(rec[2]), # parameter keys
- bool(rec[5]), # whether we have "value" parameters
- rec[6],
- rec[7])):
+ cached_stmt = base_mapper._memo(("insert", table), table.insert)
+
+ for (
+ (connection, pkeys, hasvalue, has_all_pks, has_all_defaults),
+ records,
+ ) in groupby(
+ insert,
+ lambda rec: (
+ rec[4], # connection
+ set(rec[2]), # parameter keys
+ bool(rec[5]), # whether we have "value" parameters
+ rec[6],
+ rec[7],
+ ),
+ ):
statement = cached_stmt
- if not bookkeeping or \
- (
- has_all_defaults
- or not base_mapper.eager_defaults
- or not connection.dialect.implicit_returning
- ) and has_all_pks and not hasvalue:
+ if (
+ not bookkeeping
+ or (
+ has_all_defaults
+ or not base_mapper.eager_defaults
+ or not connection.dialect.implicit_returning
+ )
+ and has_all_pks
+ and not hasvalue
+ ):
records = list(records)
multiparams = [rec[2] for rec in records]
- c = cached_connections[connection].\
- execute(statement, multiparams)
+ c = cached_connections[connection].execute(statement, multiparams)
if bookkeeping:
- for (state, state_dict, params, mapper_rec,
- conn, value_params, has_all_pks, has_all_defaults), \
- last_inserted_params in \
- zip(records, c.context.compiled_parameters):
+ for (
+ (
+ state,
+ state_dict,
+ params,
+ mapper_rec,
+ conn,
+ value_params,
+ has_all_pks,
+ has_all_defaults,
+ ),
+ last_inserted_params,
+ ) in zip(records, c.context.compiled_parameters):
if state:
_postfetch(
mapper_rec,
@@ -849,7 +1062,8 @@ def _emit_insert_statements(base_mapper, uowtransaction,
state_dict,
c,
last_inserted_params,
- value_params)
+ value_params,
+ )
else:
_postfetch_bulk_save(mapper_rec, state_dict, table)
@@ -859,24 +1073,33 @@ def _emit_insert_statements(base_mapper, uowtransaction,
elif mapper.version_id_col is not None:
statement = statement.return_defaults(mapper.version_id_col)
- for state, state_dict, params, mapper_rec, \
- connection, value_params, \
- has_all_pks, has_all_defaults in records:
+ for (
+ state,
+ state_dict,
+ params,
+ mapper_rec,
+ connection,
+ value_params,
+ has_all_pks,
+ has_all_defaults,
+ ) in records:
if value_params:
result = connection.execute(
- statement.values(value_params),
- params)
+ statement.values(value_params), params
+ )
else:
- result = cached_connections[connection].\
- execute(statement, params)
+ result = cached_connections[connection].execute(
+ statement, params
+ )
primary_key = result.context.inserted_primary_key
if primary_key is not None:
# set primary key attributes
- for pk, col in zip(primary_key,
- mapper._pks_by_table[table]):
+ for pk, col in zip(
+ primary_key, mapper._pks_by_table[table]
+ ):
prop = mapper_rec._columntoproperty[col]
if state_dict.get(prop.key) is None:
state_dict[prop.key] = pk
@@ -890,31 +1113,39 @@ def _emit_insert_statements(base_mapper, uowtransaction,
state_dict,
result,
result.context.compiled_parameters[0],
- value_params)
+ value_params,
+ )
else:
_postfetch_bulk_save(mapper_rec, state_dict, table)
-def _emit_post_update_statements(base_mapper, uowtransaction,
- cached_connections, mapper, table, update):
+def _emit_post_update_statements(
+ base_mapper, uowtransaction, cached_connections, mapper, table, update
+):
"""Emit UPDATE statements corresponding to value lists collected
by _collect_post_update_commands()."""
- needs_version_id = mapper.version_id_col is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]
+ needs_version_id = (
+ mapper.version_id_col is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ )
def update_stmt():
clause = sql.and_()
for col in mapper._pks_by_table[table]:
- clause.clauses.append(col == sql.bindparam(col._label,
- type_=col.type))
+ clause.clauses.append(
+ col == sql.bindparam(col._label, type_=col.type)
+ )
if needs_version_id:
clause.clauses.append(
- mapper.version_id_col == sql.bindparam(
+ mapper.version_id_col
+ == sql.bindparam(
mapper.version_id_col._label,
- type_=mapper.version_id_col.type))
+ type_=mapper.version_id_col.type,
+ )
+ )
stmt = table.update(clause)
@@ -923,17 +1154,15 @@ def _emit_post_update_statements(base_mapper, uowtransaction,
return stmt
- statement = base_mapper._memo(('post_update', table), update_stmt)
+ statement = base_mapper._memo(("post_update", table), update_stmt)
# execute each UPDATE in the order according to the original
# list of states to guarantee row access order, but
# also group them into common (connection, cols) sets
# to support executemany().
for key, records in groupby(
- update, lambda rec: (
- rec[3], # connection
- set(rec[4]), # parameter keys
- )
+ update,
+ lambda rec: (rec[3], set(rec[4])), # connection # parameter keys
):
rows = 0
@@ -945,84 +1174,96 @@ def _emit_post_update_statements(base_mapper, uowtransaction,
if mapper.version_id_col is None
else connection.dialect.supports_sane_rowcount_returning
)
- assert_multirow = assert_singlerow and \
- connection.dialect.supports_sane_multi_rowcount
+ assert_multirow = (
+ assert_singlerow
+ and connection.dialect.supports_sane_multi_rowcount
+ )
allow_multirow = not needs_version_id or assert_multirow
-
if not allow_multirow:
check_rowcount = assert_singlerow
- for state, state_dict, mapper_rec, \
- connection, params in records:
- c = cached_connections[connection].\
- execute(statement, params)
+ for state, state_dict, mapper_rec, connection, params in records:
+ c = cached_connections[connection].execute(statement, params)
_postfetch_post_update(
- mapper_rec, uowtransaction, table, state, state_dict,
- c, c.context.compiled_parameters[0])
+ mapper_rec,
+ uowtransaction,
+ table,
+ state,
+ state_dict,
+ c,
+ c.context.compiled_parameters[0],
+ )
rows += c.rowcount
else:
multiparams = [
- params for
- state, state_dict, mapper_rec, conn, params in records]
+ params
+ for state, state_dict, mapper_rec, conn, params in records
+ ]
check_rowcount = assert_multirow or (
- assert_singlerow and
- len(multiparams) == 1
+ assert_singlerow and len(multiparams) == 1
)
- c = cached_connections[connection].\
- execute(statement, multiparams)
+ c = cached_connections[connection].execute(statement, multiparams)
rows += c.rowcount
- for state, state_dict, mapper_rec, \
- connection, params in records:
+ for state, state_dict, mapper_rec, connection, params in records:
_postfetch_post_update(
- mapper_rec, uowtransaction, table, state, state_dict,
- c, c.context.compiled_parameters[0])
+ mapper_rec,
+ uowtransaction,
+ table,
+ state,
+ state_dict,
+ c,
+ c.context.compiled_parameters[0],
+ )
if check_rowcount:
if rows != len(records):
raise orm_exc.StaleDataError(
"UPDATE statement on table '%s' expected to "
- "update %d row(s); %d were matched." %
- (table.description, len(records), rows))
+ "update %d row(s); %d were matched."
+ % (table.description, len(records), rows)
+ )
elif needs_version_id:
- util.warn("Dialect %s does not support updated rowcount "
- "- versioning cannot be verified." %
- c.dialect.dialect_description)
+ util.warn(
+ "Dialect %s does not support updated rowcount "
+ "- versioning cannot be verified."
+ % c.dialect.dialect_description
+ )
-def _emit_delete_statements(base_mapper, uowtransaction, cached_connections,
- mapper, table, delete):
+def _emit_delete_statements(
+ base_mapper, uowtransaction, cached_connections, mapper, table, delete
+):
"""Emit DELETE statements corresponding to value lists collected
by _collect_delete_commands()."""
- need_version_id = mapper.version_id_col is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]
+ need_version_id = (
+ mapper.version_id_col is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ )
def delete_stmt():
clause = sql.and_()
for col in mapper._pks_by_table[table]:
clause.clauses.append(
- col == sql.bindparam(col.key, type_=col.type))
+ col == sql.bindparam(col.key, type_=col.type)
+ )
if need_version_id:
clause.clauses.append(
- mapper.version_id_col ==
- sql.bindparam(
- mapper.version_id_col.key,
- type_=mapper.version_id_col.type
+ mapper.version_id_col
+ == sql.bindparam(
+ mapper.version_id_col.key, type_=mapper.version_id_col.type
)
)
return table.delete(clause)
- statement = base_mapper._memo(('delete', table), delete_stmt)
- for connection, recs in groupby(
- delete,
- lambda rec: rec[1] # connection
- ):
+ statement = base_mapper._memo(("delete", table), delete_stmt)
+ for connection, recs in groupby(delete, lambda rec: rec[1]): # connection
del_objects = [params for params, connection in recs]
connection = cached_connections[connection]
@@ -1049,9 +1290,10 @@ def _emit_delete_statements(base_mapper, uowtransaction, cached_connections,
else:
util.warn(
"Dialect %s does not support deleted rowcount "
- "- versioning cannot be verified." %
- connection.dialect.dialect_description,
- stacklevel=12)
+ "- versioning cannot be verified."
+ % connection.dialect.dialect_description,
+ stacklevel=12,
+ )
connection.execute(statement, del_objects)
else:
c = connection.execute(statement, del_objects)
@@ -1061,23 +1303,26 @@ def _emit_delete_statements(base_mapper, uowtransaction, cached_connections,
rows_matched = c.rowcount
- if base_mapper.confirm_deleted_rows and \
- rows_matched > -1 and expected != rows_matched:
+ if (
+ base_mapper.confirm_deleted_rows
+ and rows_matched > -1
+ and expected != rows_matched
+ ):
if only_warn:
util.warn(
"DELETE statement on table '%s' expected to "
"delete %d row(s); %d were matched. Please set "
"confirm_deleted_rows=False within the mapper "
- "configuration to prevent this warning." %
- (table.description, expected, rows_matched)
+ "configuration to prevent this warning."
+ % (table.description, expected, rows_matched)
)
else:
raise orm_exc.StaleDataError(
"DELETE statement on table '%s' expected to "
"delete %d row(s); %d were matched. Please set "
"confirm_deleted_rows=False within the mapper "
- "configuration to prevent this warning." %
- (table.description, expected, rows_matched)
+ "configuration to prevent this warning."
+ % (table.description, expected, rows_matched)
)
@@ -1091,13 +1336,16 @@ def _finalize_insert_update_commands(base_mapper, uowtransaction, states):
if mapper._readonly_props:
readonly = state.unmodified_intersection(
[
- p.key for p in mapper._readonly_props
+ p.key
+ for p in mapper._readonly_props
if (
- p.expire_on_flush and
- (not p.deferred or p.key in state.dict)
- ) or (
- not p.expire_on_flush and
- not p.deferred and p.key not in state.dict
+ p.expire_on_flush
+ and (not p.deferred or p.key in state.dict)
+ )
+ or (
+ not p.expire_on_flush
+ and not p.deferred
+ and p.key not in state.dict
)
]
)
@@ -1112,11 +1360,14 @@ def _finalize_insert_update_commands(base_mapper, uowtransaction, states):
if base_mapper.eager_defaults:
toload_now.extend(
state._unloaded_non_object.intersection(
- mapper._server_default_plus_onupdate_propkeys)
+ mapper._server_default_plus_onupdate_propkeys
+ )
)
- if mapper.version_id_col is not None and \
- mapper.version_id_generator is False:
+ if (
+ mapper.version_id_col is not None
+ and mapper.version_id_generator is False
+ ):
if mapper._version_id_prop.key in state.unloaded:
toload_now.extend([mapper._version_id_prop.key])
@@ -1124,8 +1375,10 @@ def _finalize_insert_update_commands(base_mapper, uowtransaction, states):
state.key = base_mapper._identity_key_from_state(state)
loading.load_on_ident(
uowtransaction.session.query(mapper),
- state.key, refresh_state=state,
- only_load_props=toload_now)
+ state.key,
+ refresh_state=state,
+ only_load_props=toload_now,
+ )
# call after_XXX extensions
if not has_identity:
@@ -1133,23 +1386,29 @@ def _finalize_insert_update_commands(base_mapper, uowtransaction, states):
else:
mapper.dispatch.after_update(mapper, connection, state)
- if mapper.version_id_generator is False and \
- mapper.version_id_col is not None:
+ if (
+ mapper.version_id_generator is False
+ and mapper.version_id_col is not None
+ ):
if state_dict[mapper._version_id_prop.key] is None:
raise orm_exc.FlushError(
- "Instance does not contain a non-NULL version value")
+ "Instance does not contain a non-NULL version value"
+ )
-def _postfetch_post_update(mapper, uowtransaction, table,
- state, dict_, result, params):
+def _postfetch_post_update(
+ mapper, uowtransaction, table, state, dict_, result, params
+):
if uowtransaction.is_deleted(state):
return
prefetch_cols = result.context.compiled.prefetch
postfetch_cols = result.context.compiled.postfetch
- if mapper.version_id_col is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]:
+ if (
+ mapper.version_id_col is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ ):
prefetch_cols = list(prefetch_cols) + [mapper.version_id_col]
refresh_flush = bool(mapper.class_manager.dispatch.refresh_flush)
@@ -1164,18 +1423,23 @@ def _postfetch_post_update(mapper, uowtransaction, table,
if refresh_flush and load_evt_attrs:
mapper.class_manager.dispatch.refresh_flush(
- state, uowtransaction, load_evt_attrs)
+ state, uowtransaction, load_evt_attrs
+ )
if postfetch_cols:
- state._expire_attributes(state.dict,
- [mapper._columntoproperty[c].key
- for c in postfetch_cols if c in
- mapper._columntoproperty]
- )
+ state._expire_attributes(
+ state.dict,
+ [
+ mapper._columntoproperty[c].key
+ for c in postfetch_cols
+ if c in mapper._columntoproperty
+ ],
+ )
-def _postfetch(mapper, uowtransaction, table,
- state, dict_, result, params, value_params):
+def _postfetch(
+ mapper, uowtransaction, table, state, dict_, result, params, value_params
+):
"""Expire attributes in need of newly persisted database state,
after an INSERT or UPDATE statement has proceeded for that
state."""
@@ -1184,8 +1448,10 @@ def _postfetch(mapper, uowtransaction, table,
postfetch_cols = result.context.compiled.postfetch
returning_cols = result.context.compiled.returning
- if mapper.version_id_col is not None and \
- mapper.version_id_col in mapper._cols_by_table[table]:
+ if (
+ mapper.version_id_col is not None
+ and mapper.version_id_col in mapper._cols_by_table[table]
+ ):
prefetch_cols = list(prefetch_cols) + [mapper.version_id_col]
refresh_flush = bool(mapper.class_manager.dispatch.refresh_flush)
@@ -1219,23 +1485,32 @@ def _postfetch(mapper, uowtransaction, table,
if refresh_flush and load_evt_attrs:
mapper.class_manager.dispatch.refresh_flush(
- state, uowtransaction, load_evt_attrs)
+ state, uowtransaction, load_evt_attrs
+ )
if postfetch_cols:
- state._expire_attributes(state.dict,
- [mapper._columntoproperty[c].key
- for c in postfetch_cols if c in
- mapper._columntoproperty]
- )
+ state._expire_attributes(
+ state.dict,
+ [
+ mapper._columntoproperty[c].key
+ for c in postfetch_cols
+ if c in mapper._columntoproperty
+ ],
+ )
# synchronize newly inserted ids from one table to the next
# TODO: this still goes a little too often. would be nice to
# have definitive list of "columns that changed" here
for m, equated_pairs in mapper._table_to_equated[table]:
- sync.populate(state, m, state, m,
- equated_pairs,
- uowtransaction,
- mapper.passive_updates)
+ sync.populate(
+ state,
+ m,
+ state,
+ m,
+ equated_pairs,
+ uowtransaction,
+ mapper.passive_updates,
+ )
def _postfetch_bulk_save(mapper, dict_, table):
@@ -1255,8 +1530,7 @@ def _connections_for_states(base_mapper, uowtransaction, states):
# organize individual states with the connection
# to use for update
if uowtransaction.session.connection_callable:
- connection_callable = \
- uowtransaction.session.connection_callable
+ connection_callable = uowtransaction.session.connection_callable
else:
connection = uowtransaction.transaction.connection(base_mapper)
connection_callable = None
@@ -1275,7 +1549,8 @@ def _cached_connection_dict(base_mapper):
return util.PopulateDict(
lambda conn: conn.execution_options(
compiled_cache=base_mapper._compiled_cache
- ))
+ )
+ )
def _sort_states(states):
@@ -1287,9 +1562,12 @@ def _sort_states(states):
except TypeError as err:
raise sa_exc.InvalidRequestError(
"Could not sort objects by primary key; primary key "
- "values must be sortable in Python (was: %s)" % err)
- return sorted(pending, key=operator.attrgetter("insert_order")) + \
- persistent_sorted
+ "values must be sortable in Python (was: %s)" % err
+ )
+ return (
+ sorted(pending, key=operator.attrgetter("insert_order"))
+ + persistent_sorted
+ )
class BulkUD(object):
@@ -1302,21 +1580,22 @@ class BulkUD(object):
def _validate_query_state(self):
for attr, methname, notset, op in (
- ('_limit', 'limit()', None, operator.is_),
- ('_offset', 'offset()', None, operator.is_),
- ('_order_by', 'order_by()', False, operator.is_),
- ('_group_by', 'group_by()', False, operator.is_),
- ('_distinct', 'distinct()', False, operator.is_),
+ ("_limit", "limit()", None, operator.is_),
+ ("_offset", "offset()", None, operator.is_),
+ ("_order_by", "order_by()", False, operator.is_),
+ ("_group_by", "group_by()", False, operator.is_),
+ ("_distinct", "distinct()", False, operator.is_),
(
- '_from_obj',
- 'join(), outerjoin(), select_from(), or from_self()',
- (), operator.eq)
+ "_from_obj",
+ "join(), outerjoin(), select_from(), or from_self()",
+ (),
+ operator.eq,
+ ),
):
if not op(getattr(self.query, attr), notset):
raise sa_exc.InvalidRequestError(
"Can't call Query.update() or Query.delete() "
- "when %s has been called" %
- (methname, )
+ "when %s has been called" % (methname,)
)
@property
@@ -1330,8 +1609,8 @@ class BulkUD(object):
except KeyError:
raise sa_exc.ArgumentError(
"Valid strategies for session synchronization "
- "are %s" % (", ".join(sorted(repr(x)
- for x in lookup))))
+ "are %s" % (", ".join(sorted(repr(x) for x in lookup)))
+ )
else:
return klass(*arg)
@@ -1400,9 +1679,9 @@ class BulkEvaluate(BulkUD):
try:
evaluator_compiler = evaluator.EvaluatorCompiler(target_cls)
if query.whereclause is not None:
- eval_condition = evaluator_compiler.process(
- query.whereclause)
+ eval_condition = evaluator_compiler.process(query.whereclause)
else:
+
def eval_condition(obj):
return True
@@ -1411,15 +1690,20 @@ class BulkEvaluate(BulkUD):
except evaluator.UnevaluatableError as err:
raise sa_exc.InvalidRequestError(
'Could not evaluate current criteria in Python: "%s". '
- 'Specify \'fetch\' or False for the '
- 'synchronize_session parameter.' % err)
+ "Specify 'fetch' or False for the "
+ "synchronize_session parameter." % err
+ )
# TODO: detect when the where clause is a trivial primary key match
self.matched_objects = [
- obj for (cls, pk, identity_token), obj in
- query.session.identity_map.items()
- if issubclass(cls, target_cls) and
- eval_condition(obj)]
+ obj
+ for (
+ cls,
+ pk,
+ identity_token,
+ ), obj in query.session.identity_map.items()
+ if issubclass(cls, target_cls) and eval_condition(obj)
+ ]
class BulkFetch(BulkUD):
@@ -1430,11 +1714,11 @@ class BulkFetch(BulkUD):
session = query.session
context = query._compile_context()
select_stmt = context.statement.with_only_columns(
- self.primary_table.primary_key)
+ self.primary_table.primary_key
+ )
self.matched_rows = session.execute(
- select_stmt,
- mapper=self.mapper,
- params=query._params).fetchall()
+ select_stmt, mapper=self.mapper, params=query._params
+ ).fetchall()
class BulkUpdate(BulkUD):
@@ -1447,18 +1731,26 @@ class BulkUpdate(BulkUD):
@classmethod
def factory(cls, query, synchronize_session, values, update_kwargs):
- return BulkUD._factory({
- "evaluate": BulkUpdateEvaluate,
- "fetch": BulkUpdateFetch,
- False: BulkUpdate
- }, synchronize_session, query, values, update_kwargs)
+ return BulkUD._factory(
+ {
+ "evaluate": BulkUpdateEvaluate,
+ "fetch": BulkUpdateFetch,
+ False: BulkUpdate,
+ },
+ synchronize_session,
+ query,
+ values,
+ update_kwargs,
+ )
@property
def _resolved_values(self):
values = []
for k, v in (
- self.values.items() if hasattr(self.values, 'items')
- else self.values):
+ self.values.items()
+ if hasattr(self.values, "items")
+ else self.values
+ ):
if self.mapper:
if isinstance(k, util.string_types):
desc = _entity_descriptor(self.mapper, k)
@@ -1478,7 +1770,7 @@ class BulkUpdate(BulkUD):
if isinstance(k, attributes.QueryableAttribute):
values.append((k.key, v))
continue
- elif hasattr(k, '__clause_element__'):
+ elif hasattr(k, "__clause_element__"):
k = k.__clause_element__()
if self.mapper and isinstance(k, expression.ColumnElement):
@@ -1490,18 +1782,22 @@ class BulkUpdate(BulkUD):
values.append((attr.key, v))
else:
raise sa_exc.InvalidRequestError(
- "Invalid expression type: %r" % k)
+ "Invalid expression type: %r" % k
+ )
return values
def _do_exec(self):
values = self._resolved_values
- if not self.update_kwargs.get('preserve_parameter_order', False):
+ if not self.update_kwargs.get("preserve_parameter_order", False):
values = dict(values)
- update_stmt = sql.update(self.primary_table,
- self.context.whereclause, values,
- **self.update_kwargs)
+ update_stmt = sql.update(
+ self.primary_table,
+ self.context.whereclause,
+ values,
+ **self.update_kwargs
+ )
self._execute_stmt(update_stmt)
@@ -1518,15 +1814,18 @@ class BulkDelete(BulkUD):
@classmethod
def factory(cls, query, synchronize_session):
- return BulkUD._factory({
- "evaluate": BulkDeleteEvaluate,
- "fetch": BulkDeleteFetch,
- False: BulkDelete
- }, synchronize_session, query)
+ return BulkUD._factory(
+ {
+ "evaluate": BulkDeleteEvaluate,
+ "fetch": BulkDeleteFetch,
+ False: BulkDelete,
+ },
+ synchronize_session,
+ query,
+ )
def _do_exec(self):
- delete_stmt = sql.delete(self.primary_table,
- self.context.whereclause)
+ delete_stmt = sql.delete(self.primary_table, self.context.whereclause)
self._execute_stmt(delete_stmt)
@@ -1544,32 +1843,33 @@ class BulkUpdateEvaluate(BulkEvaluate, BulkUpdate):
values = self._resolved_values_keys_as_propnames
for key, value in values:
self.value_evaluators[key] = evaluator_compiler.process(
- expression._literal_as_binds(value))
+ expression._literal_as_binds(value)
+ )
def _do_post_synchronize(self):
session = self.query.session
states = set()
evaluated_keys = list(self.value_evaluators.keys())
for obj in self.matched_objects:
- state, dict_ = attributes.instance_state(obj),\
- attributes.instance_dict(obj)
+ state, dict_ = (
+ attributes.instance_state(obj),
+ attributes.instance_dict(obj),
+ )
# only evaluate unmodified attributes
- to_evaluate = state.unmodified.intersection(
- evaluated_keys)
+ to_evaluate = state.unmodified.intersection(evaluated_keys)
for key in to_evaluate:
dict_[key] = self.value_evaluators[key](obj)
- state.manager.dispatch.refresh(
- state, None, to_evaluate)
+ state.manager.dispatch.refresh(state, None, to_evaluate)
state._commit(dict_, list(to_evaluate))
# expire attributes with pending changes
# (there was no autoflush, so they are overwritten)
- state._expire_attributes(dict_,
- set(evaluated_keys).
- difference(to_evaluate))
+ state._expire_attributes(
+ dict_, set(evaluated_keys).difference(to_evaluate)
+ )
states.add(state)
session._register_altered(states)
@@ -1580,8 +1880,8 @@ class BulkDeleteEvaluate(BulkEvaluate, BulkDelete):
def _do_post_synchronize(self):
self.query.session._remove_newly_deleted(
- [attributes.instance_state(obj)
- for obj in self.matched_objects])
+ [attributes.instance_state(obj) for obj in self.matched_objects]
+ )
class BulkUpdateFetch(BulkFetch, BulkUpdate):
@@ -1592,15 +1892,18 @@ class BulkUpdateFetch(BulkFetch, BulkUpdate):
session = self.query.session
target_mapper = self.query._mapper_zero()
- states = set([
- attributes.instance_state(session.identity_map[identity_key])
- for identity_key in [
- target_mapper.identity_key_from_primary_key(
- list(primary_key))
- for primary_key in self.matched_rows
+ states = set(
+ [
+ attributes.instance_state(session.identity_map[identity_key])
+ for identity_key in [
+ target_mapper.identity_key_from_primary_key(
+ list(primary_key)
+ )
+ for primary_key in self.matched_rows
+ ]
+ if identity_key in session.identity_map
]
- if identity_key in session.identity_map
- ])
+ )
values = self._resolved_values_keys_as_propnames
attrib = set(k for k, v in values)
@@ -1622,10 +1925,13 @@ class BulkDeleteFetch(BulkFetch, BulkDelete):
# TODO: inline this and call remove_newly_deleted
# once
identity_key = target_mapper.identity_key_from_primary_key(
- list(primary_key))
+ list(primary_key)
+ )
if identity_key in session.identity_map:
session._remove_newly_deleted(
- [attributes.instance_state(
- session.identity_map[identity_key]
- )]
+ [
+ attributes.instance_state(
+ session.identity_map[identity_key]
+ )
+ ]
)
diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py
index ca47fe7ea..a39cd8703 100644
--- a/lib/sqlalchemy/orm/properties.py
+++ b/lib/sqlalchemy/orm/properties.py
@@ -20,7 +20,7 @@ from .util import _orm_full_deannotate
from .interfaces import PropComparator, StrategizedProperty
-__all__ = ['ColumnProperty']
+__all__ = ["ColumnProperty"]
@log.class_logger
@@ -31,14 +31,27 @@ class ColumnProperty(StrategizedProperty):
"""
- strategy_wildcard_key = 'column'
+ strategy_wildcard_key = "column"
__slots__ = (
- '_orig_columns', 'columns', 'group', 'deferred',
- 'instrument', 'comparator_factory', 'descriptor', 'extension',
- 'active_history', 'expire_on_flush', 'info', 'doc',
- 'strategy_key', '_creation_order', '_is_polymorphic_discriminator',
- '_mapped_by_synonym', '_deferred_column_loader')
+ "_orig_columns",
+ "columns",
+ "group",
+ "deferred",
+ "instrument",
+ "comparator_factory",
+ "descriptor",
+ "extension",
+ "active_history",
+ "expire_on_flush",
+ "info",
+ "doc",
+ "strategy_key",
+ "_creation_order",
+ "_is_polymorphic_discriminator",
+ "_mapped_by_synonym",
+ "_deferred_column_loader",
+ )
def __init__(self, *columns, **kwargs):
r"""Provide a column-level property for use with a Mapper.
@@ -117,26 +130,28 @@ class ColumnProperty(StrategizedProperty):
"""
super(ColumnProperty, self).__init__()
self._orig_columns = [expression._labeled(c) for c in columns]
- self.columns = [expression._labeled(_orm_full_deannotate(c))
- for c in columns]
- self.group = kwargs.pop('group', None)
- self.deferred = kwargs.pop('deferred', False)
- self.instrument = kwargs.pop('_instrument', True)
- self.comparator_factory = kwargs.pop('comparator_factory',
- self.__class__.Comparator)
- self.descriptor = kwargs.pop('descriptor', None)
- self.extension = kwargs.pop('extension', None)
- self.active_history = kwargs.pop('active_history', False)
- self.expire_on_flush = kwargs.pop('expire_on_flush', True)
-
- if 'info' in kwargs:
- self.info = kwargs.pop('info')
-
- if 'doc' in kwargs:
- self.doc = kwargs.pop('doc')
+ self.columns = [
+ expression._labeled(_orm_full_deannotate(c)) for c in columns
+ ]
+ self.group = kwargs.pop("group", None)
+ self.deferred = kwargs.pop("deferred", False)
+ self.instrument = kwargs.pop("_instrument", True)
+ self.comparator_factory = kwargs.pop(
+ "comparator_factory", self.__class__.Comparator
+ )
+ self.descriptor = kwargs.pop("descriptor", None)
+ self.extension = kwargs.pop("extension", None)
+ self.active_history = kwargs.pop("active_history", False)
+ self.expire_on_flush = kwargs.pop("expire_on_flush", True)
+
+ if "info" in kwargs:
+ self.info = kwargs.pop("info")
+
+ if "doc" in kwargs:
+ self.doc = kwargs.pop("doc")
else:
for col in reversed(self.columns):
- doc = getattr(col, 'doc', None)
+ doc = getattr(col, "doc", None)
if doc is not None:
self.doc = doc
break
@@ -145,22 +160,24 @@ class ColumnProperty(StrategizedProperty):
if kwargs:
raise TypeError(
- "%s received unexpected keyword argument(s): %s" % (
- self.__class__.__name__,
- ', '.join(sorted(kwargs.keys()))))
+ "%s received unexpected keyword argument(s): %s"
+ % (self.__class__.__name__, ", ".join(sorted(kwargs.keys())))
+ )
util.set_creation_order(self)
self.strategy_key = (
("deferred", self.deferred),
- ("instrument", self.instrument)
+ ("instrument", self.instrument),
)
@util.dependencies("sqlalchemy.orm.state", "sqlalchemy.orm.strategies")
def _memoized_attr__deferred_column_loader(self, state, strategies):
return state.InstanceState._instance_level_callable_processor(
self.parent.class_manager,
- strategies.LoadDeferredColumns(self.key), self.key)
+ strategies.LoadDeferredColumns(self.key),
+ self.key,
+ )
def __clause_element__(self):
"""Allow the ColumnProperty to work in expression before it is turned
@@ -185,34 +202,50 @@ class ColumnProperty(StrategizedProperty):
self.key,
comparator=self.comparator_factory(self, mapper),
parententity=mapper,
- doc=self.doc
+ doc=self.doc,
)
def do_init(self):
super(ColumnProperty, self).do_init()
- if len(self.columns) > 1 and \
- set(self.parent.primary_key).issuperset(self.columns):
+ if len(self.columns) > 1 and set(self.parent.primary_key).issuperset(
+ self.columns
+ ):
util.warn(
- ("On mapper %s, primary key column '%s' is being combined "
- "with distinct primary key column '%s' in attribute '%s'. "
- "Use explicit properties to give each column its own mapped "
- "attribute name.") % (self.parent, self.columns[1],
- self.columns[0], self.key))
+ (
+ "On mapper %s, primary key column '%s' is being combined "
+ "with distinct primary key column '%s' in attribute '%s'. "
+ "Use explicit properties to give each column its own mapped "
+ "attribute name."
+ )
+ % (self.parent, self.columns[1], self.columns[0], self.key)
+ )
def copy(self):
return ColumnProperty(
deferred=self.deferred,
group=self.group,
active_history=self.active_history,
- *self.columns)
+ *self.columns
+ )
- def _getcommitted(self, state, dict_, column,
- passive=attributes.PASSIVE_OFF):
- return state.get_impl(self.key).\
- get_committed_value(state, dict_, passive=passive)
+ def _getcommitted(
+ self, state, dict_, column, passive=attributes.PASSIVE_OFF
+ ):
+ return state.get_impl(self.key).get_committed_value(
+ state, dict_, passive=passive
+ )
- def merge(self, session, source_state, source_dict, dest_state,
- dest_dict, load, _recursive, _resolve_conflict_map):
+ def merge(
+ self,
+ session,
+ source_state,
+ source_dict,
+ dest_state,
+ dest_dict,
+ load,
+ _recursive,
+ _resolve_conflict_map,
+ ):
if not self.instrument:
return
elif self.key in source_dict:
@@ -225,7 +258,8 @@ class ColumnProperty(StrategizedProperty):
impl.set(dest_state, dest_dict, value, None)
elif dest_state.has_identity and self.key not in dest_dict:
dest_state._expire_attributes(
- dest_dict, [self.key], no_loader=True)
+ dest_dict, [self.key], no_loader=True
+ )
class Comparator(util.MemoizedSlots, PropComparator):
"""Produce boolean, comparison, and other operators for
@@ -246,7 +280,7 @@ class ColumnProperty(StrategizedProperty):
"""
- __slots__ = '__clause_element__', 'info'
+ __slots__ = "__clause_element__", "info"
def _memoized_method___clause_element__(self):
if self.adapter:
@@ -254,9 +288,12 @@ class ColumnProperty(StrategizedProperty):
else:
# no adapter, so we aren't aliased
# assert self._parententity is self._parentmapper
- return self.prop.columns[0]._annotate({
- "parententity": self._parententity,
- "parentmapper": self._parententity})
+ return self.prop.columns[0]._annotate(
+ {
+ "parententity": self._parententity,
+ "parentmapper": self._parententity,
+ }
+ )
def _memoized_attr_info(self):
ce = self.__clause_element__()
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py
index febf627b4..4a55a3247 100644
--- a/lib/sqlalchemy/orm/query.py
+++ b/lib/sqlalchemy/orm/query.py
@@ -22,26 +22,37 @@ database to return iterable result sets.
from itertools import chain
from . import (
- attributes, interfaces, object_mapper, persistence,
- exc as orm_exc, loading
+ attributes,
+ interfaces,
+ object_mapper,
+ persistence,
+ exc as orm_exc,
+ loading,
+)
+from .base import (
+ _entity_descriptor,
+ _is_aliased_class,
+ _is_mapped_class,
+ _orm_columns,
+ _generative,
+ InspectionAttr,
)
-from .base import _entity_descriptor, _is_aliased_class, \
- _is_mapped_class, _orm_columns, _generative, InspectionAttr
from .path_registry import PathRegistry
from .util import (
- AliasedClass, ORMAdapter, join as orm_join, with_parent, aliased,
- _entity_corresponds_to
+ AliasedClass,
+ ORMAdapter,
+ join as orm_join,
+ with_parent,
+ aliased,
+ _entity_corresponds_to,
)
from .. import sql, util, log, exc as sa_exc, inspect, inspection
from ..sql.expression import _interpret_as_from
-from ..sql import (
- util as sql_util,
- expression, visitors
-)
+from ..sql import util as sql_util, expression, visitors
from ..sql.base import ColumnCollection
from . import properties
-__all__ = ['Query', 'QueryContext', 'aliased']
+__all__ = ["Query", "QueryContext", "aliased"]
_path_registry = PathRegistry.root
@@ -192,16 +203,20 @@ class Query(object):
for entity in ent.entities:
if entity not in d:
ext_info = inspect(entity)
- if not ext_info.is_aliased_class and \
- ext_info.mapper.with_polymorphic:
- if ext_info.mapper.mapped_table not in \
- self._polymorphic_adapters:
+ if (
+ not ext_info.is_aliased_class
+ and ext_info.mapper.with_polymorphic
+ ):
+ if (
+ ext_info.mapper.mapped_table
+ not in self._polymorphic_adapters
+ ):
self._mapper_loads_polymorphically_with(
ext_info.mapper,
sql_util.ColumnAdapter(
ext_info.selectable,
- ext_info.mapper._equivalent_columns
- )
+ ext_info.mapper._equivalent_columns,
+ ),
)
aliased_adapter = None
elif ext_info.is_aliased_class:
@@ -209,10 +224,7 @@ class Query(object):
else:
aliased_adapter = None
- d[entity] = (
- ext_info,
- aliased_adapter
- )
+ d[entity] = (ext_info, aliased_adapter)
ent.setup_entity(*d[entity])
def _mapper_loads_polymorphically_with(self, mapper, adapter):
@@ -227,18 +239,21 @@ class Query(object):
for from_obj in obj:
info = inspect(from_obj)
- if hasattr(info, 'mapper') and \
- (info.is_mapper or info.is_aliased_class):
+ if hasattr(info, "mapper") and (
+ info.is_mapper or info.is_aliased_class
+ ):
self._select_from_entity = info
if set_base_alias and not info.is_aliased_class:
raise sa_exc.ArgumentError(
"A selectable (FromClause) instance is "
- "expected when the base alias is being set.")
+ "expected when the base alias is being set."
+ )
fa.append(info.selectable)
elif not info.is_selectable:
raise sa_exc.ArgumentError(
"argument is not a mapped class, mapper, "
- "aliased(), or FromClause instance.")
+ "aliased(), or FromClause instance."
+ )
else:
if isinstance(from_obj, expression.SelectBase):
from_obj = from_obj.alias()
@@ -248,16 +263,21 @@ class Query(object):
self._from_obj = tuple(fa)
- if set_base_alias and \
- len(self._from_obj) == 1 and \
- isinstance(select_from_alias, expression.Alias):
+ if (
+ set_base_alias
+ and len(self._from_obj) == 1
+ and isinstance(select_from_alias, expression.Alias)
+ ):
equivs = self.__all_equivs()
self._from_obj_alias = sql_util.ColumnAdapter(
- self._from_obj[0], equivs)
- elif set_base_alias and \
- len(self._from_obj) == 1 and \
- hasattr(info, "mapper") and \
- info.is_aliased_class:
+ self._from_obj[0], equivs
+ )
+ elif (
+ set_base_alias
+ and len(self._from_obj) == 1
+ and hasattr(info, "mapper")
+ and info.is_aliased_class
+ ):
self._from_obj_alias = info._adapter
def _reset_polymorphic_adapter(self, mapper):
@@ -268,14 +288,14 @@ class Query(object):
def _adapt_polymorphic_element(self, element):
if "parententity" in element._annotations:
- search = element._annotations['parententity']
+ search = element._annotations["parententity"]
alias = self._polymorphic_adapters.get(search, None)
if alias:
return alias.adapt_clause(element)
if isinstance(element, expression.FromClause):
search = element
- elif hasattr(element, 'table'):
+ elif hasattr(element, "table"):
search = element.table
else:
return None
@@ -287,8 +307,8 @@ class Query(object):
def _adapt_col_list(self, cols):
return [
self._adapt_clause(
- expression._literal_as_label_reference(o),
- True, True)
+ expression._literal_as_label_reference(o), True, True
+ )
for o in cols
]
@@ -312,11 +332,7 @@ class Query(object):
if as_filter and self._filter_aliases:
for fa in self._filter_aliases.visitor_iterator:
- adapters.append(
- (
- orm_only, fa.replace
- )
- )
+ adapters.append((orm_only, fa.replace))
if self._from_obj_alias:
# for the "from obj" alias, apply extra rule to the
@@ -326,16 +342,12 @@ class Query(object):
adapters.append(
(
orm_only if self._orm_only_from_obj_alias else False,
- self._from_obj_alias.replace
+ self._from_obj_alias.replace,
)
)
if self._polymorphic_adapters:
- adapters.append(
- (
- orm_only, self._adapt_polymorphic_element
- )
- )
+ adapters.append((orm_only, self._adapt_polymorphic_element))
if not adapters:
return clause
@@ -344,19 +356,17 @@ class Query(object):
for _orm_only, adapter in adapters:
# if 'orm only', look for ORM annotations
# in the element before adapting.
- if not _orm_only or \
- '_orm_adapt' in elem._annotations or \
- "parententity" in elem._annotations:
+ if (
+ not _orm_only
+ or "_orm_adapt" in elem._annotations
+ or "parententity" in elem._annotations
+ ):
e = adapter(elem)
if e is not None:
return e
- return visitors.replacement_traverse(
- clause,
- {},
- replace
- )
+ return visitors.replacement_traverse(clause, {}, replace)
def _query_entity_zero(self):
"""Return the first QueryEntity."""
@@ -371,9 +381,11 @@ class Query(object):
with the first QueryEntity, or alternatively the 'select from'
entity if specified."""
- return self._select_from_entity \
- if self._select_from_entity is not None \
+ return (
+ self._select_from_entity
+ if self._select_from_entity is not None
else self._query_entity_zero().entity_zero
+ )
@property
def _mapper_entities(self):
@@ -382,10 +394,7 @@ class Query(object):
yield ent
def _joinpoint_zero(self):
- return self._joinpoint.get(
- '_joinpoint_entity',
- self._entity_zero()
- )
+ return self._joinpoint.get("_joinpoint_entity", self._entity_zero())
def _bind_mapper(self):
ezero = self._entity_zero()
@@ -400,14 +409,15 @@ class Query(object):
if self._entities != [self._primary_entity]:
raise sa_exc.InvalidRequestError(
"%s() can only be used against "
- "a single mapped class." % methname)
+ "a single mapped class." % methname
+ )
return self._primary_entity.entity_zero
def _only_entity_zero(self, rationale=None):
if len(self._entities) > 1:
raise sa_exc.InvalidRequestError(
- rationale or
- "This operation requires a Query "
+ rationale
+ or "This operation requires a Query "
"against a single mapper."
)
return self._entity_zero()
@@ -420,7 +430,8 @@ class Query(object):
def _get_condition(self):
return self._no_criterion_condition(
- "get", order_by=False, distinct=False)
+ "get", order_by=False, distinct=False
+ )
def _get_existing_condition(self):
self._no_criterion_assertion("get", order_by=False, distinct=False)
@@ -428,14 +439,20 @@ class Query(object):
def _no_criterion_assertion(self, meth, order_by=True, distinct=True):
if not self._enable_assertions:
return
- if self._criterion is not None or \
- self._statement is not None or self._from_obj or \
- self._limit is not None or self._offset is not None or \
- self._group_by or (order_by and self._order_by) or \
- (distinct and self._distinct):
+ if (
+ self._criterion is not None
+ or self._statement is not None
+ or self._from_obj
+ or self._limit is not None
+ or self._offset is not None
+ or self._group_by
+ or (order_by and self._order_by)
+ or (distinct and self._distinct)
+ ):
raise sa_exc.InvalidRequestError(
"Query.%s() being called on a "
- "Query with existing criterion. " % meth)
+ "Query with existing criterion. " % meth
+ )
def _no_criterion_condition(self, meth, order_by=True, distinct=True):
self._no_criterion_assertion(meth, order_by, distinct)
@@ -450,7 +467,8 @@ class Query(object):
if self._order_by:
raise sa_exc.InvalidRequestError(
"Query.%s() being called on a "
- "Query with existing criterion. " % meth)
+ "Query with existing criterion. " % meth
+ )
self._no_criterion_condition(meth)
def _no_statement_condition(self, meth):
@@ -458,8 +476,12 @@ class Query(object):
return
if self._statement is not None:
raise sa_exc.InvalidRequestError(
- ("Query.%s() being called on a Query with an existing full "
- "statement - can't apply criterion.") % meth)
+ (
+ "Query.%s() being called on a Query with an existing full "
+ "statement - can't apply criterion."
+ )
+ % meth
+ )
def _no_limit_offset(self, meth):
if not self._enable_assertions:
@@ -470,15 +492,17 @@ class Query(object):
"or OFFSET applied. To modify the row-limited results of a "
" Query, call from_self() first. "
"Otherwise, call %s() before limit() or offset() "
- "are applied."
- % (meth, meth)
+ "are applied." % (meth, meth)
)
- def _get_options(self, populate_existing=None,
- version_check=None,
- only_load_props=None,
- refresh_state=None,
- identity_token=None):
+ def _get_options(
+ self,
+ populate_existing=None,
+ version_check=None,
+ only_load_props=None,
+ refresh_state=None,
+ identity_token=None,
+ ):
if populate_existing:
self._populate_existing = populate_existing
if version_check:
@@ -507,8 +531,7 @@ class Query(object):
"""
- stmt = self._compile_context(labels=self._with_labels).\
- statement
+ stmt = self._compile_context(labels=self._with_labels).statement
if self._params:
stmt = stmt.params(self._params)
@@ -602,8 +625,9 @@ class Query(object):
:meth:`.HasCTE.cte`
"""
- return self.enable_eagerloads(False).\
- statement.cte(name=name, recursive=recursive)
+ return self.enable_eagerloads(False).statement.cte(
+ name=name, recursive=recursive
+ )
def label(self, name):
"""Return the full SELECT statement represented by this
@@ -678,7 +702,8 @@ class Query(object):
"compatible with %s eager loading. Please "
"specify lazyload('*') or query.enable_eagerloads(False) in "
"order to "
- "proceed with query.yield_per()." % message)
+ "proceed with query.yield_per()." % message
+ )
@_generative()
def with_labels(self):
@@ -752,10 +777,9 @@ class Query(object):
self._current_path = path
@_generative(_no_clauseelement_condition)
- def with_polymorphic(self,
- cls_or_mappers,
- selectable=None,
- polymorphic_on=None):
+ def with_polymorphic(
+ self, cls_or_mappers, selectable=None, polymorphic_on=None
+ ):
"""Load columns for inheriting classes.
:meth:`.Query.with_polymorphic` applies transformations
@@ -783,13 +807,16 @@ class Query(object):
if not self._primary_entity:
raise sa_exc.InvalidRequestError(
- "No primary mapper set up for this Query.")
+ "No primary mapper set up for this Query."
+ )
entity = self._entities[0]._clone()
self._entities = [entity] + self._entities[1:]
- entity.set_with_polymorphic(self,
- cls_or_mappers,
- selectable=selectable,
- polymorphic_on=polymorphic_on)
+ entity.set_with_polymorphic(
+ self,
+ cls_or_mappers,
+ selectable=selectable,
+ polymorphic_on=polymorphic_on,
+ )
@_generative()
def yield_per(self, count):
@@ -858,8 +885,8 @@ class Query(object):
"""
self._yield_per = count
self._execution_options = self._execution_options.union(
- {"stream_results": True,
- "max_row_buffer": count})
+ {"stream_results": True, "max_row_buffer": count}
+ )
def get(self, ident):
"""Return an instance based on the given primary key identifier,
@@ -918,12 +945,16 @@ class Query(object):
:return: The object instance, or ``None``.
"""
- return self._get_impl(
- ident, loading.load_on_pk_identity)
-
- def _identity_lookup(self, mapper, primary_key_identity,
- identity_token=None, passive=attributes.PASSIVE_OFF,
- lazy_loaded_from=None):
+ return self._get_impl(ident, loading.load_on_pk_identity)
+
+ def _identity_lookup(
+ self,
+ mapper,
+ primary_key_identity,
+ identity_token=None,
+ passive=attributes.PASSIVE_OFF,
+ lazy_loaded_from=None,
+ ):
"""Locate an object in the identity map.
Given a primary key identity, constructs an identity key and then
@@ -966,14 +997,13 @@ class Query(object):
"""
key = mapper.identity_key_from_primary_key(
- primary_key_identity, identity_token=identity_token)
- return loading.get_from_identity(
- self.session, key, passive)
+ primary_key_identity, identity_token=identity_token
+ )
+ return loading.get_from_identity(self.session, key, passive)
- def _get_impl(
- self, primary_key_identity, db_load_fn, identity_token=None):
+ def _get_impl(self, primary_key_identity, db_load_fn, identity_token=None):
# convert composite types to individual args
- if hasattr(primary_key_identity, '__composite_values__'):
+ if hasattr(primary_key_identity, "__composite_values__"):
primary_key_identity = primary_key_identity.__composite_values__()
primary_key_identity = util.to_list(primary_key_identity)
@@ -983,16 +1013,19 @@ class Query(object):
if len(primary_key_identity) != len(mapper.primary_key):
raise sa_exc.InvalidRequestError(
"Incorrect number of values in identifier to formulate "
- "primary key for query.get(); primary key columns are %s" %
- ','.join("'%s'" % c for c in mapper.primary_key))
+ "primary key for query.get(); primary key columns are %s"
+ % ",".join("'%s'" % c for c in mapper.primary_key)
+ )
- if not self._populate_existing and \
- not mapper.always_refresh and \
- self._for_update_arg is None:
+ if (
+ not self._populate_existing
+ and not mapper.always_refresh
+ and self._for_update_arg is None
+ ):
instance = self._identity_lookup(
- mapper, primary_key_identity,
- identity_token=identity_token)
+ mapper, primary_key_identity, identity_token=identity_token
+ )
if instance is not None:
self._get_existing_condition()
@@ -1106,17 +1139,20 @@ class Query(object):
mapper = object_mapper(instance)
for prop in mapper.iterate_properties:
- if isinstance(prop, properties.RelationshipProperty) and \
- prop.mapper is entity_zero.mapper:
+ if (
+ isinstance(prop, properties.RelationshipProperty)
+ and prop.mapper is entity_zero.mapper
+ ):
property = prop
break
else:
raise sa_exc.InvalidRequestError(
"Could not locate a property which relates instances "
- "of class '%s' to instances of class '%s'" %
- (
+ "of class '%s' to instances of class '%s'"
+ % (
entity_zero.mapper.class_.__name__,
- instance.__class__.__name__)
+ instance.__class__.__name__,
+ )
)
return self.filter(with_parent(instance, property, entity_zero.entity))
@@ -1323,8 +1359,11 @@ class Query(object):
those being selected.
"""
- fromclause = self.with_labels().enable_eagerloads(False).\
- statement.correlate(None)
+ fromclause = (
+ self.with_labels()
+ .enable_eagerloads(False)
+ .statement.correlate(None)
+ )
q = self._from_selectable(fromclause)
q._enable_single_crit = False
q._select_from_entity = self._entity_zero()
@@ -1339,12 +1378,18 @@ class Query(object):
@_generative()
def _from_selectable(self, fromclause):
for attr in (
- '_statement', '_criterion',
- '_order_by', '_group_by',
- '_limit', '_offset',
- '_joinpath', '_joinpoint',
- '_distinct', '_having',
- '_prefixes', '_suffixes'
+ "_statement",
+ "_criterion",
+ "_order_by",
+ "_group_by",
+ "_limit",
+ "_offset",
+ "_joinpath",
+ "_joinpoint",
+ "_distinct",
+ "_having",
+ "_prefixes",
+ "_suffixes",
):
self.__dict__.pop(attr, None)
self._set_select_from([fromclause], True)
@@ -1369,6 +1414,7 @@ class Query(object):
if not q._yield_per:
q._yield_per = 10
return iter(q)
+
_values = values
def value(self, column):
@@ -1420,10 +1466,11 @@ class Query(object):
# given arg is a FROM clause
self._set_entity_selectables(self._entities[l:])
- @util.pending_deprecation("0.7",
- ":meth:`.add_column` is superseded "
- "by :meth:`.add_columns`",
- False)
+ @util.pending_deprecation(
+ "0.7",
+ ":meth:`.add_column` is superseded " "by :meth:`.add_columns`",
+ False,
+ )
def add_column(self, column):
"""Add a column expression to the list of result columns to be
returned.
@@ -1454,8 +1501,8 @@ class Query(object):
# most MapperOptions write to the '_attributes' dictionary,
# so copy that as well
self._attributes = self._attributes.copy()
- if '_unbound_load_dedupes' not in self._attributes:
- self._attributes['_unbound_load_dedupes'] = set()
+ if "_unbound_load_dedupes" not in self._attributes:
+ self._attributes["_unbound_load_dedupes"] = set()
opts = tuple(util.flatten_iterator(args))
self._with_options = self._with_options + opts
if conditional:
@@ -1487,7 +1534,7 @@ class Query(object):
return fn(self)
@_generative()
- def with_hint(self, selectable, text, dialect_name='*'):
+ def with_hint(self, selectable, text, dialect_name="*"):
"""Add an indexing or other executional context
hint for the given entity or selectable to
this :class:`.Query`.
@@ -1508,7 +1555,7 @@ class Query(object):
self._with_hints += ((selectable, text, dialect_name),)
- def with_statement_hint(self, text, dialect_name='*'):
+ def with_statement_hint(self, text, dialect_name="*"):
"""add a statement hint to this :class:`.Select`.
This method is similar to :meth:`.Select.with_hint` except that
@@ -1570,8 +1617,14 @@ class Query(object):
self._for_update_arg = LockmodeArg.parse_legacy_query(mode)
@_generative()
- def with_for_update(self, read=False, nowait=False, of=None,
- skip_locked=False, key_share=False):
+ def with_for_update(
+ self,
+ read=False,
+ nowait=False,
+ of=None,
+ skip_locked=False,
+ key_share=False,
+ ):
"""return a new :class:`.Query` with the specified options for the
``FOR UPDATE`` clause.
@@ -1599,9 +1652,13 @@ class Query(object):
full argument and behavioral description.
"""
- self._for_update_arg = LockmodeArg(read=read, nowait=nowait, of=of,
- skip_locked=skip_locked,
- key_share=key_share)
+ self._for_update_arg = LockmodeArg(
+ read=read,
+ nowait=nowait,
+ of=of,
+ skip_locked=skip_locked,
+ key_share=key_share,
+ )
@_generative()
def params(self, *args, **kwargs):
@@ -1619,7 +1676,8 @@ class Query(object):
elif len(args) > 0:
raise sa_exc.ArgumentError(
"params() takes zero or one positional argument, "
- "which is a dictionary.")
+ "which is a dictionary."
+ )
self._params = self._params.copy()
self._params.update(kwargs)
@@ -1683,8 +1741,10 @@ class Query(object):
"""
- clauses = [_entity_descriptor(self._joinpoint_zero(), key) == value
- for key, value in kwargs.items()]
+ clauses = [
+ _entity_descriptor(self._joinpoint_zero(), key) == value
+ for key, value in kwargs.items()
+ ]
return self.filter(sql.and_(*clauses))
@_generative(_no_statement_condition, _no_limit_offset)
@@ -1704,7 +1764,7 @@ class Query(object):
if len(criterion) == 1:
if criterion[0] is False:
- if '_order_by' in self.__dict__:
+ if "_order_by" in self.__dict__:
self._order_by = False
return
if criterion[0] is None:
@@ -1765,11 +1825,13 @@ class Query(object):
criterion = expression._expression_literal_as_text(criterion)
- if criterion is not None and \
- not isinstance(criterion, sql.ClauseElement):
+ if criterion is not None and not isinstance(
+ criterion, sql.ClauseElement
+ ):
raise sa_exc.ArgumentError(
"having() argument must be of type "
- "sqlalchemy.sql.ClauseElement or string")
+ "sqlalchemy.sql.ClauseElement or string"
+ )
criterion = self._adapt_clause(criterion, True, True)
@@ -2122,17 +2184,23 @@ class Query(object):
SQLAlchemy versions was the primary ORM-level joining interface.
"""
- aliased, from_joinpoint, isouter, full = kwargs.pop('aliased', False),\
- kwargs.pop('from_joinpoint', False),\
- kwargs.pop('isouter', False),\
- kwargs.pop('full', False)
+ aliased, from_joinpoint, isouter, full = (
+ kwargs.pop("aliased", False),
+ kwargs.pop("from_joinpoint", False),
+ kwargs.pop("isouter", False),
+ kwargs.pop("full", False),
+ )
if kwargs:
- raise TypeError("unknown arguments: %s" %
- ', '.join(sorted(kwargs)))
- return self._join(props,
- outerjoin=isouter, full=full,
- create_aliases=aliased,
- from_joinpoint=from_joinpoint)
+ raise TypeError(
+ "unknown arguments: %s" % ", ".join(sorted(kwargs))
+ )
+ return self._join(
+ props,
+ outerjoin=isouter,
+ full=full,
+ create_aliases=aliased,
+ from_joinpoint=from_joinpoint,
+ )
def outerjoin(self, *props, **kwargs):
"""Create a left outer join against this ``Query`` object's criterion
@@ -2141,25 +2209,32 @@ class Query(object):
Usage is the same as the ``join()`` method.
"""
- aliased, from_joinpoint, full = kwargs.pop('aliased', False), \
- kwargs.pop('from_joinpoint', False), \
- kwargs.pop('full', False)
+ aliased, from_joinpoint, full = (
+ kwargs.pop("aliased", False),
+ kwargs.pop("from_joinpoint", False),
+ kwargs.pop("full", False),
+ )
if kwargs:
- raise TypeError("unknown arguments: %s" %
- ', '.join(sorted(kwargs)))
- return self._join(props,
- outerjoin=True, full=full, create_aliases=aliased,
- from_joinpoint=from_joinpoint)
+ raise TypeError(
+ "unknown arguments: %s" % ", ".join(sorted(kwargs))
+ )
+ return self._join(
+ props,
+ outerjoin=True,
+ full=full,
+ create_aliases=aliased,
+ from_joinpoint=from_joinpoint,
+ )
def _update_joinpoint(self, jp):
self._joinpoint = jp
# copy backwards to the root of the _joinpath
# dict, so that no existing dict in the path is mutated
- while 'prev' in jp:
- f, prev = jp['prev']
+ while "prev" in jp:
+ f, prev = jp["prev"]
prev = prev.copy()
prev[f] = jp
- jp['prev'] = (f, prev)
+ jp["prev"] = (f, prev)
jp = prev
self._joinpath = jp
@@ -2173,11 +2248,16 @@ class Query(object):
if not from_joinpoint:
self._reset_joinpoint()
- if len(keys) == 2 and \
- isinstance(keys[0], (expression.FromClause,
- type, AliasedClass)) and \
- isinstance(keys[1], (str, expression.ClauseElement,
- interfaces.PropComparator)):
+ if (
+ len(keys) == 2
+ and isinstance(
+ keys[0], (expression.FromClause, type, AliasedClass)
+ )
+ and isinstance(
+ keys[1],
+ (str, expression.ClauseElement, interfaces.PropComparator),
+ )
+ ):
# detect 2-arg form of join and
# convert to a tuple.
keys = (keys,)
@@ -2202,20 +2282,22 @@ class Query(object):
# is a little bit of legacy behavior still at work here
# which means they might be in either order.
if isinstance(
- arg1, (interfaces.PropComparator, util.string_types)):
+ arg1, (interfaces.PropComparator, util.string_types)
+ ):
right, onclause = arg2, arg1
else:
right, onclause = arg1, arg2
if onclause is None:
r_info = inspect(right)
- if not r_info.is_selectable and not hasattr(r_info, 'mapper'):
+ if not r_info.is_selectable and not hasattr(r_info, "mapper"):
raise sa_exc.ArgumentError(
"Expected mapped entity or "
- "selectable/table as join target")
+ "selectable/table as join target"
+ )
if isinstance(onclause, interfaces.PropComparator):
- of_type = getattr(onclause, '_of_type', None)
+ of_type = getattr(onclause, "_of_type", None)
else:
of_type = None
@@ -2234,12 +2316,13 @@ class Query(object):
# to work with the aliased=True flag, which is also something
# that probably shouldn't exist on join() due to its high
# complexity/usefulness ratio
- elif from_joinpoint and \
- isinstance(onclause, interfaces.PropComparator):
+ elif from_joinpoint and isinstance(
+ onclause, interfaces.PropComparator
+ ):
jp0 = self._joinpoint_zero()
info = inspect(jp0)
- if getattr(info, 'mapper', None) is onclause._parententity:
+ if getattr(info, "mapper", None) is onclause._parententity:
onclause = _entity_descriptor(jp0, onclause.key)
if isinstance(onclause, interfaces.PropComparator):
@@ -2256,8 +2339,7 @@ class Query(object):
alias = self._polymorphic_adapters.get(left, None)
# could be None or could be ColumnAdapter also
- if isinstance(alias, ORMAdapter) and \
- alias.mapper.isa(left):
+ if isinstance(alias, ORMAdapter) and alias.mapper.isa(left):
left = alias.aliased_class
onclause = getattr(left, onclause.key)
@@ -2278,14 +2360,15 @@ class Query(object):
# and then mutate the child, which might be
# shared by a different query object.
jp = self._joinpoint[edge].copy()
- jp['prev'] = (edge, self._joinpoint)
+ jp["prev"] = (edge, self._joinpoint)
self._update_joinpoint(jp)
# warn only on the last element of the list
if idx == len(keylist) - 1:
util.warn(
"Pathed join target %s has already "
- "been joined to; skipping" % prop)
+ "been joined to; skipping" % prop
+ )
continue
else:
# no descriptor/property given; we will need to figure out
@@ -2295,13 +2378,12 @@ class Query(object):
# figure out the final "left" and "right" sides and create an
# ORMJoin to add to our _from_obj tuple
self._join_left_to_right(
- left, right, onclause, prop, create_aliases,
- outerjoin, full
+ left, right, onclause, prop, create_aliases, outerjoin, full
)
def _join_left_to_right(
- self, left, right, onclause, prop,
- create_aliases, outerjoin, full):
+ self, left, right, onclause, prop, create_aliases, outerjoin, full
+ ):
"""given raw "left", "right", "onclause" parameters consumed from
a particular key within _join(), add a real ORMJoin object to
our _from_obj list (or augment an existing one)
@@ -2315,15 +2397,17 @@ class Query(object):
# figure out the best "left" side based on our existing froms /
# entities
assert prop is None
- left, replace_from_obj_index, use_entity_index = \
- self._join_determine_implicit_left_side(left, right, onclause)
+ left, replace_from_obj_index, use_entity_index = self._join_determine_implicit_left_side(
+ left, right, onclause
+ )
else:
# left is given via a relationship/name. Determine where in our
# "froms" list it should be spliced/appended as well as what
# existing entity it corresponds to.
assert prop is not None
- replace_from_obj_index, use_entity_index = \
- self._join_place_explicit_left_side(left)
+ replace_from_obj_index, use_entity_index = self._join_place_explicit_left_side(
+ left
+ )
# this should never happen because we would not have found a place
# to join on
@@ -2333,7 +2417,7 @@ class Query(object):
# a lot of things can be wrong with it. handle all that and
# get back the new effective "right" side
r_info, right, onclause = self._join_check_and_adapt_right_side(
- left, right, onclause, prop, create_aliases,
+ left, right, onclause, prop, create_aliases
)
if replace_from_obj_index is not None:
@@ -2342,11 +2426,18 @@ class Query(object):
left_clause = self._from_obj[replace_from_obj_index]
self._from_obj = (
- self._from_obj[:replace_from_obj_index] +
- (orm_join(
- left_clause, right,
- onclause, isouter=outerjoin, full=full), ) +
- self._from_obj[replace_from_obj_index + 1:])
+ self._from_obj[:replace_from_obj_index]
+ + (
+ orm_join(
+ left_clause,
+ right,
+ onclause,
+ isouter=outerjoin,
+ full=full,
+ ),
+ )
+ + self._from_obj[replace_from_obj_index + 1 :]
+ )
else:
# add a new element to the self._from_obj list
@@ -2358,8 +2449,8 @@ class Query(object):
self._from_obj = self._from_obj + (
orm_join(
- left_clause, right, onclause,
- isouter=outerjoin, full=full),
+ left_clause, right, onclause, isouter=outerjoin, full=full
+ ),
)
def _join_determine_implicit_left_side(self, left, right, onclause):
@@ -2388,8 +2479,8 @@ class Query(object):
# join has to connect to one of those FROMs.
indexes = sql_util.find_left_clause_to_join_from(
- self._from_obj,
- r_info.selectable, onclause)
+ self._from_obj, r_info.selectable, onclause
+ )
if len(indexes) == 1:
replace_from_obj_index = indexes[0]
@@ -2399,12 +2490,13 @@ class Query(object):
"Can't determine which FROM clause to join "
"from, there are multiple FROMS which can "
"join to this entity. Try adding an explicit ON clause "
- "to help resolve the ambiguity.")
+ "to help resolve the ambiguity."
+ )
else:
raise sa_exc.InvalidRequestError(
"Don't know how to join to %s; please use "
"an ON clause to more clearly establish the left "
- "side of this join" % (right, )
+ "side of this join" % (right,)
)
elif self._entities:
@@ -2430,7 +2522,8 @@ class Query(object):
all_clauses = list(potential.keys())
indexes = sql_util.find_left_clause_to_join_from(
- all_clauses, r_info.selectable, onclause)
+ all_clauses, r_info.selectable, onclause
+ )
if len(indexes) == 1:
use_entity_index, left = potential[all_clauses[indexes[0]]]
@@ -2439,18 +2532,20 @@ class Query(object):
"Can't determine which FROM clause to join "
"from, there are multiple FROMS which can "
"join to this entity. Try adding an explicit ON clause "
- "to help resolve the ambiguity.")
+ "to help resolve the ambiguity."
+ )
else:
raise sa_exc.InvalidRequestError(
"Don't know how to join to %s; please use "
"an ON clause to more clearly establish the left "
- "side of this join" % (right, )
+ "side of this join" % (right,)
)
else:
raise sa_exc.InvalidRequestError(
"No entities to join from; please use "
"select_from() to establish the left "
- "entity/selectable of this join")
+ "entity/selectable of this join"
+ )
return left, replace_from_obj_index, use_entity_index
@@ -2484,13 +2579,15 @@ class Query(object):
l_info = inspect(left)
if self._from_obj:
indexes = sql_util.find_left_clause_that_matches_given(
- self._from_obj, l_info.selectable)
+ self._from_obj, l_info.selectable
+ )
if len(indexes) > 1:
raise sa_exc.InvalidRequestError(
"Can't identify which entity in which to assign the "
"left side of this join. Please use a more specific "
- "ON clause.")
+ "ON clause."
+ )
# have an index, means the left side is already present in
# an existing FROM in the self._from_obj tuple
@@ -2504,8 +2601,11 @@ class Query(object):
# self._from_obj tuple. Determine if this left side matches up
# with existing mapper entities, in which case we want to apply the
# aliasing / adaptation rules present on that entity if any
- if replace_from_obj_index is None and \
- self._entities and hasattr(l_info, 'mapper'):
+ if (
+ replace_from_obj_index is None
+ and self._entities
+ and hasattr(l_info, "mapper")
+ ):
for idx, ent in enumerate(self._entities):
# TODO: should we be checking for multiple mapper entities
# matching?
@@ -2516,7 +2616,8 @@ class Query(object):
return replace_from_obj_index, use_entity_index
def _join_check_and_adapt_right_side(
- self, left, right, onclause, prop, create_aliases):
+ self, left, right, onclause, prop, create_aliases
+ ):
"""transform the "right" side of the join as well as the onclause
according to polymorphic mapping translations, aliasing on the query
or on the join, special cases where the right and left side have
@@ -2533,30 +2634,37 @@ class Query(object):
# if the target is a joined inheritance mapping,
# be more liberal about auto-aliasing.
if right_mapper and (
- right_mapper.with_polymorphic or
- isinstance(right_mapper.mapped_table, expression.Join)
+ right_mapper.with_polymorphic
+ or isinstance(right_mapper.mapped_table, expression.Join)
):
for from_obj in self._from_obj or [l_info.selectable]:
if sql_util.selectables_overlap(
- l_info.selectable, from_obj) and \
- sql_util.selectables_overlap(
- from_obj, r_info.selectable):
+ l_info.selectable, from_obj
+ ) and sql_util.selectables_overlap(
+ from_obj, r_info.selectable
+ ):
overlap = True
break
- if (overlap or not create_aliases) and \
- l_info.selectable is r_info.selectable:
+ if (
+ overlap or not create_aliases
+ ) and l_info.selectable is r_info.selectable:
raise sa_exc.InvalidRequestError(
- "Can't join table/selectable '%s' to itself" %
- l_info.selectable)
+ "Can't join table/selectable '%s' to itself"
+ % l_info.selectable
+ )
- right_mapper, right_selectable, right_is_aliased = \
- getattr(r_info, 'mapper', None), \
- r_info.selectable, \
- getattr(r_info, 'is_aliased_class', False)
+ right_mapper, right_selectable, right_is_aliased = (
+ getattr(r_info, "mapper", None),
+ r_info.selectable,
+ getattr(r_info, "is_aliased_class", False),
+ )
- if right_mapper and prop and \
- not right_mapper.common_parent(prop.mapper):
+ if (
+ right_mapper
+ and prop
+ and not right_mapper.common_parent(prop.mapper)
+ ):
raise sa_exc.InvalidRequestError(
"Join target %s does not correspond to "
"the right side of join condition %s" % (right, onclause)
@@ -2564,8 +2672,8 @@ class Query(object):
# _join_entities is used as a hint for single-table inheritance
# purposes at the moment
- if hasattr(r_info, 'mapper'):
- self._join_entities += (r_info, )
+ if hasattr(r_info, "mapper"):
+ self._join_entities += (r_info,)
if not right_mapper and prop:
right_mapper = prop.mapper
@@ -2579,12 +2687,14 @@ class Query(object):
right = self._adapt_clause(right, True, False)
if right_mapper and right is right_selectable:
- if not right_selectable.is_derived_from(
- right_mapper.mapped_table):
+ if not right_selectable.is_derived_from(right_mapper.mapped_table):
raise sa_exc.InvalidRequestError(
- "Selectable '%s' is not derived from '%s'" %
- (right_selectable.description,
- right_mapper.mapped_table.description))
+ "Selectable '%s' is not derived from '%s'"
+ % (
+ right_selectable.description,
+ right_mapper.mapped_table.description,
+ )
+ )
if isinstance(right_selectable, expression.SelectBase):
# TODO: this isn't even covered now!
@@ -2593,16 +2703,20 @@ class Query(object):
right = aliased(right_mapper, right_selectable)
- aliased_entity = right_mapper and \
- not right_is_aliased and \
- (
- right_mapper.with_polymorphic and isinstance(
- right_mapper._with_polymorphic_selectable,
- expression.Alias) or overlap
+ aliased_entity = (
+ right_mapper
+ and not right_is_aliased
+ and (
+ right_mapper.with_polymorphic
+ and isinstance(
+ right_mapper._with_polymorphic_selectable, expression.Alias
+ )
+ or overlap
# test for overlap:
# orm/inheritance/relationships.py
# SelfReferentialM2MTest
)
+ )
if not need_adapter and (create_aliases or aliased_entity):
right = aliased(right, flat=True)
@@ -2614,9 +2728,11 @@ class Query(object):
if need_adapter:
self._filter_aliases = ORMAdapter(
right,
- equivalents=right_mapper and
- right_mapper._equivalent_columns or {},
- chain_to=self._filter_aliases)
+ equivalents=right_mapper
+ and right_mapper._equivalent_columns
+ or {},
+ chain_to=self._filter_aliases,
+ )
# if the onclause is a ClauseElement, adapt it with any
# adapters that are in place right now
@@ -2631,20 +2747,21 @@ class Query(object):
self._mapper_loads_polymorphically_with(
right_mapper,
ORMAdapter(
- right,
- equivalents=right_mapper._equivalent_columns
- )
+ right, equivalents=right_mapper._equivalent_columns
+ ),
)
# if joining on a MapperProperty path,
# track the path to prevent redundant joins
if not create_aliases and prop:
- self._update_joinpoint({
- '_joinpoint_entity': right,
- 'prev': ((left, right, prop.key), self._joinpoint)
- })
+ self._update_joinpoint(
+ {
+ "_joinpoint_entity": right,
+ "prev": ((left, right, prop.key), self._joinpoint),
+ }
+ )
else:
- self._joinpoint = {'_joinpoint_entity': right}
+ self._joinpoint = {"_joinpoint_entity": right}
return right, inspect(right), onclause
@@ -2821,27 +2938,30 @@ class Query(object):
if isinstance(item, slice):
start, stop, step = util.decode_slice(item)
- if isinstance(stop, int) and \
- isinstance(start, int) and \
- stop - start <= 0:
+ if (
+ isinstance(stop, int)
+ and isinstance(start, int)
+ and stop - start <= 0
+ ):
return []
# perhaps we should execute a count() here so that we
# can still use LIMIT/OFFSET ?
- elif (isinstance(start, int) and start < 0) \
- or (isinstance(stop, int) and stop < 0):
+ elif (isinstance(start, int) and start < 0) or (
+ isinstance(stop, int) and stop < 0
+ ):
return list(self)[item]
res = self.slice(start, stop)
if step is not None:
- return list(res)[None:None:item.step]
+ return list(res)[None : None : item.step]
else:
return list(res)
else:
if item == -1:
return list(self)[-1]
else:
- return list(self[item:item + 1])[0]
+ return list(self[item : item + 1])[0]
@_generative(_no_statement_condition)
def slice(self, start, stop):
@@ -3014,12 +3134,13 @@ class Query(object):
"""
statement = expression._expression_literal_as_text(statement)
- if not isinstance(statement,
- (expression.TextClause,
- expression.SelectBase)):
+ if not isinstance(
+ statement, (expression.TextClause, expression.SelectBase)
+ ):
raise sa_exc.ArgumentError(
"from_statement accepts text(), select(), "
- "and union() objects only.")
+ "and union() objects only."
+ )
self._statement = statement
@@ -3082,7 +3203,8 @@ class Query(object):
return None
else:
raise orm_exc.MultipleResultsFound(
- "Multiple rows were found for one_or_none()")
+ "Multiple rows were found for one_or_none()"
+ )
def one(self):
"""Return exactly one result or raise an exception.
@@ -3106,7 +3228,8 @@ class Query(object):
ret = self.one_or_none()
except orm_exc.MultipleResultsFound:
raise orm_exc.MultipleResultsFound(
- "Multiple rows were found for one()")
+ "Multiple rows were found for one()"
+ )
else:
if ret is None:
raise orm_exc.NoResultFound("No row was found for one()")
@@ -3149,8 +3272,11 @@ class Query(object):
def __str__(self):
context = self._compile_context()
try:
- bind = self._get_bind_args(
- context, self.session.get_bind) if self.session else None
+ bind = (
+ self._get_bind_args(context, self.session.get_bind)
+ if self.session
+ else None
+ )
except sa_exc.UnboundExecutionError:
bind = None
return str(context.statement.compile(bind))
@@ -3163,24 +3289,22 @@ class Query(object):
def _execute_and_instances(self, querycontext):
conn = self._get_bind_args(
- querycontext,
- self._connection_from_session,
- close_with_result=True)
+ querycontext, self._connection_from_session, close_with_result=True
+ )
result = conn.execute(querycontext.statement, self._params)
return loading.instances(querycontext.query, result, querycontext)
def _execute_crud(self, stmt, mapper):
conn = self._connection_from_session(
- mapper=mapper, clause=stmt, close_with_result=True)
+ mapper=mapper, clause=stmt, close_with_result=True
+ )
return conn.execute(stmt, self._params)
def _get_bind_args(self, querycontext, fn, **kw):
return fn(
- mapper=self._bind_mapper(),
- clause=querycontext.statement,
- **kw
+ mapper=self._bind_mapper(), clause=querycontext.statement, **kw
)
@property
@@ -3225,21 +3349,23 @@ class Query(object):
return [
{
- 'name': ent._label_name,
- 'type': ent.type,
- 'aliased': getattr(insp_ent, 'is_aliased_class', False),
- 'expr': ent.expr,
- 'entity':
- getattr(insp_ent, "entity", None)
- if ent.entity_zero is not None
- and not insp_ent.is_clause_element
- else None
+ "name": ent._label_name,
+ "type": ent.type,
+ "aliased": getattr(insp_ent, "is_aliased_class", False),
+ "expr": ent.expr,
+ "entity": getattr(insp_ent, "entity", None)
+ if ent.entity_zero is not None
+ and not insp_ent.is_clause_element
+ else None,
}
for ent, insp_ent in [
(
_ent,
- (inspect(_ent.entity_zero)
- if _ent.entity_zero is not None else None)
+ (
+ inspect(_ent.entity_zero)
+ if _ent.entity_zero is not None
+ else None
+ ),
)
for _ent in self._entities
]
@@ -3290,21 +3416,23 @@ class Query(object):
@property
def _select_args(self):
return {
- 'limit': self._limit,
- 'offset': self._offset,
- 'distinct': self._distinct,
- 'prefixes': self._prefixes,
- 'suffixes': self._suffixes,
- 'group_by': self._group_by or None,
- 'having': self._having
+ "limit": self._limit,
+ "offset": self._offset,
+ "distinct": self._distinct,
+ "prefixes": self._prefixes,
+ "suffixes": self._suffixes,
+ "group_by": self._group_by or None,
+ "having": self._having,
}
@property
def _should_nest_selectable(self):
kwargs = self._select_args
- return (kwargs.get('limit') is not None or
- kwargs.get('offset') is not None or
- kwargs.get('distinct', False))
+ return (
+ kwargs.get("limit") is not None
+ or kwargs.get("offset") is not None
+ or kwargs.get("distinct", False)
+ )
def exists(self):
"""A convenience method that turns a query into an EXISTS subquery
@@ -3343,9 +3471,12 @@ class Query(object):
# omitting the FROM clause from a query(X) (#2818);
# .with_only_columns() after we have a core select() so that
# we get just "SELECT 1" without any entities.
- return sql.exists(self.enable_eagerloads(False).add_columns('1').
- with_labels().
- statement.with_only_columns([1]))
+ return sql.exists(
+ self.enable_eagerloads(False)
+ .add_columns("1")
+ .with_labels()
+ .statement.with_only_columns([1])
+ )
def count(self):
r"""Return a count of rows this Query would return.
@@ -3384,10 +3515,10 @@ class Query(object):
session.query(func.count(distinct(User.name)))
"""
- col = sql.func.count(sql.literal_column('*'))
+ col = sql.func.count(sql.literal_column("*"))
return self.from_self(col).scalar()
- def delete(self, synchronize_session='evaluate'):
+ def delete(self, synchronize_session="evaluate"):
r"""Perform a bulk delete query.
Deletes rows matched by this query from the database.
@@ -3506,12 +3637,11 @@ class Query(object):
"""
- delete_op = persistence.BulkDelete.factory(
- self, synchronize_session)
+ delete_op = persistence.BulkDelete.factory(self, synchronize_session)
delete_op.exec_()
return delete_op.rowcount
- def update(self, values, synchronize_session='evaluate', update_args=None):
+ def update(self, values, synchronize_session="evaluate", update_args=None):
r"""Perform a bulk update query.
Updates rows matched by this query in the database.
@@ -3640,7 +3770,8 @@ class Query(object):
update_args = update_args or {}
update_op = persistence.BulkUpdate.factory(
- self, synchronize_session, values, update_args)
+ self, synchronize_session, values, update_args
+ )
update_op.exec_()
return update_op.rowcount
@@ -3682,11 +3813,12 @@ class Query(object):
raise sa_exc.InvalidRequestError(
"No column-based properties specified for "
"refresh operation. Use session.expire() "
- "to reload collections and related items.")
+ "to reload collections and related items."
+ )
else:
raise sa_exc.InvalidRequestError(
- "Query contains no columns with which to "
- "SELECT from.")
+ "Query contains no columns with which to " "SELECT from."
+ )
if context.multi_row_eager_loaders and self._should_nest_selectable:
context.statement = self._compound_eager_statement(context)
@@ -3701,11 +3833,9 @@ class Query(object):
# then append eager joins onto that
if context.order_by:
- order_by_col_expr = \
- sql_util.expand_column_list_from_order_by(
- context.primary_columns,
- context.order_by
- )
+ order_by_col_expr = sql_util.expand_column_list_from_order_by(
+ context.primary_columns, context.order_by
+ )
else:
context.order_by = None
order_by_col_expr = []
@@ -3738,15 +3868,17 @@ class Query(object):
context.adapter = sql_util.ColumnAdapter(inner, equivs)
statement = sql.select(
- [inner] + context.secondary_columns,
- use_labels=context.labels)
+ [inner] + context.secondary_columns, use_labels=context.labels
+ )
# Oracle however does not allow FOR UPDATE on the subquery,
# and the Oracle dialect ignores it, plus for PostgreSQL, MySQL
# we expect that all elements of the row are locked, so also put it
# on the outside (except in the case of PG when OF is used)
- if context._for_update_arg is not None and \
- context._for_update_arg.of is None:
+ if (
+ context._for_update_arg is not None
+ and context._for_update_arg.of is None
+ ):
statement._for_update_arg = context._for_update_arg
from_clause = inner
@@ -3755,16 +3887,14 @@ class Query(object):
# giving us a marker as to where the "splice point" of
# the join should be
from_clause = sql_util.splice_joins(
- from_clause,
- eager_join, eager_join.stop_on)
+ from_clause, eager_join, eager_join.stop_on
+ )
statement.append_from(from_clause)
if context.order_by:
statement.append_order_by(
- *context.adapter.copy_and_process(
- context.order_by
- )
+ *context.adapter.copy_and_process(context.order_by)
)
statement.append_order_by(*context.eager_order_by)
@@ -3775,16 +3905,13 @@ class Query(object):
context.order_by = None
if self._distinct is True and context.order_by:
- context.primary_columns += \
- sql_util.expand_column_list_from_order_by(
- context.primary_columns,
- context.order_by
- )
+ context.primary_columns += sql_util.expand_column_list_from_order_by(
+ context.primary_columns, context.order_by
+ )
context.froms += tuple(context.eager_joins.values())
statement = sql.select(
- context.primary_columns +
- context.secondary_columns,
+ context.primary_columns + context.secondary_columns,
context.whereclause,
from_obj=context.froms,
use_labels=context.labels,
@@ -3815,8 +3942,10 @@ class Query(object):
"""
search = set(self._mapper_adapter_map.values())
- if self._select_from_entity and \
- self._select_from_entity not in self._mapper_adapter_map:
+ if (
+ self._select_from_entity
+ and self._select_from_entity not in self._mapper_adapter_map
+ ):
insp = inspect(self._select_from_entity)
if insp.is_aliased_class:
adapter = insp._adapter
@@ -3833,8 +3962,8 @@ class Query(object):
single_crit = adapter.traverse(single_crit)
single_crit = self._adapt_clause(single_crit, False, False)
context.whereclause = sql.and_(
- sql.True_._ifnone(context.whereclause),
- single_crit)
+ sql.True_._ifnone(context.whereclause), single_crit
+ )
from ..sql.selectable import ForUpdateArg
@@ -3856,7 +3985,8 @@ class LockmodeArg(ForUpdateArg):
read = False
else:
raise sa_exc.ArgumentError(
- "Unknown with_lockmode argument: %r" % mode)
+ "Unknown with_lockmode argument: %r" % mode
+ )
return LockmodeArg(read=read, nowait=nowait)
@@ -3867,8 +3997,9 @@ class _QueryEntity(object):
def __new__(cls, *args, **kwargs):
if cls is _QueryEntity:
entity = args[1]
- if not isinstance(entity, util.string_types) and \
- _is_mapped_class(entity):
+ if not isinstance(entity, util.string_types) and _is_mapped_class(
+ entity
+ ):
cls = _MapperEntity
elif isinstance(entity, Bundle):
cls = _BundleEntity
@@ -3903,8 +4034,7 @@ class _MapperEntity(_QueryEntity):
self.selectable = ext_info.selectable
self.is_aliased_class = ext_info.is_aliased_class
self._with_polymorphic = ext_info.with_polymorphic_mappers
- self._polymorphic_discriminator = \
- ext_info.polymorphic_on
+ self._polymorphic_discriminator = ext_info.polymorphic_on
self.entity_zero = ext_info
if ext_info.is_aliased_class:
self._label_name = self.entity_zero.name
@@ -3912,8 +4042,9 @@ class _MapperEntity(_QueryEntity):
self._label_name = self.mapper.class_.__name__
self.path = self.entity_zero._path_registry
- def set_with_polymorphic(self, query, cls_or_mappers,
- selectable, polymorphic_on):
+ def set_with_polymorphic(
+ self, query, cls_or_mappers, selectable, polymorphic_on
+ ):
"""Receive an update from a call to query.with_polymorphic().
Note the newer style of using a free standing with_polymporphic()
@@ -3924,8 +4055,7 @@ class _MapperEntity(_QueryEntity):
if self.is_aliased_class:
# TODO: invalidrequest ?
raise NotImplementedError(
- "Can't use with_polymorphic() against "
- "an Aliased object"
+ "Can't use with_polymorphic() against " "an Aliased object"
)
if cls_or_mappers is None:
@@ -3933,14 +4063,16 @@ class _MapperEntity(_QueryEntity):
return
mappers, from_obj = self.mapper._with_polymorphic_args(
- cls_or_mappers, selectable)
+ cls_or_mappers, selectable
+ )
self._with_polymorphic = mappers
self._polymorphic_discriminator = polymorphic_on
self.selectable = from_obj
query._mapper_loads_polymorphically_with(
- self.mapper, sql_util.ColumnAdapter(
- from_obj, self.mapper._equivalent_columns))
+ self.mapper,
+ sql_util.ColumnAdapter(from_obj, self.mapper._equivalent_columns),
+ )
@property
def type(self):
@@ -3989,8 +4121,8 @@ class _MapperEntity(_QueryEntity):
# require row aliasing unconditionally.
if not adapter and self.mapper._requires_row_aliasing:
adapter = sql_util.ColumnAdapter(
- self.selectable,
- self.mapper._equivalent_columns)
+ self.selectable, self.mapper._equivalent_columns
+ )
if query._primary_entity is self:
only_load_props = query._only_load_props
@@ -4006,7 +4138,7 @@ class _MapperEntity(_QueryEntity):
adapter,
only_load_props=only_load_props,
refresh_state=refresh_state,
- polymorphic_discriminator=self._polymorphic_discriminator
+ polymorphic_discriminator=self._polymorphic_discriminator,
)
return _instance, self._label_name
@@ -4023,17 +4155,19 @@ class _MapperEntity(_QueryEntity):
# apply adaptation to the mapper's order_by if needed.
if adapter:
context.order_by = adapter.adapt_list(
- util.to_list(
- context.order_by
- )
+ util.to_list(context.order_by)
)
loading._setup_entity_query(
- context, self.mapper, self,
- self.path, adapter, context.primary_columns,
+ context,
+ self.mapper,
+ self,
+ self.path,
+ adapter,
+ context.primary_columns,
with_polymorphic=self._with_polymorphic,
only_load_props=query._only_load_props,
- polymorphic_discriminator=self._polymorphic_discriminator
+ polymorphic_discriminator=self._polymorphic_discriminator,
)
def __str__(self):
@@ -4091,9 +4225,10 @@ class Bundle(InspectionAttr):
self.name = self._label = name
self.exprs = exprs
self.c = self.columns = ColumnCollection()
- self.columns.update((getattr(col, "key", col._label), col)
- for col in exprs)
- self.single_entity = kw.pop('single_entity', self.single_entity)
+ self.columns.update(
+ (getattr(col, "key", col._label), col) for col in exprs
+ )
+ self.single_entity = kw.pop("single_entity", self.single_entity)
columns = None
"""A namespace of SQL expressions referred to by this :class:`.Bundle`.
@@ -4152,10 +4287,11 @@ class Bundle(InspectionAttr):
:ref:`bundles` - includes an example of subclassing.
"""
- keyed_tuple = util.lightweight_named_tuple('result', labels)
+ keyed_tuple = util.lightweight_named_tuple("result", labels)
def proc(row):
return keyed_tuple([proc(row) for proc in procs])
+
return proc
@@ -4235,8 +4371,10 @@ class _BundleEntity(_QueryEntity):
def row_processor(self, query, context, result):
procs, labels = zip(
- *[ent.row_processor(query, context, result)
- for ent in self._entities]
+ *[
+ ent.row_processor(query, context, result)
+ for ent in self._entities
+ ]
)
proc = self.bundle.create_row_processor(query, procs, labels)
@@ -4259,11 +4397,10 @@ class _ColumnEntity(_QueryEntity):
search_entities = False
check_column = True
_entity = None
- elif isinstance(column, (
- attributes.QueryableAttribute,
- interfaces.PropComparator
- )):
- _entity = getattr(column, '_parententity', None)
+ elif isinstance(
+ column, (attributes.QueryableAttribute, interfaces.PropComparator)
+ ):
+ _entity = getattr(column, "_parententity", None)
if _entity is not None:
search_entities = False
self._label_name = column.key
@@ -4274,7 +4411,7 @@ class _ColumnEntity(_QueryEntity):
return
if not isinstance(column, sql.ColumnElement):
- if hasattr(column, '_select_iterable'):
+ if hasattr(column, "_select_iterable"):
# break out an object like Table into
# individual columns
for c in column._select_iterable:
@@ -4286,10 +4423,10 @@ class _ColumnEntity(_QueryEntity):
raise sa_exc.InvalidRequestError(
"SQL expression, column, or mapped entity "
- "expected - got '%r'" % (column, )
+ "expected - got '%r'" % (column,)
)
elif not check_column:
- self._label_name = getattr(column, 'key', None)
+ self._label_name = getattr(column, "key", None)
search_entities = True
self.type = type_ = column.type
@@ -4301,7 +4438,7 @@ class _ColumnEntity(_QueryEntity):
# if the expression's identity has been changed
# due to adaption.
- if not column._label and not getattr(column, 'is_literal', False):
+ if not column._label and not getattr(column, "is_literal", False):
column = column.label(self._label_name)
query._entities.append(self)
@@ -4328,23 +4465,29 @@ class _ColumnEntity(_QueryEntity):
self._from_entities = set(self.entities)
else:
all_elements = [
- elem for elem in sql_util.surface_column_elements(
- column, include_scalar_selects=False)
- if 'parententity' in elem._annotations
+ elem
+ for elem in sql_util.surface_column_elements(
+ column, include_scalar_selects=False
+ )
+ if "parententity" in elem._annotations
]
- self.entities = util.unique_list([
- elem._annotations['parententity']
- for elem in all_elements
- if 'parententity' in elem._annotations
- ])
-
- self._from_entities = set([
- elem._annotations['parententity']
- for elem in all_elements
- if 'parententity' in elem._annotations
- and actual_froms.intersection(elem._from_objects)
- ])
+ self.entities = util.unique_list(
+ [
+ elem._annotations["parententity"]
+ for elem in all_elements
+ if "parententity" in elem._annotations
+ ]
+ )
+
+ self._from_entities = set(
+ [
+ elem._annotations["parententity"]
+ for elem in all_elements
+ if "parententity" in elem._annotations
+ and actual_froms.intersection(elem._from_objects)
+ ]
+ )
if self.entities:
self.entity_zero = self.entities[0]
self.mapper = self.entity_zero.mapper
@@ -4373,7 +4516,7 @@ class _ColumnEntity(_QueryEntity):
c.entities = self.entities
def setup_entity(self, ext_info, aliased_adapter):
- if 'selectable' not in self.__dict__:
+ if "selectable" not in self.__dict__:
self.selectable = ext_info.selectable
if self.actual_froms.intersection(ext_info.selectable._from_objects):
@@ -4386,12 +4529,13 @@ class _ColumnEntity(_QueryEntity):
# TODO: polymorphic subclasses ?
return entity is self.entity_zero
else:
- return not _is_aliased_class(self.entity_zero) and \
- entity.common_parent(self.entity_zero)
+ return not _is_aliased_class(
+ self.entity_zero
+ ) and entity.common_parent(self.entity_zero)
def row_processor(self, query, context, result):
- if ('fetch_column', self) in context.attributes:
- column = context.attributes[('fetch_column', self)]
+ if ("fetch_column", self) in context.attributes:
+ column = context.attributes[("fetch_column", self)]
else:
column = query._adapt_clause(self.column, False, True)
@@ -4417,7 +4561,7 @@ class _ColumnEntity(_QueryEntity):
context.froms += tuple(self.froms)
context.primary_columns.append(column)
- context.attributes[('fetch_column', self)] = column
+ context.attributes[("fetch_column", self)] = column
def __str__(self):
return str(self.column)
@@ -4425,22 +4569,44 @@ class _ColumnEntity(_QueryEntity):
class QueryContext(object):
__slots__ = (
- 'multi_row_eager_loaders', 'adapter', 'froms', 'for_update',
- 'query', 'session', 'autoflush', 'populate_existing',
- 'invoke_all_eagers', 'version_check', 'refresh_state',
- 'primary_columns', 'secondary_columns', 'eager_order_by',
- 'eager_joins', 'create_eager_joins', 'propagate_options',
- 'attributes', 'statement', 'from_clause', 'whereclause',
- 'order_by', 'labels', '_for_update_arg', 'runid', 'partials',
- 'post_load_paths', 'identity_token'
+ "multi_row_eager_loaders",
+ "adapter",
+ "froms",
+ "for_update",
+ "query",
+ "session",
+ "autoflush",
+ "populate_existing",
+ "invoke_all_eagers",
+ "version_check",
+ "refresh_state",
+ "primary_columns",
+ "secondary_columns",
+ "eager_order_by",
+ "eager_joins",
+ "create_eager_joins",
+ "propagate_options",
+ "attributes",
+ "statement",
+ "from_clause",
+ "whereclause",
+ "order_by",
+ "labels",
+ "_for_update_arg",
+ "runid",
+ "partials",
+ "post_load_paths",
+ "identity_token",
)
def __init__(self, query):
if query._statement is not None:
- if isinstance(query._statement, expression.SelectBase) and \
- not query._statement._textual and \
- not query._statement.use_labels:
+ if (
+ isinstance(query._statement, expression.SelectBase)
+ and not query._statement._textual
+ and not query._statement.use_labels
+ ):
self.statement = query._statement.apply_labels()
else:
self.statement = query._statement
@@ -4466,8 +4632,9 @@ class QueryContext(object):
self.eager_order_by = []
self.eager_joins = {}
self.create_eager_joins = []
- self.propagate_options = set(o for o in query._with_options if
- o.propagate_to_loaders)
+ self.propagate_options = set(
+ o for o in query._with_options if o.propagate_to_loaders
+ )
self.attributes = query._attributes.copy()
if self.refresh_state is not None:
self.identity_token = query._refresh_identity_token
@@ -4476,7 +4643,6 @@ class QueryContext(object):
class AliasOption(interfaces.MapperOption):
-
def __init__(self, alias):
r"""Return a :class:`.MapperOption` that will indicate to the :class:`.Query`
that the main table has been aliased.
diff --git a/lib/sqlalchemy/orm/relationships.py b/lib/sqlalchemy/orm/relationships.py
index e7896c423..e89d1542f 100644
--- a/lib/sqlalchemy/orm/relationships.py
+++ b/lib/sqlalchemy/orm/relationships.py
@@ -22,14 +22,23 @@ from . import dependency
from . import attributes
from ..sql.util import (
ClauseAdapter,
- join_condition, _shallow_annotate, visit_binary_product,
- _deep_deannotate, selectables_overlap, adapt_criterion_to_null
+ join_condition,
+ _shallow_annotate,
+ visit_binary_product,
+ _deep_deannotate,
+ selectables_overlap,
+ adapt_criterion_to_null,
)
from .base import state_str
from ..sql import operators, expression, visitors
-from .interfaces import (MANYTOMANY, MANYTOONE, ONETOMANY,
- StrategizedProperty, PropComparator)
+from .interfaces import (
+ MANYTOMANY,
+ MANYTOONE,
+ ONETOMANY,
+ StrategizedProperty,
+ PropComparator,
+)
from ..inspection import inspect
from . import mapper as mapperlib
import collections
@@ -51,8 +60,9 @@ def remote(expr):
:func:`.foreign`
"""
- return _annotate_columns(expression._clause_element_as_expr(expr),
- {"remote": True})
+ return _annotate_columns(
+ expression._clause_element_as_expr(expr), {"remote": True}
+ )
def foreign(expr):
@@ -72,8 +82,9 @@ def foreign(expr):
"""
- return _annotate_columns(expression._clause_element_as_expr(expr),
- {"foreign": True})
+ return _annotate_columns(
+ expression._clause_element_as_expr(expr), {"foreign": True}
+ )
@log.class_logger
@@ -90,36 +101,46 @@ class RelationshipProperty(StrategizedProperty):
"""
- strategy_wildcard_key = 'relationship'
+ strategy_wildcard_key = "relationship"
_dependency_processor = None
- def __init__(self, argument,
- secondary=None, primaryjoin=None,
- secondaryjoin=None,
- foreign_keys=None,
- uselist=None,
- order_by=False,
- backref=None,
- back_populates=None,
- post_update=False,
- cascade=False, extension=None,
- viewonly=False, lazy="select",
- collection_class=None, passive_deletes=False,
- passive_updates=True, remote_side=None,
- enable_typechecks=True, join_depth=None,
- comparator_factory=None,
- single_parent=False, innerjoin=False,
- distinct_target_key=None,
- doc=None,
- active_history=False,
- cascade_backrefs=True,
- load_on_pending=False,
- bake_queries=True,
- _local_remote_pairs=None,
- query_class=None,
- info=None,
- omit_join=None):
+ def __init__(
+ self,
+ argument,
+ secondary=None,
+ primaryjoin=None,
+ secondaryjoin=None,
+ foreign_keys=None,
+ uselist=None,
+ order_by=False,
+ backref=None,
+ back_populates=None,
+ post_update=False,
+ cascade=False,
+ extension=None,
+ viewonly=False,
+ lazy="select",
+ collection_class=None,
+ passive_deletes=False,
+ passive_updates=True,
+ remote_side=None,
+ enable_typechecks=True,
+ join_depth=None,
+ comparator_factory=None,
+ single_parent=False,
+ innerjoin=False,
+ distinct_target_key=None,
+ doc=None,
+ active_history=False,
+ cascade_backrefs=True,
+ load_on_pending=False,
+ bake_queries=True,
+ _local_remote_pairs=None,
+ query_class=None,
+ info=None,
+ omit_join=None,
+ ):
"""Provide a relationship between two mapped classes.
This corresponds to a parent-child or associative table relationship.
@@ -858,20 +879,22 @@ class RelationshipProperty(StrategizedProperty):
self.extension = extension
self.bake_queries = bake_queries
self.load_on_pending = load_on_pending
- self.comparator_factory = comparator_factory or \
- RelationshipProperty.Comparator
+ self.comparator_factory = (
+ comparator_factory or RelationshipProperty.Comparator
+ )
self.comparator = self.comparator_factory(self, None)
util.set_creation_order(self)
if info is not None:
self.info = info
- self.strategy_key = (("lazy", self.lazy), )
+ self.strategy_key = (("lazy", self.lazy),)
self._reverse_property = set()
- self.cascade = cascade if cascade is not False \
- else "save-update, merge"
+ self.cascade = (
+ cascade if cascade is not False else "save-update, merge"
+ )
self.order_by = order_by
@@ -881,7 +904,8 @@ class RelationshipProperty(StrategizedProperty):
if backref:
raise sa_exc.ArgumentError(
"backref and back_populates keyword arguments "
- "are mutually exclusive")
+ "are mutually exclusive"
+ )
self.backref = None
else:
self.backref = backref
@@ -919,7 +943,8 @@ class RelationshipProperty(StrategizedProperty):
_of_type = None
def __init__(
- self, prop, parentmapper, adapt_to_entity=None, of_type=None):
+ self, prop, parentmapper, adapt_to_entity=None, of_type=None
+ ):
"""Construction of :class:`.RelationshipProperty.Comparator`
is internal to the ORM's attribute mechanics.
@@ -931,9 +956,12 @@ class RelationshipProperty(StrategizedProperty):
self._of_type = of_type
def adapt_to_entity(self, adapt_to_entity):
- return self.__class__(self.property, self._parententity,
- adapt_to_entity=adapt_to_entity,
- of_type=self._of_type)
+ return self.__class__(
+ self.property,
+ self._parententity,
+ adapt_to_entity=adapt_to_entity,
+ of_type=self._of_type,
+ )
@util.memoized_property
def mapper(self):
@@ -963,11 +991,11 @@ class RelationshipProperty(StrategizedProperty):
else:
of_type = None
- pj, sj, source, dest, \
- secondary, target_adapter = self.property._create_joins(
- source_selectable=adapt_from,
- source_polymorphic=True,
- of_type=of_type)
+ pj, sj, source, dest, secondary, target_adapter = self.property._create_joins(
+ source_selectable=adapt_from,
+ source_polymorphic=True,
+ of_type=of_type,
+ )
if sj is not None:
return pj & sj
else:
@@ -983,17 +1011,20 @@ class RelationshipProperty(StrategizedProperty):
self.property,
self._parententity,
adapt_to_entity=self._adapt_to_entity,
- of_type=cls)
+ of_type=cls,
+ )
def in_(self, other):
"""Produce an IN clause - this is not implemented
for :func:`~.orm.relationship`-based attributes at this time.
"""
- raise NotImplementedError('in_() not yet supported for '
- 'relationships. For a simple '
- 'many-to-one, use in_() against '
- 'the set of foreign key values.')
+ raise NotImplementedError(
+ "in_() not yet supported for "
+ "relationships. For a simple "
+ "many-to-one, use in_() against "
+ "the set of foreign key values."
+ )
__hash__ = None
@@ -1038,24 +1069,32 @@ class RelationshipProperty(StrategizedProperty):
if self.property.direction in [ONETOMANY, MANYTOMANY]:
return ~self._criterion_exists()
else:
- return _orm_annotate(self.property._optimized_compare(
- None, adapt_source=self.adapter))
+ return _orm_annotate(
+ self.property._optimized_compare(
+ None, adapt_source=self.adapter
+ )
+ )
elif self.property.uselist:
raise sa_exc.InvalidRequestError(
"Can't compare a collection to an object or collection; "
- "use contains() to test for membership.")
+ "use contains() to test for membership."
+ )
else:
return _orm_annotate(
self.property._optimized_compare(
- other, adapt_source=self.adapter))
+ other, adapt_source=self.adapter
+ )
+ )
def _criterion_exists(self, criterion=None, **kwargs):
- if getattr(self, '_of_type', None):
+ if getattr(self, "_of_type", None):
info = inspect(self._of_type)
- target_mapper, to_selectable, is_aliased_class = \
- info.mapper, info.selectable, info.is_aliased_class
- if self.property._is_self_referential and not \
- is_aliased_class:
+ target_mapper, to_selectable, is_aliased_class = (
+ info.mapper,
+ info.selectable,
+ info.is_aliased_class,
+ )
+ if self.property._is_self_referential and not is_aliased_class:
to_selectable = to_selectable.alias()
single_crit = target_mapper._single_table_criterion
@@ -1073,11 +1112,11 @@ class RelationshipProperty(StrategizedProperty):
else:
source_selectable = None
- pj, sj, source, dest, secondary, target_adapter = \
- self.property._create_joins(
- dest_polymorphic=True,
- dest_selectable=to_selectable,
- source_selectable=source_selectable)
+ pj, sj, source, dest, secondary, target_adapter = self.property._create_joins(
+ dest_polymorphic=True,
+ dest_selectable=to_selectable,
+ source_selectable=source_selectable,
+ )
for k in kwargs:
crit = getattr(self.property.mapper.class_, k) == kwargs[k]
@@ -1094,8 +1133,11 @@ class RelationshipProperty(StrategizedProperty):
else:
j = _orm_annotate(pj, exclude=self.property.remote_side)
- if criterion is not None and target_adapter and not \
- is_aliased_class:
+ if (
+ criterion is not None
+ and target_adapter
+ and not is_aliased_class
+ ):
# limit this adapter to annotated only?
criterion = target_adapter.traverse(criterion)
@@ -1106,16 +1148,19 @@ class RelationshipProperty(StrategizedProperty):
# to anything in the enclosing query.
if criterion is not None:
criterion = criterion._annotate(
- {'no_replacement_traverse': True})
+ {"no_replacement_traverse": True}
+ )
crit = j & sql.True_._ifnone(criterion)
if secondary is not None:
- ex = sql.exists([1], crit, from_obj=[dest, secondary]).\
- correlate_except(dest, secondary)
+ ex = sql.exists(
+ [1], crit, from_obj=[dest, secondary]
+ ).correlate_except(dest, secondary)
else:
- ex = sql.exists([1], crit, from_obj=dest).\
- correlate_except(dest)
+ ex = sql.exists([1], crit, from_obj=dest).correlate_except(
+ dest
+ )
return ex
def any(self, criterion=None, **kwargs):
@@ -1197,8 +1242,8 @@ class RelationshipProperty(StrategizedProperty):
"""
if self.property.uselist:
raise sa_exc.InvalidRequestError(
- "'has()' not implemented for collections. "
- "Use any().")
+ "'has()' not implemented for collections. " "Use any()."
+ )
return self._criterion_exists(criterion, **kwargs)
def contains(self, other, **kwargs):
@@ -1260,13 +1305,16 @@ class RelationshipProperty(StrategizedProperty):
if not self.property.uselist:
raise sa_exc.InvalidRequestError(
"'contains' not implemented for scalar "
- "attributes. Use ==")
+ "attributes. Use =="
+ )
clause = self.property._optimized_compare(
- other, adapt_source=self.adapter)
+ other, adapt_source=self.adapter
+ )
if self.property.secondaryjoin is not None:
- clause.negation_clause = \
- self.__negated_contains_or_equals(other)
+ clause.negation_clause = self.__negated_contains_or_equals(
+ other
+ )
return clause
@@ -1277,10 +1325,11 @@ class RelationshipProperty(StrategizedProperty):
def state_bindparam(x, state, col):
dict_ = state.dict
return sql.bindparam(
- x, unique=True,
+ x,
+ unique=True,
callable_=self.property._get_attr_w_warn_on_none(
self.property.mapper, state, dict_, col
- )
+ ),
)
def adapt(col):
@@ -1290,19 +1339,26 @@ class RelationshipProperty(StrategizedProperty):
return col
if self.property._use_get:
- return sql.and_(*[
- sql.or_(
- adapt(x) != state_bindparam(adapt(x), state, y),
- adapt(x) == None)
- for (x, y) in self.property.local_remote_pairs])
-
- criterion = sql.and_(*[
- x == y for (x, y) in
- zip(
- self.property.mapper.primary_key,
- self.property.mapper.primary_key_from_instance(other)
- )
- ])
+ return sql.and_(
+ *[
+ sql.or_(
+ adapt(x)
+ != state_bindparam(adapt(x), state, y),
+ adapt(x) == None,
+ )
+ for (x, y) in self.property.local_remote_pairs
+ ]
+ )
+
+ criterion = sql.and_(
+ *[
+ x == y
+ for (x, y) in zip(
+ self.property.mapper.primary_key,
+ self.property.mapper.primary_key_from_instance(other),
+ )
+ ]
+ )
return ~self._criterion_exists(criterion)
@@ -1347,8 +1403,11 @@ class RelationshipProperty(StrategizedProperty):
"""
if isinstance(other, (util.NoneType, expression.Null)):
if self.property.direction == MANYTOONE:
- return _orm_annotate(~self.property._optimized_compare(
- None, adapt_source=self.adapter))
+ return _orm_annotate(
+ ~self.property._optimized_compare(
+ None, adapt_source=self.adapter
+ )
+ )
else:
return self._criterion_exists()
@@ -1356,7 +1415,8 @@ class RelationshipProperty(StrategizedProperty):
raise sa_exc.InvalidRequestError(
"Can't compare a collection"
" to an object or collection; use "
- "contains() to test for membership.")
+ "contains() to test for membership."
+ )
else:
return _orm_annotate(self.__negated_contains_or_equals(other))
@@ -1374,12 +1434,19 @@ class RelationshipProperty(StrategizedProperty):
if insp.is_aliased_class:
adapt_source = insp._adapter.adapt_clause
return self._optimized_compare(
- instance, value_is_parent=True, adapt_source=adapt_source,
- alias_secondary=alias_secondary)
+ instance,
+ value_is_parent=True,
+ adapt_source=adapt_source,
+ alias_secondary=alias_secondary,
+ )
- def _optimized_compare(self, state, value_is_parent=False,
- adapt_source=None,
- alias_secondary=True):
+ def _optimized_compare(
+ self,
+ state,
+ value_is_parent=False,
+ adapt_source=None,
+ alias_secondary=True,
+ ):
if state is not None:
state = attributes.instance_state(state)
@@ -1387,17 +1454,19 @@ class RelationshipProperty(StrategizedProperty):
if state is None:
return self._lazy_none_clause(
- reverse_direction,
- adapt_source=adapt_source)
+ reverse_direction, adapt_source=adapt_source
+ )
if not reverse_direction:
- criterion, bind_to_col = \
- self._lazy_strategy._lazywhere, \
- self._lazy_strategy._bind_to_col
+ criterion, bind_to_col = (
+ self._lazy_strategy._lazywhere,
+ self._lazy_strategy._bind_to_col,
+ )
else:
- criterion, bind_to_col = \
- self._lazy_strategy._rev_lazywhere, \
- self._lazy_strategy._rev_bind_to_col
+ criterion, bind_to_col = (
+ self._lazy_strategy._rev_lazywhere,
+ self._lazy_strategy._rev_bind_to_col,
+ )
if reverse_direction:
mapper = self.mapper
@@ -1409,16 +1478,20 @@ class RelationshipProperty(StrategizedProperty):
def visit_bindparam(bindparam):
if bindparam._identifying_key in bind_to_col:
bindparam.callable = self._get_attr_w_warn_on_none(
- mapper, state, dict_,
- bind_to_col[bindparam._identifying_key])
+ mapper,
+ state,
+ dict_,
+ bind_to_col[bindparam._identifying_key],
+ )
if self.secondary is not None and alias_secondary:
- criterion = ClauseAdapter(
- self.secondary.alias()).\
- traverse(criterion)
+ criterion = ClauseAdapter(self.secondary.alias()).traverse(
+ criterion
+ )
criterion = visitors.cloned_traverse(
- criterion, {}, {'bindparam': visit_bindparam})
+ criterion, {}, {"bindparam": visit_bindparam}
+ )
if adapt_source:
criterion = adapt_source(criterion)
@@ -1483,25 +1556,27 @@ class RelationshipProperty(StrategizedProperty):
# only if we can't get a value now due to detachment do we return
# the last known value
current_value = mapper._get_state_attr_by_column(
- state, dict_, column,
+ state,
+ dict_,
+ column,
passive=attributes.PASSIVE_RETURN_NEVER_SET
if state.persistent
- else attributes.PASSIVE_NO_FETCH ^ attributes.INIT_OK)
+ else attributes.PASSIVE_NO_FETCH ^ attributes.INIT_OK,
+ )
if current_value is attributes.NEVER_SET:
if not existing_is_available:
raise sa_exc.InvalidRequestError(
"Can't resolve value for column %s on object "
- "%s; no value has been set for this column" % (
- column, state_str(state))
+ "%s; no value has been set for this column"
+ % (column, state_str(state))
)
elif current_value is attributes.PASSIVE_NO_RESULT:
if not existing_is_available:
raise sa_exc.InvalidRequestError(
"Can't resolve value for column %s on object "
"%s; the object is detached and the value was "
- "expired" % (
- column, state_str(state))
+ "expired" % (column, state_str(state))
)
else:
to_return = current_value
@@ -1510,19 +1585,23 @@ class RelationshipProperty(StrategizedProperty):
"Got None for value of column %s; this is unsupported "
"for a relationship comparison and will not "
"currently produce an IS comparison "
- "(but may in a future release)" % column)
+ "(but may in a future release)" % column
+ )
return to_return
+
return _go
def _lazy_none_clause(self, reverse_direction=False, adapt_source=None):
if not reverse_direction:
- criterion, bind_to_col = \
- self._lazy_strategy._lazywhere, \
- self._lazy_strategy._bind_to_col
+ criterion, bind_to_col = (
+ self._lazy_strategy._lazywhere,
+ self._lazy_strategy._bind_to_col,
+ )
else:
- criterion, bind_to_col = \
- self._lazy_strategy._rev_lazywhere, \
- self._lazy_strategy._rev_bind_to_col
+ criterion, bind_to_col = (
+ self._lazy_strategy._rev_lazywhere,
+ self._lazy_strategy._rev_bind_to_col,
+ )
criterion = adapt_criterion_to_null(criterion, bind_to_col)
@@ -1533,13 +1612,17 @@ class RelationshipProperty(StrategizedProperty):
def __str__(self):
return str(self.parent.class_.__name__) + "." + self.key
- def merge(self,
- session,
- source_state,
- source_dict,
- dest_state,
- dest_dict,
- load, _recursive, _resolve_conflict_map):
+ def merge(
+ self,
+ session,
+ source_state,
+ source_dict,
+ dest_state,
+ dest_dict,
+ load,
+ _recursive,
+ _resolve_conflict_map,
+ ):
if load:
for r in self._reverse_property:
@@ -1553,9 +1636,10 @@ class RelationshipProperty(StrategizedProperty):
return
if self.uselist:
- instances = source_state.get_impl(self.key).\
- get(source_state, source_dict)
- if hasattr(instances, '_sa_adapter'):
+ instances = source_state.get_impl(self.key).get(
+ source_state, source_dict
+ )
+ if hasattr(instances, "_sa_adapter"):
# convert collections to adapters to get a true iterator
instances = instances._sa_adapter
@@ -1573,21 +1657,25 @@ class RelationshipProperty(StrategizedProperty):
current_dict = attributes.instance_dict(current)
_recursive[(current_state, self)] = True
obj = session._merge(
- current_state, current_dict,
- load=load, _recursive=_recursive,
- _resolve_conflict_map=_resolve_conflict_map)
+ current_state,
+ current_dict,
+ load=load,
+ _recursive=_recursive,
+ _resolve_conflict_map=_resolve_conflict_map,
+ )
if obj is not None:
dest_list.append(obj)
if not load:
- coll = attributes.init_state_collection(dest_state,
- dest_dict, self.key)
+ coll = attributes.init_state_collection(
+ dest_state, dest_dict, self.key
+ )
for c in dest_list:
coll.append_without_event(c)
else:
dest_state.get_impl(self.key).set(
- dest_state, dest_dict, dest_list,
- _adapt=False)
+ dest_state, dest_dict, dest_list, _adapt=False
+ )
else:
current = source_dict[self.key]
if current is not None:
@@ -1595,20 +1683,25 @@ class RelationshipProperty(StrategizedProperty):
current_dict = attributes.instance_dict(current)
_recursive[(current_state, self)] = True
obj = session._merge(
- current_state, current_dict,
- load=load, _recursive=_recursive,
- _resolve_conflict_map=_resolve_conflict_map)
+ current_state,
+ current_dict,
+ load=load,
+ _recursive=_recursive,
+ _resolve_conflict_map=_resolve_conflict_map,
+ )
else:
obj = None
if not load:
dest_dict[self.key] = obj
else:
- dest_state.get_impl(self.key).set(dest_state,
- dest_dict, obj, None)
+ dest_state.get_impl(self.key).set(
+ dest_state, dest_dict, obj, None
+ )
- def _value_as_iterable(self, state, dict_, key,
- passive=attributes.PASSIVE_OFF):
+ def _value_as_iterable(
+ self, state, dict_, key, passive=attributes.PASSIVE_OFF
+ ):
"""Return a list of tuples (state, obj) for the given
key.
@@ -1619,34 +1712,36 @@ class RelationshipProperty(StrategizedProperty):
x = impl.get(state, dict_, passive=passive)
if x is attributes.PASSIVE_NO_RESULT or x is None:
return []
- elif hasattr(impl, 'get_collection'):
+ elif hasattr(impl, "get_collection"):
return [
- (attributes.instance_state(o), o) for o in
- impl.get_collection(state, dict_, x, passive=passive)
+ (attributes.instance_state(o), o)
+ for o in impl.get_collection(state, dict_, x, passive=passive)
]
else:
return [(attributes.instance_state(x), x)]
- def cascade_iterator(self, type_, state, dict_,
- visited_states, halt_on=None):
+ def cascade_iterator(
+ self, type_, state, dict_, visited_states, halt_on=None
+ ):
# assert type_ in self._cascade
# only actively lazy load on the 'delete' cascade
- if type_ != 'delete' or self.passive_deletes:
+ if type_ != "delete" or self.passive_deletes:
passive = attributes.PASSIVE_NO_INITIALIZE
else:
passive = attributes.PASSIVE_OFF
- if type_ == 'save-update':
- tuples = state.manager[self.key].impl.\
- get_all_pending(state, dict_)
+ if type_ == "save-update":
+ tuples = state.manager[self.key].impl.get_all_pending(state, dict_)
else:
- tuples = self._value_as_iterable(state, dict_, self.key,
- passive=passive)
+ tuples = self._value_as_iterable(
+ state, dict_, self.key, passive=passive
+ )
- skip_pending = type_ == 'refresh-expire' and 'delete-orphan' \
- not in self._cascade
+ skip_pending = (
+ type_ == "refresh-expire" and "delete-orphan" not in self._cascade
+ )
for instance_state, c in tuples:
if instance_state in visited_states:
@@ -1670,13 +1765,12 @@ class RelationshipProperty(StrategizedProperty):
instance_mapper = instance_state.manager.mapper
if not instance_mapper.isa(self.mapper.class_manager.mapper):
- raise AssertionError("Attribute '%s' on class '%s' "
- "doesn't handle objects "
- "of type '%s'" % (
- self.key,
- self.parent.class_,
- c.__class__
- ))
+ raise AssertionError(
+ "Attribute '%s' on class '%s' "
+ "doesn't handle objects "
+ "of type '%s'"
+ % (self.key, self.parent.class_, c.__class__)
+ )
visited_states.add(instance_state)
@@ -1689,18 +1783,22 @@ class RelationshipProperty(StrategizedProperty):
if not other.mapper.common_parent(self.parent):
raise sa_exc.ArgumentError(
- 'reverse_property %r on '
- 'relationship %s references relationship %s, which '
- 'does not reference mapper %s' %
- (key, self, other, self.parent))
+ "reverse_property %r on "
+ "relationship %s references relationship %s, which "
+ "does not reference mapper %s"
+ % (key, self, other, self.parent)
+ )
- if self.direction in (ONETOMANY, MANYTOONE) and self.direction \
- == other.direction:
+ if (
+ self.direction in (ONETOMANY, MANYTOONE)
+ and self.direction == other.direction
+ ):
raise sa_exc.ArgumentError(
- '%s and back-reference %s are '
- 'both of the same direction %r. Did you mean to '
- 'set remote_side on the many-to-one side ?' %
- (other, self, self.direction))
+ "%s and back-reference %s are "
+ "both of the same direction %r. Did you mean to "
+ "set remote_side on the many-to-one side ?"
+ % (other, self, self.direction)
+ )
@util.memoized_property
def mapper(self):
@@ -1710,22 +1808,23 @@ class RelationshipProperty(StrategizedProperty):
This is a lazy-initializing static attribute.
"""
- if util.callable(self.argument) and \
- not isinstance(self.argument, (type, mapperlib.Mapper)):
+ if util.callable(self.argument) and not isinstance(
+ self.argument, (type, mapperlib.Mapper)
+ ):
argument = self.argument()
else:
argument = self.argument
if isinstance(argument, type):
- mapper_ = mapperlib.class_mapper(argument,
- configure=False)
+ mapper_ = mapperlib.class_mapper(argument, configure=False)
elif isinstance(self.argument, mapperlib.Mapper):
mapper_ = argument
else:
raise sa_exc.ArgumentError(
"relationship '%s' expects "
"a class or a mapper argument (received: %s)"
- % (self.key, type(argument)))
+ % (self.key, type(argument))
+ )
return mapper_
@util.memoized_property
@@ -1759,8 +1858,12 @@ class RelationshipProperty(StrategizedProperty):
# deferred initialization. This technique is used
# by declarative "string configs" and some recipes.
for attr in (
- 'order_by', 'primaryjoin', 'secondaryjoin',
- 'secondary', '_user_defined_foreign_keys', 'remote_side',
+ "order_by",
+ "primaryjoin",
+ "secondaryjoin",
+ "secondary",
+ "_user_defined_foreign_keys",
+ "remote_side",
):
attr_value = getattr(self, attr)
if util.callable(attr_value):
@@ -1768,11 +1871,15 @@ class RelationshipProperty(StrategizedProperty):
# remove "annotations" which are present if mapped class
# descriptors are used to create the join expression.
- for attr in 'primaryjoin', 'secondaryjoin':
+ for attr in "primaryjoin", "secondaryjoin":
val = getattr(self, attr)
if val is not None:
- setattr(self, attr, _orm_deannotate(
- expression._only_column_elements(val, attr))
+ setattr(
+ self,
+ attr,
+ _orm_deannotate(
+ expression._only_column_elements(val, attr)
+ ),
)
# ensure expressions in self.order_by, foreign_keys,
@@ -1780,21 +1887,18 @@ class RelationshipProperty(StrategizedProperty):
if self.order_by is not False and self.order_by is not None:
self.order_by = [
expression._only_column_elements(x, "order_by")
- for x in
- util.to_list(self.order_by)]
-
- self._user_defined_foreign_keys = \
- util.column_set(
- expression._only_column_elements(x, "foreign_keys")
- for x in util.to_column_set(
- self._user_defined_foreign_keys
- ))
-
- self.remote_side = \
- util.column_set(
- expression._only_column_elements(x, "remote_side")
- for x in
- util.to_column_set(self.remote_side))
+ for x in util.to_list(self.order_by)
+ ]
+
+ self._user_defined_foreign_keys = util.column_set(
+ expression._only_column_elements(x, "foreign_keys")
+ for x in util.to_column_set(self._user_defined_foreign_keys)
+ )
+
+ self.remote_side = util.column_set(
+ expression._only_column_elements(x, "remote_side")
+ for x in util.to_column_set(self.remote_side)
+ )
self.target = self.mapper.mapped_table
@@ -1815,7 +1919,7 @@ class RelationshipProperty(StrategizedProperty):
self_referential=self._is_self_referential,
prop=self,
support_sync=not self.viewonly,
- can_be_synced_fn=self._columns_are_mapped
+ can_be_synced_fn=self._columns_are_mapped,
)
self.primaryjoin = jc.primaryjoin
self.secondaryjoin = jc.secondaryjoin
@@ -1832,16 +1936,20 @@ class RelationshipProperty(StrategizedProperty):
inheritance conflicts."""
if self.parent.non_primary and not mapperlib.class_mapper(
- self.parent.class_,
- configure=False).has_property(self.key):
+ self.parent.class_, configure=False
+ ).has_property(self.key):
raise sa_exc.ArgumentError(
"Attempting to assign a new "
"relationship '%s' to a non-primary mapper on "
"class '%s'. New relationships can only be 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__))
+ "created for class '%s' "
+ % (
+ self.key,
+ self.parent.class_.__name__,
+ self.parent.class_.__name__,
+ )
+ )
def _get_cascade(self):
"""Return the current cascade setting for this
@@ -1851,7 +1959,7 @@ class RelationshipProperty(StrategizedProperty):
def _set_cascade(self, cascade):
cascade = CascadeOptions(cascade)
- if 'mapper' in self.__dict__:
+ if "mapper" in self.__dict__:
self._check_cascade_settings(cascade)
self._cascade = cascade
@@ -1861,27 +1969,31 @@ class RelationshipProperty(StrategizedProperty):
cascade = property(_get_cascade, _set_cascade)
def _check_cascade_settings(self, cascade):
- if cascade.delete_orphan and not self.single_parent \
- and (self.direction is MANYTOMANY or self.direction
- is MANYTOONE):
+ if (
+ cascade.delete_orphan
+ and not self.single_parent
+ and (self.direction is MANYTOMANY or self.direction is MANYTOONE)
+ ):
raise sa_exc.ArgumentError(
- 'On %s, delete-orphan cascade is not supported '
- 'on a many-to-many or many-to-one relationship '
- 'when single_parent is not set. Set '
- 'single_parent=True on the relationship().'
- % self)
+ "On %s, delete-orphan cascade is not supported "
+ "on a many-to-many or many-to-one relationship "
+ "when single_parent is not set. Set "
+ "single_parent=True on the relationship()." % self
+ )
if self.direction is MANYTOONE and self.passive_deletes:
- util.warn("On %s, 'passive_deletes' is normally configured "
- "on one-to-many, one-to-one, many-to-many "
- "relationships only."
- % self)
-
- if self.passive_deletes == 'all' and \
- ("delete" in cascade or
- "delete-orphan" in cascade):
+ util.warn(
+ "On %s, 'passive_deletes' is normally configured "
+ "on one-to-many, one-to-one, many-to-many "
+ "relationships only." % self
+ )
+
+ if self.passive_deletes == "all" and (
+ "delete" in cascade or "delete-orphan" in cascade
+ ):
raise sa_exc.ArgumentError(
"On %s, can't set passive_deletes='all' in conjunction "
- "with 'delete' or 'delete-orphan' cascade" % self)
+ "with 'delete' or 'delete-orphan' cascade" % self
+ )
if cascade.delete_orphan:
self.mapper.primary_mapper()._delete_orphans.append(
@@ -1894,8 +2006,10 @@ class RelationshipProperty(StrategizedProperty):
"""
- return self.key in mapper.relationships and \
- mapper.relationships[self.key] is self
+ return (
+ self.key in mapper.relationships
+ and mapper.relationships[self.key] is self
+ )
def _columns_are_mapped(self, *cols):
"""Return True if all columns in the given collection are
@@ -1903,11 +2017,14 @@ class RelationshipProperty(StrategizedProperty):
"""
for c in cols:
- if self.secondary is not None \
- and self.secondary.c.contains_column(c):
+ if (
+ self.secondary is not None
+ and self.secondary.c.contains_column(c)
+ ):
continue
- if not self.parent.mapped_table.c.contains_column(c) and \
- not self.target.c.contains_column(c):
+ if not self.parent.mapped_table.c.contains_column(
+ c
+ ) and not self.target.c.contains_column(c):
return False
return True
@@ -1925,15 +2042,17 @@ class RelationshipProperty(StrategizedProperty):
mapper = self.mapper.primary_mapper()
if not mapper.concrete:
- check = set(mapper.iterate_to_root()).\
- union(mapper.self_and_descendants)
+ check = set(mapper.iterate_to_root()).union(
+ mapper.self_and_descendants
+ )
for m in check:
if m.has_property(backref_key) and not m.concrete:
raise sa_exc.ArgumentError(
"Error creating backref "
"'%s' on relationship '%s': property of that "
- "name exists on mapper '%s'" %
- (backref_key, self, m))
+ "name exists on mapper '%s'"
+ % (backref_key, self, m)
+ )
# determine primaryjoin/secondaryjoin for the
# backref. Use the one we had, so that
@@ -1944,35 +2063,42 @@ class RelationshipProperty(StrategizedProperty):
# secondaryjoin. use the annotated
# pj/sj on the _join_condition.
pj = kwargs.pop(
- 'primaryjoin',
- self._join_condition.secondaryjoin_minus_local)
+ "primaryjoin",
+ self._join_condition.secondaryjoin_minus_local,
+ )
sj = kwargs.pop(
- 'secondaryjoin',
- self._join_condition.primaryjoin_minus_local)
+ "secondaryjoin",
+ self._join_condition.primaryjoin_minus_local,
+ )
else:
pj = kwargs.pop(
- 'primaryjoin',
- self._join_condition.primaryjoin_reverse_remote)
- sj = kwargs.pop('secondaryjoin', None)
+ "primaryjoin",
+ self._join_condition.primaryjoin_reverse_remote,
+ )
+ sj = kwargs.pop("secondaryjoin", None)
if sj:
raise sa_exc.InvalidRequestError(
"Can't assign 'secondaryjoin' on a backref "
"against a non-secondary relationship."
)
- foreign_keys = kwargs.pop('foreign_keys',
- self._user_defined_foreign_keys)
+ foreign_keys = kwargs.pop(
+ "foreign_keys", self._user_defined_foreign_keys
+ )
parent = self.parent.primary_mapper()
- kwargs.setdefault('viewonly', self.viewonly)
- kwargs.setdefault('post_update', self.post_update)
- kwargs.setdefault('passive_updates', self.passive_updates)
+ kwargs.setdefault("viewonly", self.viewonly)
+ kwargs.setdefault("post_update", self.post_update)
+ kwargs.setdefault("passive_updates", self.passive_updates)
self.back_populates = backref_key
relationship = RelationshipProperty(
- parent, self.secondary,
- pj, sj,
+ parent,
+ self.secondary,
+ pj,
+ sj,
foreign_keys=foreign_keys,
back_populates=self.key,
- **kwargs)
+ **kwargs
+ )
mapper._configure_property(backref_key, relationship)
if self.back_populates:
@@ -1982,8 +2108,9 @@ class RelationshipProperty(StrategizedProperty):
if self.uselist is None:
self.uselist = self.direction is not MANYTOONE
if not self.viewonly:
- self._dependency_processor = \
- dependency.DependencyProcessor.from_relationship(self)
+ self._dependency_processor = dependency.DependencyProcessor.from_relationship(
+ self
+ )
@util.memoized_property
def _use_get(self):
@@ -1997,9 +2124,14 @@ class RelationshipProperty(StrategizedProperty):
def _is_self_referential(self):
return self.mapper.common_parent(self.parent)
- def _create_joins(self, source_polymorphic=False,
- source_selectable=None, dest_polymorphic=False,
- dest_selectable=None, of_type=None):
+ def _create_joins(
+ self,
+ source_polymorphic=False,
+ source_selectable=None,
+ dest_polymorphic=False,
+ dest_selectable=None,
+ of_type=None,
+ ):
if source_selectable is None:
if source_polymorphic and self.parent.with_polymorphic:
source_selectable = self.parent._with_polymorphic_selectable
@@ -2023,16 +2155,21 @@ class RelationshipProperty(StrategizedProperty):
single_crit = dest_mapper._single_table_criterion
aliased = aliased or (source_selectable is not None)
- primaryjoin, secondaryjoin, secondary, target_adapter, dest_selectable = \
- self._join_condition.join_targets(
- source_selectable, dest_selectable, aliased, single_crit
- )
+ primaryjoin, secondaryjoin, secondary, target_adapter, dest_selectable = self._join_condition.join_targets(
+ source_selectable, dest_selectable, aliased, single_crit
+ )
if source_selectable is None:
source_selectable = self.parent.local_table
if dest_selectable is None:
dest_selectable = self.mapper.local_table
- return (primaryjoin, secondaryjoin, source_selectable,
- dest_selectable, secondary, target_adapter)
+ return (
+ primaryjoin,
+ secondaryjoin,
+ source_selectable,
+ dest_selectable,
+ secondary,
+ target_adapter,
+ )
def _annotate_columns(element, annotations):
@@ -2048,24 +2185,25 @@ def _annotate_columns(element, annotations):
class JoinCondition(object):
- def __init__(self,
- parent_selectable,
- child_selectable,
- parent_local_selectable,
- child_local_selectable,
- primaryjoin=None,
- secondary=None,
- secondaryjoin=None,
- parent_equivalents=None,
- child_equivalents=None,
- consider_as_foreign_keys=None,
- local_remote_pairs=None,
- remote_side=None,
- self_referential=False,
- prop=None,
- support_sync=True,
- can_be_synced_fn=lambda *c: True
- ):
+ def __init__(
+ self,
+ parent_selectable,
+ child_selectable,
+ parent_local_selectable,
+ child_local_selectable,
+ primaryjoin=None,
+ secondary=None,
+ secondaryjoin=None,
+ parent_equivalents=None,
+ child_equivalents=None,
+ consider_as_foreign_keys=None,
+ local_remote_pairs=None,
+ remote_side=None,
+ self_referential=False,
+ prop=None,
+ support_sync=True,
+ can_be_synced_fn=lambda *c: True,
+ ):
self.parent_selectable = parent_selectable
self.parent_local_selectable = parent_local_selectable
self.child_selectable = child_selectable
@@ -2100,27 +2238,41 @@ class JoinCondition(object):
if self.prop is None:
return
log = self.prop.logger
- log.info('%s setup primary join %s', self.prop,
- self.primaryjoin)
- log.info('%s setup secondary join %s', self.prop,
- self.secondaryjoin)
- log.info('%s synchronize pairs [%s]', self.prop,
- ','.join('(%s => %s)' % (l, r) for (l, r) in
- self.synchronize_pairs))
- log.info('%s secondary synchronize pairs [%s]', self.prop,
- ','.join('(%s => %s)' % (l, r) for (l, r) in
- self.secondary_synchronize_pairs or []))
- log.info('%s local/remote pairs [%s]', self.prop,
- ','.join('(%s / %s)' % (l, r) for (l, r) in
- self.local_remote_pairs))
- log.info('%s remote columns [%s]', self.prop,
- ','.join('%s' % col for col in self.remote_columns)
- )
- log.info('%s local columns [%s]', self.prop,
- ','.join('%s' % col for col in self.local_columns)
- )
- log.info('%s relationship direction %s', self.prop,
- self.direction)
+ log.info("%s setup primary join %s", self.prop, self.primaryjoin)
+ log.info("%s setup secondary join %s", self.prop, self.secondaryjoin)
+ log.info(
+ "%s synchronize pairs [%s]",
+ self.prop,
+ ",".join(
+ "(%s => %s)" % (l, r) for (l, r) in self.synchronize_pairs
+ ),
+ )
+ log.info(
+ "%s secondary synchronize pairs [%s]",
+ self.prop,
+ ",".join(
+ "(%s => %s)" % (l, r)
+ for (l, r) in self.secondary_synchronize_pairs or []
+ ),
+ )
+ log.info(
+ "%s local/remote pairs [%s]",
+ self.prop,
+ ",".join(
+ "(%s / %s)" % (l, r) for (l, r) in self.local_remote_pairs
+ ),
+ )
+ log.info(
+ "%s remote columns [%s]",
+ self.prop,
+ ",".join("%s" % col for col in self.remote_columns),
+ )
+ log.info(
+ "%s local columns [%s]",
+ self.prop,
+ ",".join("%s" % col for col in self.local_columns),
+ )
+ log.info("%s relationship direction %s", self.prop, self.direction)
def _sanitize_joins(self):
"""remove the parententity annotation from our join conditions which
@@ -2133,10 +2285,12 @@ class JoinCondition(object):
"""
self.primaryjoin = _deep_deannotate(
- self.primaryjoin, values=("parententity",))
+ self.primaryjoin, values=("parententity",)
+ )
if self.secondaryjoin is not None:
self.secondaryjoin = _deep_deannotate(
- self.secondaryjoin, values=("parententity",))
+ self.secondaryjoin, values=("parententity",)
+ )
def _determine_joins(self):
"""Determine the 'primaryjoin' and 'secondaryjoin' attributes,
@@ -2150,7 +2304,8 @@ class JoinCondition(object):
raise sa_exc.ArgumentError(
"Property %s specified with secondary "
"join condition but "
- "no secondary argument" % self.prop)
+ "no secondary argument" % self.prop
+ )
# find a join between the given mapper's mapped table and
# the given table. will try the mapper's local table first
@@ -2161,30 +2316,27 @@ class JoinCondition(object):
consider_as_foreign_keys = self.consider_as_foreign_keys or None
if self.secondary is not None:
if self.secondaryjoin is None:
- self.secondaryjoin = \
- join_condition(
- self.child_selectable,
- self.secondary,
- a_subset=self.child_local_selectable,
- consider_as_foreign_keys=consider_as_foreign_keys
- )
+ self.secondaryjoin = join_condition(
+ self.child_selectable,
+ self.secondary,
+ a_subset=self.child_local_selectable,
+ consider_as_foreign_keys=consider_as_foreign_keys,
+ )
if self.primaryjoin is None:
- self.primaryjoin = \
- join_condition(
- self.parent_selectable,
- self.secondary,
- a_subset=self.parent_local_selectable,
- consider_as_foreign_keys=consider_as_foreign_keys
- )
+ self.primaryjoin = join_condition(
+ self.parent_selectable,
+ self.secondary,
+ a_subset=self.parent_local_selectable,
+ consider_as_foreign_keys=consider_as_foreign_keys,
+ )
else:
if self.primaryjoin is None:
- self.primaryjoin = \
- join_condition(
- self.parent_selectable,
- self.child_selectable,
- a_subset=self.parent_local_selectable,
- consider_as_foreign_keys=consider_as_foreign_keys
- )
+ self.primaryjoin = join_condition(
+ self.parent_selectable,
+ self.child_selectable,
+ a_subset=self.parent_local_selectable,
+ consider_as_foreign_keys=consider_as_foreign_keys,
+ )
except sa_exc.NoForeignKeysError:
if self.secondary is not None:
raise sa_exc.NoForeignKeysError(
@@ -2195,7 +2347,8 @@ class JoinCondition(object):
"Ensure that referencing columns are associated "
"with a ForeignKey or ForeignKeyConstraint, or "
"specify 'primaryjoin' and 'secondaryjoin' "
- "expressions." % (self.prop, self.secondary))
+ "expressions." % (self.prop, self.secondary)
+ )
else:
raise sa_exc.NoForeignKeysError(
"Could not determine join "
@@ -2204,7 +2357,8 @@ class JoinCondition(object):
"linking these tables. "
"Ensure that referencing columns are associated "
"with a ForeignKey or ForeignKeyConstraint, or "
- "specify a 'primaryjoin' expression." % self.prop)
+ "specify a 'primaryjoin' expression." % self.prop
+ )
except sa_exc.AmbiguousForeignKeysError:
if self.secondary is not None:
raise sa_exc.AmbiguousForeignKeysError(
@@ -2216,8 +2370,8 @@ class JoinCondition(object):
"argument, providing a list of those columns which "
"should be counted as containing a foreign key "
"reference from the secondary table to each of the "
- "parent and child tables."
- % (self.prop, self.secondary))
+ "parent and child tables." % (self.prop, self.secondary)
+ )
else:
raise sa_exc.AmbiguousForeignKeysError(
"Could not determine join "
@@ -2226,8 +2380,8 @@ class JoinCondition(object):
"paths linking the tables. Specify the "
"'foreign_keys' argument, providing a list of those "
"columns which should be counted as containing a "
- "foreign key reference to the parent table."
- % self.prop)
+ "foreign key reference to the parent table." % self.prop
+ )
@property
def primaryjoin_minus_local(self):
@@ -2235,8 +2389,7 @@ class JoinCondition(object):
@property
def secondaryjoin_minus_local(self):
- return _deep_deannotate(self.secondaryjoin,
- values=("local", "remote"))
+ return _deep_deannotate(self.secondaryjoin, values=("local", "remote"))
@util.memoized_property
def primaryjoin_reverse_remote(self):
@@ -2250,24 +2403,26 @@ class JoinCondition(object):
"""
if self._has_remote_annotations:
+
def replace(element):
if "remote" in element._annotations:
v = element._annotations.copy()
- del v['remote']
- v['local'] = True
+ del v["remote"]
+ v["local"] = True
return element._with_annotations(v)
elif "local" in element._annotations:
v = element._annotations.copy()
- del v['local']
- v['remote'] = True
+ del v["local"]
+ v["remote"] = True
return element._with_annotations(v)
- return visitors.replacement_traverse(
- self.primaryjoin, {}, replace)
+
+ return visitors.replacement_traverse(self.primaryjoin, {}, replace)
else:
if self._has_foreign_annotations:
# TODO: coverage
- return _deep_deannotate(self.primaryjoin,
- values=("local", "remote"))
+ return _deep_deannotate(
+ self.primaryjoin, values=("local", "remote")
+ )
else:
return _deep_deannotate(self.primaryjoin)
@@ -2304,16 +2459,13 @@ class JoinCondition(object):
def check_fk(col):
if col in self.consider_as_foreign_keys:
return col._annotate({"foreign": True})
+
self.primaryjoin = visitors.replacement_traverse(
- self.primaryjoin,
- {},
- check_fk
+ self.primaryjoin, {}, check_fk
)
if self.secondaryjoin is not None:
self.secondaryjoin = visitors.replacement_traverse(
- self.secondaryjoin,
- {},
- check_fk
+ self.secondaryjoin, {}, check_fk
)
def _annotate_present_fks(self):
@@ -2323,8 +2475,7 @@ class JoinCondition(object):
secondarycols = set()
def is_foreign(a, b):
- if isinstance(a, schema.Column) and \
- isinstance(b, schema.Column):
+ if isinstance(a, schema.Column) and isinstance(b, schema.Column):
if a.references(b):
return a
elif b.references(a):
@@ -2337,31 +2488,30 @@ class JoinCondition(object):
return b
def visit_binary(binary):
- if not isinstance(binary.left, sql.ColumnElement) or \
- not isinstance(binary.right, sql.ColumnElement):
+ if not isinstance(
+ binary.left, sql.ColumnElement
+ ) or not isinstance(binary.right, sql.ColumnElement):
return
- if "foreign" not in binary.left._annotations and \
- "foreign" not in binary.right._annotations:
+ if (
+ "foreign" not in binary.left._annotations
+ and "foreign" not in binary.right._annotations
+ ):
col = is_foreign(binary.left, binary.right)
if col is not None:
if col.compare(binary.left):
- binary.left = binary.left._annotate(
- {"foreign": True})
+ binary.left = binary.left._annotate({"foreign": True})
elif col.compare(binary.right):
binary.right = binary.right._annotate(
- {"foreign": True})
+ {"foreign": True}
+ )
self.primaryjoin = visitors.cloned_traverse(
- self.primaryjoin,
- {},
- {"binary": visit_binary}
+ self.primaryjoin, {}, {"binary": visit_binary}
)
if self.secondaryjoin is not None:
self.secondaryjoin = visitors.cloned_traverse(
- self.secondaryjoin,
- {},
- {"binary": visit_binary}
+ self.secondaryjoin, {}, {"binary": visit_binary}
)
def _refers_to_parent_table(self):
@@ -2376,26 +2526,24 @@ class JoinCondition(object):
def visit_binary(binary):
c, f = binary.left, binary.right
if (
- isinstance(c, expression.ColumnClause) and
- isinstance(f, expression.ColumnClause) and
- pt.is_derived_from(c.table) and
- pt.is_derived_from(f.table) and
- mt.is_derived_from(c.table) and
- mt.is_derived_from(f.table)
+ isinstance(c, expression.ColumnClause)
+ and isinstance(f, expression.ColumnClause)
+ and pt.is_derived_from(c.table)
+ and pt.is_derived_from(f.table)
+ and mt.is_derived_from(c.table)
+ and mt.is_derived_from(f.table)
):
result[0] = True
- visitors.traverse(
- self.primaryjoin,
- {},
- {"binary": visit_binary}
- )
+
+ visitors.traverse(self.primaryjoin, {}, {"binary": visit_binary})
return result[0]
def _tables_overlap(self):
"""Return True if parent/child tables have some overlap."""
return selectables_overlap(
- self.parent_selectable, self.child_selectable)
+ self.parent_selectable, self.child_selectable
+ )
def _annotate_remote(self):
"""Annotate the primaryjoin and secondaryjoin
@@ -2411,7 +2559,9 @@ class JoinCondition(object):
elif self._local_remote_pairs or self._remote_side:
self._annotate_remote_from_args()
elif self._refers_to_parent_table():
- self._annotate_selfref(lambda col: "foreign" in col._annotations, False)
+ self._annotate_selfref(
+ lambda col: "foreign" in col._annotations, False
+ )
elif self._tables_overlap():
self._annotate_remote_with_overlap()
else:
@@ -2422,35 +2572,40 @@ class JoinCondition(object):
when 'secondary' is present.
"""
+
def repl(element):
if self.secondary.c.contains_column(element):
return element._annotate({"remote": True})
+
self.primaryjoin = visitors.replacement_traverse(
- self.primaryjoin, {}, repl)
+ self.primaryjoin, {}, repl
+ )
self.secondaryjoin = visitors.replacement_traverse(
- self.secondaryjoin, {}, repl)
+ self.secondaryjoin, {}, repl
+ )
def _annotate_selfref(self, fn, remote_side_given):
"""annotate 'remote' in primaryjoin, secondaryjoin
when the relationship is detected as self-referential.
"""
+
def visit_binary(binary):
equated = binary.left.compare(binary.right)
- if isinstance(binary.left, expression.ColumnClause) and \
- isinstance(binary.right, expression.ColumnClause):
+ if isinstance(binary.left, expression.ColumnClause) and isinstance(
+ binary.right, expression.ColumnClause
+ ):
# assume one to many - FKs are "remote"
if fn(binary.left):
binary.left = binary.left._annotate({"remote": True})
if fn(binary.right) and not equated:
- binary.right = binary.right._annotate(
- {"remote": True})
+ binary.right = binary.right._annotate({"remote": True})
elif not remote_side_given:
self._warn_non_column_elements()
self.primaryjoin = visitors.cloned_traverse(
- self.primaryjoin, {},
- {"binary": visit_binary})
+ self.primaryjoin, {}, {"binary": visit_binary}
+ )
def _annotate_remote_from_args(self):
"""annotate 'remote' in primaryjoin, secondaryjoin
@@ -2463,7 +2618,8 @@ class JoinCondition(object):
raise sa_exc.ArgumentError(
"remote_side argument is redundant "
"against more detailed _local_remote_side "
- "argument.")
+ "argument."
+ )
remote_side = [r for (l, r) in self._local_remote_pairs]
else:
@@ -2472,11 +2628,14 @@ class JoinCondition(object):
if self._refers_to_parent_table():
self._annotate_selfref(lambda col: col in remote_side, True)
else:
+
def repl(element):
if element in remote_side:
return element._annotate({"remote": True})
+
self.primaryjoin = visitors.replacement_traverse(
- self.primaryjoin, {}, repl)
+ self.primaryjoin, {}, repl
+ )
def _annotate_remote_with_overlap(self):
"""annotate 'remote' in primaryjoin, secondaryjoin
@@ -2485,26 +2644,36 @@ class JoinCondition(object):
relationship.
"""
+
def visit_binary(binary):
- binary.left, binary.right = proc_left_right(binary.left,
- binary.right)
- binary.right, binary.left = proc_left_right(binary.right,
- binary.left)
+ binary.left, binary.right = proc_left_right(
+ binary.left, binary.right
+ )
+ binary.right, binary.left = proc_left_right(
+ binary.right, binary.left
+ )
- check_entities = self.prop is not None and \
- self.prop.mapper is not self.prop.parent
+ check_entities = (
+ self.prop is not None and self.prop.mapper is not self.prop.parent
+ )
def proc_left_right(left, right):
- if isinstance(left, expression.ColumnClause) and \
- isinstance(right, expression.ColumnClause):
- if self.child_selectable.c.contains_column(right) and \
- self.parent_selectable.c.contains_column(left):
+ if isinstance(left, expression.ColumnClause) and isinstance(
+ right, expression.ColumnClause
+ ):
+ if self.child_selectable.c.contains_column(
+ right
+ ) and self.parent_selectable.c.contains_column(left):
right = right._annotate({"remote": True})
- elif check_entities and \
- right._annotations.get('parentmapper') is self.prop.mapper:
+ elif (
+ check_entities
+ and right._annotations.get("parentmapper") is self.prop.mapper
+ ):
right = right._annotate({"remote": True})
- elif check_entities and \
- left._annotations.get('parentmapper') is self.prop.mapper:
+ elif (
+ check_entities
+ and left._annotations.get("parentmapper") is self.prop.mapper
+ ):
left = left._annotate({"remote": True})
else:
self._warn_non_column_elements()
@@ -2512,8 +2681,8 @@ class JoinCondition(object):
return left, right
self.primaryjoin = visitors.cloned_traverse(
- self.primaryjoin, {},
- {"binary": visit_binary})
+ self.primaryjoin, {}, {"binary": visit_binary}
+ )
def _annotate_remote_distinct_selectables(self):
"""annotate 'remote' in primaryjoin, secondaryjoin
@@ -2521,22 +2690,23 @@ class JoinCondition(object):
separate.
"""
+
def repl(element):
- if self.child_selectable.c.contains_column(element) and \
- (not self.parent_local_selectable.c.
- contains_column(element) or
- self.child_local_selectable.c.
- contains_column(element)):
+ if self.child_selectable.c.contains_column(element) and (
+ not self.parent_local_selectable.c.contains_column(element)
+ or self.child_local_selectable.c.contains_column(element)
+ ):
return element._annotate({"remote": True})
+
self.primaryjoin = visitors.replacement_traverse(
- self.primaryjoin, {}, repl)
+ self.primaryjoin, {}, repl
+ )
def _warn_non_column_elements(self):
util.warn(
"Non-simple column elements in primary "
"join condition for property %s - consider using "
- "remote() annotations to mark the remote side."
- % self.prop
+ "remote() annotations to mark the remote side." % self.prop
)
def _annotate_local(self):
@@ -2554,15 +2724,16 @@ class JoinCondition(object):
return
if self._local_remote_pairs:
- local_side = util.column_set([l for (l, r)
- in self._local_remote_pairs])
+ local_side = util.column_set(
+ [l for (l, r) in self._local_remote_pairs]
+ )
else:
local_side = util.column_set(self.parent_selectable.c)
def locals_(elem):
- if "remote" not in elem._annotations and \
- elem in local_side:
+ if "remote" not in elem._annotations and elem in local_side:
return elem._annotate({"local": True})
+
self.primaryjoin = visitors.replacement_traverse(
self.primaryjoin, {}, locals_
)
@@ -2576,6 +2747,7 @@ class JoinCondition(object):
return elem._annotate({"parentmapper": self.prop.mapper})
elif "local" in elem._annotations:
return elem._annotate({"parentmapper": self.prop.parent})
+
self.primaryjoin = visitors.replacement_traverse(
self.primaryjoin, {}, parentmappers_
)
@@ -2583,14 +2755,15 @@ class JoinCondition(object):
def _check_remote_side(self):
if not self.local_remote_pairs:
raise sa_exc.ArgumentError(
- 'Relationship %s could '
- 'not determine any unambiguous local/remote column '
- 'pairs based on join condition and remote_side '
- 'arguments. '
- 'Consider using the remote() annotation to '
- 'accurately mark those elements of the join '
- 'condition that are on the remote side of '
- 'the relationship.' % (self.prop, ))
+ "Relationship %s could "
+ "not determine any unambiguous local/remote column "
+ "pairs based on join condition and remote_side "
+ "arguments. "
+ "Consider using the remote() annotation to "
+ "accurately mark those elements of the join "
+ "condition that are on the remote side of "
+ "the relationship." % (self.prop,)
+ )
def _check_foreign_cols(self, join_condition, primary):
"""Check the foreign key columns collected and emit error
@@ -2599,7 +2772,8 @@ class JoinCondition(object):
can_sync = False
foreign_cols = self._gather_columns_with_annotation(
- join_condition, "foreign")
+ join_condition, "foreign"
+ )
has_foreign = bool(foreign_cols)
@@ -2608,42 +2782,53 @@ class JoinCondition(object):
else:
can_sync = bool(self.secondary_synchronize_pairs)
- if self.support_sync and can_sync or \
- (not self.support_sync and has_foreign):
+ if (
+ self.support_sync
+ and can_sync
+ or (not self.support_sync and has_foreign)
+ ):
return
# from here below is just determining the best error message
# to report. Check for a join condition using any operator
# (not just ==), perhaps they need to turn on "viewonly=True".
if self.support_sync and has_foreign and not can_sync:
- err = "Could not locate any simple equality expressions "\
- "involving locally mapped foreign key columns for "\
- "%s join condition "\
- "'%s' on relationship %s." % (
- primary and 'primary' or 'secondary',
+ err = (
+ "Could not locate any simple equality expressions "
+ "involving locally mapped foreign key columns for "
+ "%s join condition "
+ "'%s' on relationship %s."
+ % (
+ primary and "primary" or "secondary",
join_condition,
- self.prop
+ self.prop,
)
- err += \
- " Ensure that referencing columns are associated "\
- "with a ForeignKey or ForeignKeyConstraint, or are "\
- "annotated in the join condition with the foreign() "\
- "annotation. To allow comparison operators other than "\
+ )
+ err += (
+ " Ensure that referencing columns are associated "
+ "with a ForeignKey or ForeignKeyConstraint, or are "
+ "annotated in the join condition with the foreign() "
+ "annotation. To allow comparison operators other than "
"'==', the relationship can be marked as viewonly=True."
+ )
raise sa_exc.ArgumentError(err)
else:
- err = "Could not locate any relevant foreign key columns "\
- "for %s join condition '%s' on relationship %s." % (
- primary and 'primary' or 'secondary',
+ err = (
+ "Could not locate any relevant foreign key columns "
+ "for %s join condition '%s' on relationship %s."
+ % (
+ primary and "primary" or "secondary",
join_condition,
- self.prop
+ self.prop,
)
- err += \
- ' Ensure that referencing columns are associated '\
- 'with a ForeignKey or ForeignKeyConstraint, or are '\
- 'annotated in the join condition with the foreign() '\
- 'annotation.'
+ )
+ err += (
+ " Ensure that referencing columns are associated "
+ "with a ForeignKey or ForeignKeyConstraint, or are "
+ "annotated in the join condition with the foreign() "
+ "annotation."
+ )
raise sa_exc.ArgumentError(err)
def _determine_direction(self):
@@ -2658,13 +2843,11 @@ class JoinCondition(object):
targetcols = util.column_set(self.child_selectable.c)
# fk collection which suggests ONETOMANY.
- onetomany_fk = targetcols.intersection(
- self.foreign_key_columns)
+ onetomany_fk = targetcols.intersection(self.foreign_key_columns)
# fk collection which suggests MANYTOONE.
- manytoone_fk = parentcols.intersection(
- self.foreign_key_columns)
+ manytoone_fk = parentcols.intersection(self.foreign_key_columns)
if onetomany_fk and manytoone_fk:
# fks on both sides. test for overlap of local/remote
@@ -2676,15 +2859,20 @@ class JoinCondition(object):
# 1. columns that are both remote and FK suggest
# onetomany.
onetomany_local = self._gather_columns_with_annotation(
- self.primaryjoin, "remote", "foreign")
+ self.primaryjoin, "remote", "foreign"
+ )
# 2. columns that are FK but are not remote (e.g. local)
# suggest manytoone.
- manytoone_local = set([c for c in
- self._gather_columns_with_annotation(
- self.primaryjoin,
- "foreign")
- if "remote" not in c._annotations])
+ manytoone_local = set(
+ [
+ c
+ for c in self._gather_columns_with_annotation(
+ self.primaryjoin, "foreign"
+ )
+ if "remote" not in c._annotations
+ ]
+ )
# 3. if both collections are present, remove columns that
# refer to themselves. This is for the case of
@@ -2713,7 +2901,8 @@ class JoinCondition(object):
"Ensure that only those columns referring "
"to a parent column are marked as foreign, "
"either via the foreign() annotation or "
- "via the foreign_keys argument." % self.prop)
+ "via the foreign_keys argument." % self.prop
+ )
elif onetomany_fk:
self.direction = ONETOMANY
elif manytoone_fk:
@@ -2723,7 +2912,8 @@ class JoinCondition(object):
"Can't determine relationship "
"direction for relationship '%s' - foreign "
"key columns are present in neither the parent "
- "nor the child's mapped tables" % self.prop)
+ "nor the child's mapped tables" % self.prop
+ )
def _deannotate_pairs(self, collection):
"""provide deannotation for the various lists of
@@ -2732,8 +2922,7 @@ class JoinCondition(object):
original columns mapped.
"""
- return [(x._deannotate(), y._deannotate())
- for x, y in collection]
+ return [(x._deannotate(), y._deannotate()) for x, y in collection]
def _setup_pairs(self):
sync_pairs = []
@@ -2742,25 +2931,31 @@ class JoinCondition(object):
def go(joincond, collection):
def visit_binary(binary, left, right):
- if "remote" in right._annotations and \
- "remote" not in left._annotations and \
- self.can_be_synced_fn(left):
+ if (
+ "remote" in right._annotations
+ and "remote" not in left._annotations
+ and self.can_be_synced_fn(left)
+ ):
lrp.add((left, right))
- elif "remote" in left._annotations and \
- "remote" not in right._annotations and \
- self.can_be_synced_fn(right):
+ elif (
+ "remote" in left._annotations
+ and "remote" not in right._annotations
+ and self.can_be_synced_fn(right)
+ ):
lrp.add((right, left))
- if binary.operator is operators.eq and \
- self.can_be_synced_fn(left, right):
+ if binary.operator is operators.eq and self.can_be_synced_fn(
+ left, right
+ ):
if "foreign" in right._annotations:
collection.append((left, right))
elif "foreign" in left._annotations:
collection.append((right, left))
+
visit_binary_product(visit_binary, joincond)
for joincond, collection in [
(self.primaryjoin, sync_pairs),
- (self.secondaryjoin, secondary_sync_pairs)
+ (self.secondaryjoin, secondary_sync_pairs),
]:
if joincond is None:
continue
@@ -2768,8 +2963,9 @@ class JoinCondition(object):
self.local_remote_pairs = self._deannotate_pairs(lrp)
self.synchronize_pairs = self._deannotate_pairs(sync_pairs)
- self.secondary_synchronize_pairs = \
- self._deannotate_pairs(secondary_sync_pairs)
+ self.secondary_synchronize_pairs = self._deannotate_pairs(
+ secondary_sync_pairs
+ )
_track_overlapping_sync_targets = weakref.WeakKeyDictionary()
@@ -2797,20 +2993,23 @@ class JoinCondition(object):
continue
if to_ not in self._track_overlapping_sync_targets:
- self._track_overlapping_sync_targets[to_] = \
- weakref.WeakKeyDictionary({self.prop: from_})
+ self._track_overlapping_sync_targets[
+ to_
+ ] = weakref.WeakKeyDictionary({self.prop: from_})
else:
other_props = []
prop_to_from = self._track_overlapping_sync_targets[to_]
for pr, fr_ in prop_to_from.items():
- if pr.mapper in mapperlib._mapper_registry and \
- (
- self.prop._persists_for(pr.parent) or
- pr._persists_for(self.prop.parent)
- ) and \
- fr_ is not from_ and \
- pr not in self.prop._reverse_property:
+ if (
+ pr.mapper in mapperlib._mapper_registry
+ and (
+ self.prop._persists_for(pr.parent)
+ or pr._persists_for(self.prop.parent)
+ )
+ and fr_ is not from_
+ and pr not in self.prop._reverse_property
+ ):
other_props.append((pr, fr_))
@@ -2821,12 +3020,15 @@ class JoinCondition(object):
"Consider applying "
"viewonly=True to read-only relationships, or provide "
"a primaryjoin condition marking writable columns "
- "with the foreign() annotation." % (
+ "with the foreign() annotation."
+ % (
self.prop,
- from_, to_,
+ from_,
+ to_,
", ".join(
"'%s' (copies %s to %s)" % (pr, fr_, to_)
- for (pr, fr_) in other_props)
+ for (pr, fr_) in other_props
+ ),
)
)
self._track_overlapping_sync_targets[to_][self.prop] = from_
@@ -2845,27 +3047,29 @@ class JoinCondition(object):
def _gather_join_annotations(self, annotation):
s = set(
- self._gather_columns_with_annotation(
- self.primaryjoin, annotation)
+ self._gather_columns_with_annotation(self.primaryjoin, annotation)
)
if self.secondaryjoin is not None:
s.update(
self._gather_columns_with_annotation(
- self.secondaryjoin, annotation)
+ self.secondaryjoin, annotation
+ )
)
return {x._deannotate() for x in s}
def _gather_columns_with_annotation(self, clause, *annotation):
annotation = set(annotation)
- return set([
- col for col in visitors.iterate(clause, {})
- if annotation.issubset(col._annotations)
- ])
-
- def join_targets(self, source_selectable,
- dest_selectable,
- aliased,
- single_crit=None):
+ return set(
+ [
+ col
+ for col in visitors.iterate(clause, {})
+ if annotation.issubset(col._annotations)
+ ]
+ )
+
+ def join_targets(
+ self, source_selectable, dest_selectable, aliased, single_crit=None
+ ):
"""Given a source and destination selectable, create a
join between them.
@@ -2881,11 +3085,14 @@ class JoinCondition(object):
# its internal structure remains fixed
# regardless of context.
dest_selectable = _shallow_annotate(
- dest_selectable,
- {'no_replacement_traverse': True})
+ dest_selectable, {"no_replacement_traverse": True}
+ )
- primaryjoin, secondaryjoin, secondary = self.primaryjoin, \
- self.secondaryjoin, self.secondary
+ primaryjoin, secondaryjoin, secondary = (
+ self.primaryjoin,
+ self.secondaryjoin,
+ self.secondary,
+ )
# adjust the join condition for single table inheritance,
# in the case that the join is to a subclass
@@ -2902,28 +3109,31 @@ class JoinCondition(object):
if secondary is not None:
secondary = secondary.alias(flat=True)
primary_aliasizer = ClauseAdapter(secondary)
- secondary_aliasizer = \
- ClauseAdapter(dest_selectable,
- equivalents=self.child_equivalents).\
- chain(primary_aliasizer)
+ secondary_aliasizer = ClauseAdapter(
+ dest_selectable, equivalents=self.child_equivalents
+ ).chain(primary_aliasizer)
if source_selectable is not None:
- primary_aliasizer = \
- ClauseAdapter(secondary).\
- chain(ClauseAdapter(
+ primary_aliasizer = ClauseAdapter(secondary).chain(
+ ClauseAdapter(
source_selectable,
- equivalents=self.parent_equivalents))
- secondaryjoin = \
- secondary_aliasizer.traverse(secondaryjoin)
+ equivalents=self.parent_equivalents,
+ )
+ )
+ secondaryjoin = secondary_aliasizer.traverse(secondaryjoin)
else:
primary_aliasizer = ClauseAdapter(
dest_selectable,
exclude_fn=_ColInAnnotations("local"),
- equivalents=self.child_equivalents)
+ equivalents=self.child_equivalents,
+ )
if source_selectable is not None:
primary_aliasizer.chain(
- ClauseAdapter(source_selectable,
- exclude_fn=_ColInAnnotations("remote"),
- equivalents=self.parent_equivalents))
+ ClauseAdapter(
+ source_selectable,
+ exclude_fn=_ColInAnnotations("remote"),
+ equivalents=self.parent_equivalents,
+ )
+ )
secondary_aliasizer = None
primaryjoin = primary_aliasizer.traverse(primaryjoin)
@@ -2931,8 +3141,13 @@ class JoinCondition(object):
target_adapter.exclude_fn = None
else:
target_adapter = None
- return primaryjoin, secondaryjoin, secondary, \
- target_adapter, dest_selectable
+ return (
+ primaryjoin,
+ secondaryjoin,
+ secondary,
+ target_adapter,
+ dest_selectable,
+ )
def create_lazy_clause(self, reverse_direction=False):
binds = util.column_dict()
@@ -2955,28 +3170,32 @@ class JoinCondition(object):
def col_to_bind(col):
if (
- (not reverse_direction and 'local' in col._annotations) or
- reverse_direction and (
- (has_secondary and col in lookup) or
- (not has_secondary and 'remote' in col._annotations)
+ (not reverse_direction and "local" in col._annotations)
+ or reverse_direction
+ and (
+ (has_secondary and col in lookup)
+ or (not has_secondary and "remote" in col._annotations)
)
):
if col not in binds:
binds[col] = sql.bindparam(
- None, None, type_=col.type, unique=True)
+ None, None, type_=col.type, unique=True
+ )
return binds[col]
return None
lazywhere = self.primaryjoin
if self.secondaryjoin is None or not reverse_direction:
lazywhere = visitors.replacement_traverse(
- lazywhere, {}, col_to_bind)
+ lazywhere, {}, col_to_bind
+ )
if self.secondaryjoin is not None:
secondaryjoin = self.secondaryjoin
if reverse_direction:
secondaryjoin = visitors.replacement_traverse(
- secondaryjoin, {}, col_to_bind)
+ secondaryjoin, {}, col_to_bind
+ )
lazywhere = sql.and_(lazywhere, secondaryjoin)
bind_to_col = {binds[col].key: col for col in binds}
diff --git a/lib/sqlalchemy/orm/scoping.py b/lib/sqlalchemy/orm/scoping.py
index 2e16872f9..2eeaf5b6d 100644
--- a/lib/sqlalchemy/orm/scoping.py
+++ b/lib/sqlalchemy/orm/scoping.py
@@ -11,7 +11,7 @@ from . import class_mapper, exc as orm_exc
from .session import Session
-__all__ = ['scoped_session']
+__all__ = ["scoped_session"]
class scoped_session(object):
@@ -65,7 +65,8 @@ class scoped_session(object):
if self.registry.has():
raise sa_exc.InvalidRequestError(
"Scoped session is already present; "
- "no new arguments may be specified.")
+ "no new arguments may be specified."
+ )
else:
sess = self.session_factory(**kw)
self.registry.set(sess)
@@ -99,9 +100,11 @@ class scoped_session(object):
"""
if self.registry.has():
- warn('At least one scoped session is already present. '
- ' configure() can not affect sessions that have '
- 'already been created.')
+ warn(
+ "At least one scoped session is already present. "
+ " configure() can not affect sessions that have "
+ "already been created."
+ )
self.session_factory.configure(**kwargs)
@@ -129,6 +132,7 @@ class scoped_session(object):
a class.
"""
+
class query(object):
def __get__(s, instance, owner):
try:
@@ -142,8 +146,10 @@ class scoped_session(object):
return self.registry().query(mapper)
except orm_exc.UnmappedClassError:
return None
+
return query()
+
ScopedSession = scoped_session
"""Old name for backwards compatibility."""
@@ -151,8 +157,10 @@ ScopedSession = scoped_session
def instrument(name):
def do(self, *args, **kwargs):
return getattr(self.registry(), name)(*args, **kwargs)
+
return do
+
for meth in Session.public_methods:
setattr(scoped_session, meth, instrument(meth))
@@ -166,16 +174,28 @@ def makeprop(name):
return property(get, set)
-for prop in ('bind', 'dirty', 'deleted', 'new', 'identity_map',
- 'is_active', 'autoflush', 'no_autoflush', 'info',
- 'autocommit'):
+
+for prop in (
+ "bind",
+ "dirty",
+ "deleted",
+ "new",
+ "identity_map",
+ "is_active",
+ "autoflush",
+ "no_autoflush",
+ "info",
+ "autocommit",
+):
setattr(scoped_session, prop, makeprop(prop))
def clslevel(name):
def do(cls, *args, **kwargs):
return getattr(Session, name)(*args, **kwargs)
+
return classmethod(do)
-for prop in ('close_all', 'object_session', 'identity_key'):
+
+for prop in ("close_all", "object_session", "identity_key"):
setattr(scoped_session, prop, clslevel(prop))
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index b1993118d..a3edacc19 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -10,15 +10,17 @@
import weakref
from .. import util, sql, engine, exc as sa_exc
from ..sql import util as sql_util, expression
-from . import (
- SessionExtension, attributes, exc, query,
- loading, identity
-)
+from . import SessionExtension, attributes, exc, query, loading, identity
from ..inspection import inspect
from .base import (
- object_mapper, class_mapper,
- _class_to_mapper, _state_mapper, object_state,
- _none_set, state_str, instance_str
+ object_mapper,
+ class_mapper,
+ _class_to_mapper,
+ _state_mapper,
+ object_state,
+ _none_set,
+ state_str,
+ instance_str,
)
import itertools
from . import persistence
@@ -26,8 +28,7 @@ from .unitofwork import UOWTransaction
from . import state as statelib
import sys
-__all__ = ['Session', 'SessionTransaction',
- 'SessionExtension', 'sessionmaker']
+__all__ = ["Session", "SessionTransaction", "SessionExtension", "sessionmaker"]
_sessions = weakref.WeakValueDictionary()
"""Weak-referencing dictionary of :class:`.Session` objects.
@@ -77,11 +78,11 @@ class _SessionClassMethods(object):
return object_session(instance)
-ACTIVE = util.symbol('ACTIVE')
-PREPARED = util.symbol('PREPARED')
-COMMITTED = util.symbol('COMMITTED')
-DEACTIVE = util.symbol('DEACTIVE')
-CLOSED = util.symbol('CLOSED')
+ACTIVE = util.symbol("ACTIVE")
+PREPARED = util.symbol("PREPARED")
+COMMITTED = util.symbol("COMMITTED")
+DEACTIVE = util.symbol("DEACTIVE")
+CLOSED = util.symbol("CLOSED")
class SessionTransaction(object):
@@ -212,7 +213,8 @@ class SessionTransaction(object):
if not parent and nested:
raise sa_exc.InvalidRequestError(
"Can't start a SAVEPOINT transaction when no existing "
- "transaction is in progress")
+ "transaction is in progress"
+ )
if self.session._enable_transaction_accounting:
self._take_snapshot()
@@ -249,10 +251,13 @@ class SessionTransaction(object):
def is_active(self):
return self.session is not None and self._state is ACTIVE
- def _assert_active(self, prepared_ok=False,
- rollback_ok=False,
- deactive_ok=False,
- closed_msg="This transaction is closed"):
+ def _assert_active(
+ self,
+ prepared_ok=False,
+ rollback_ok=False,
+ deactive_ok=False,
+ closed_msg="This transaction is closed",
+ ):
if self._state is COMMITTED:
raise sa_exc.InvalidRequestError(
"This session is in 'committed' state; no further "
@@ -295,21 +300,21 @@ class SessionTransaction(object):
def _begin(self, nested=False):
self._assert_active()
- return SessionTransaction(
- self.session, self, nested=nested)
+ return SessionTransaction(self.session, self, nested=nested)
def _iterate_self_and_parents(self, upto=None):
current = self
result = ()
while current:
- result += (current, )
+ result += (current,)
if current._parent is upto:
break
elif current._parent is None:
raise sa_exc.InvalidRequestError(
- "Transaction %s is not on the active transaction list" % (
- upto))
+ "Transaction %s is not on the active transaction list"
+ % (upto)
+ )
else:
current = current._parent
@@ -376,7 +381,8 @@ class SessionTransaction(object):
s._expire(s.dict, self.session.identity_map._modified)
statelib.InstanceState._detach_states(
- list(self._deleted), self.session)
+ list(self._deleted), self.session
+ )
self._deleted.clear()
elif self.nested:
self._parent._new.update(self._new)
@@ -391,7 +397,8 @@ class SessionTransaction(object):
if execution_options:
util.warn(
"Connection is already established for the "
- "given bind; execution_options ignored")
+ "given bind; execution_options ignored"
+ )
return self._connections[bind][0]
if self._parent:
@@ -404,7 +411,8 @@ class SessionTransaction(object):
if conn.engine in self._connections:
raise sa_exc.InvalidRequestError(
"Session already has a Connection associated for the "
- "given Connection's Engine")
+ "given Connection's Engine"
+ )
else:
conn = bind.contextual_connect()
@@ -418,8 +426,11 @@ class SessionTransaction(object):
else:
transaction = conn.begin()
- self._connections[conn] = self._connections[conn.engine] = \
- (conn, transaction, conn is not bind)
+ self._connections[conn] = self._connections[conn.engine] = (
+ conn,
+ transaction,
+ conn is not bind,
+ )
self.session.dispatch.after_begin(self.session, self, conn)
return conn
@@ -427,7 +438,8 @@ class SessionTransaction(object):
if self._parent is not None or not self.session.twophase:
raise sa_exc.InvalidRequestError(
"'twophase' mode not enabled, or not root transaction; "
- "can't prepare.")
+ "can't prepare."
+ )
self._prepare_impl()
def _prepare_impl(self):
@@ -449,7 +461,8 @@ class SessionTransaction(object):
raise exc.FlushError(
"Over 100 subsequent flushes have occurred within "
"session.commit() - is an after_flush() hook "
- "creating new objects?")
+ "creating new objects?"
+ )
if self._parent is None and self.session.twophase:
try:
@@ -504,7 +517,8 @@ class SessionTransaction(object):
transaction._state = DEACTIVE
if self.session._enable_transaction_accounting:
transaction._restore_snapshot(
- dirty_only=transaction.nested)
+ dirty_only=transaction.nested
+ )
boundary = transaction
break
else:
@@ -512,15 +526,19 @@ class SessionTransaction(object):
sess = self.session
- if not rollback_err and sess._enable_transaction_accounting and \
- not sess._is_clean():
+ if (
+ not rollback_err
+ and sess._enable_transaction_accounting
+ and not sess._is_clean()
+ ):
# if items were added, deleted, or mutated
# here, we need to re-restore the snapshot
util.warn(
"Session's state has been changed on "
"a non-active transaction - this state "
- "will be discarded.")
+ "will be discarded."
+ )
boundary._restore_snapshot(dirty_only=boundary.nested)
self.close()
@@ -535,12 +553,12 @@ class SessionTransaction(object):
return self._parent
-
def close(self, invalidate=False):
self.session.transaction = self._parent
if self._parent is None:
- for connection, transaction, autoclose in \
- set(self._connections.values()):
+ for connection, transaction, autoclose in set(
+ self._connections.values()
+ ):
if invalidate:
connection.invalidate()
if autoclose:
@@ -583,21 +601,49 @@ class Session(_SessionClassMethods):
"""
public_methods = (
- '__contains__', '__iter__', 'add', 'add_all', 'begin', 'begin_nested',
- 'close', 'commit', 'connection', 'delete', 'execute', 'expire',
- 'expire_all', 'expunge', 'expunge_all', 'flush', 'get_bind',
- 'is_modified', 'bulk_save_objects', 'bulk_insert_mappings',
- 'bulk_update_mappings',
- 'merge', 'query', 'refresh', 'rollback',
- 'scalar')
-
- def __init__(self, bind=None, autoflush=True, expire_on_commit=True,
- _enable_transaction_accounting=True,
- autocommit=False, twophase=False,
- weak_identity_map=True, binds=None, extension=None,
- enable_baked_queries=True,
- info=None,
- query_cls=query.Query):
+ "__contains__",
+ "__iter__",
+ "add",
+ "add_all",
+ "begin",
+ "begin_nested",
+ "close",
+ "commit",
+ "connection",
+ "delete",
+ "execute",
+ "expire",
+ "expire_all",
+ "expunge",
+ "expunge_all",
+ "flush",
+ "get_bind",
+ "is_modified",
+ "bulk_save_objects",
+ "bulk_insert_mappings",
+ "bulk_update_mappings",
+ "merge",
+ "query",
+ "refresh",
+ "rollback",
+ "scalar",
+ )
+
+ def __init__(
+ self,
+ bind=None,
+ autoflush=True,
+ expire_on_commit=True,
+ _enable_transaction_accounting=True,
+ autocommit=False,
+ twophase=False,
+ weak_identity_map=True,
+ binds=None,
+ extension=None,
+ enable_baked_queries=True,
+ info=None,
+ query_cls=query.Query,
+ ):
r"""Construct a new Session.
See also the :class:`.sessionmaker` function which is used to
@@ -753,12 +799,13 @@ class Session(_SessionClassMethods):
"weak_identity_map=False is deprecated. "
"See the documentation on 'Session Referencing Behavior' "
"for an event-based approach to maintaining strong identity "
- "references.")
+ "references."
+ )
self._identity_cls = identity.StrongInstanceDict
self.identity_map = self._identity_cls()
- self._new = {} # InstanceState->object, strong refs object
+ self._new = {} # InstanceState->object, strong refs object
self._deleted = {} # same
self.bind = bind
self.__binds = {}
@@ -861,15 +908,14 @@ class Session(_SessionClassMethods):
"""
if self.transaction is not None:
if subtransactions or nested:
- self.transaction = self.transaction._begin(
- nested=nested)
+ self.transaction = self.transaction._begin(nested=nested)
else:
raise sa_exc.InvalidRequestError(
"A transaction is already begun. Use "
- "subtransactions=True to allow subtransactions.")
+ "subtransactions=True to allow subtransactions."
+ )
else:
- self.transaction = SessionTransaction(
- self, nested=nested)
+ self.transaction = SessionTransaction(self, nested=nested)
return self.transaction # needed for __enter__/__exit__ hook
def begin_nested(self):
@@ -972,11 +1018,15 @@ class Session(_SessionClassMethods):
self.transaction.prepare()
- def connection(self, mapper=None, clause=None,
- bind=None,
- close_with_result=False,
- execution_options=None,
- **kw):
+ def connection(
+ self,
+ mapper=None,
+ clause=None,
+ bind=None,
+ close_with_result=False,
+ execution_options=None,
+ **kw
+ ):
r"""Return a :class:`.Connection` object corresponding to this
:class:`.Session` object's transactional state.
@@ -1041,14 +1091,17 @@ class Session(_SessionClassMethods):
if bind is None:
bind = self.get_bind(mapper, clause=clause, **kw)
- return self._connection_for_bind(bind,
- close_with_result=close_with_result,
- execution_options=execution_options)
+ return self._connection_for_bind(
+ bind,
+ close_with_result=close_with_result,
+ execution_options=execution_options,
+ )
def _connection_for_bind(self, engine, execution_options=None, **kw):
if self.transaction is not None:
return self.transaction._connection_for_bind(
- engine, execution_options)
+ engine, execution_options
+ )
else:
conn = engine.contextual_connect(**kw)
if execution_options:
@@ -1183,14 +1236,16 @@ class Session(_SessionClassMethods):
if bind is None:
bind = self.get_bind(mapper, clause=clause, **kw)
- return self._connection_for_bind(
- bind, close_with_result=True).execute(clause, params or {})
+ return self._connection_for_bind(bind, close_with_result=True).execute(
+ clause, params or {}
+ )
def scalar(self, clause, params=None, mapper=None, bind=None, **kw):
"""Like :meth:`~.Session.execute` but return a scalar result."""
return self.execute(
- clause, params=params, mapper=mapper, bind=bind, **kw).scalar()
+ clause, params=params, mapper=mapper, bind=bind, **kw
+ ).scalar()
def close(self):
"""Close this Session.
@@ -1256,9 +1311,7 @@ class Session(_SessionClassMethods):
self._new = {}
self._deleted = {}
- statelib.InstanceState._detach_states(
- all_states, self
- )
+ statelib.InstanceState._detach_states(all_states, self)
def _add_bind(self, key, bind):
try:
@@ -1266,7 +1319,8 @@ class Session(_SessionClassMethods):
except sa_exc.NoInspectionAvailable:
if not isinstance(key, type):
raise sa_exc.ArgumentError(
- "Not an acceptable bind target: %s" % key)
+ "Not an acceptable bind target: %s" % key
+ )
else:
self.__binds[key] = bind
else:
@@ -1278,7 +1332,8 @@ class Session(_SessionClassMethods):
self.__binds[selectable] = bind
else:
raise sa_exc.ArgumentError(
- "Not an acceptable bind target: %s" % key)
+ "Not an acceptable bind target: %s" % key
+ )
def bind_mapper(self, mapper, bind):
"""Associate a :class:`.Mapper` or arbitrary Python class with a
@@ -1408,7 +1463,8 @@ class Session(_SessionClassMethods):
raise sa_exc.UnboundExecutionError(
"This session is not bound to a single Engine or "
"Connection, and no context was provided to locate "
- "a binding.")
+ "a binding."
+ )
if mapper is not None:
try:
@@ -1443,13 +1499,14 @@ class Session(_SessionClassMethods):
context = []
if mapper is not None:
- context.append('mapper %s' % mapper)
+ context.append("mapper %s" % mapper)
if clause is not None:
- context.append('SQL expression')
+ context.append("SQL expression")
raise sa_exc.UnboundExecutionError(
- "Could not locate a bind configured on %s or this Session" % (
- ', '.join(context)))
+ "Could not locate a bind configured on %s or this Session"
+ % (", ".join(context))
+ )
def query(self, *entities, **kwargs):
"""Return a new :class:`.Query` object corresponding to this
@@ -1499,12 +1556,17 @@ class Session(_SessionClassMethods):
e.add_detail(
"raised as a result of Query-invoked autoflush; "
"consider using a session.no_autoflush block if this "
- "flush is occurring prematurely")
+ "flush is occurring prematurely"
+ )
util.raise_from_cause(e)
def refresh(
- self, instance, attribute_names=None, with_for_update=None,
- lockmode=None):
+ self,
+ instance,
+ attribute_names=None,
+ with_for_update=None,
+ lockmode=None,
+ ):
"""Expire and refresh the attributes on the given instance.
A query will be issued to the database and all attributes will be
@@ -1560,7 +1622,8 @@ class Session(_SessionClassMethods):
raise sa_exc.ArgumentError(
"with_for_update should be the boolean value "
"True, or a dictionary with options. "
- "A blank dictionary is ambiguous.")
+ "A blank dictionary is ambiguous."
+ )
if lockmode:
with_for_update = query.LockmodeArg.parse_legacy_query(lockmode)
@@ -1572,14 +1635,19 @@ class Session(_SessionClassMethods):
else:
with_for_update = None
- if loading.load_on_ident(
+ if (
+ loading.load_on_ident(
self.query(object_mapper(instance)),
- state.key, refresh_state=state,
+ state.key,
+ refresh_state=state,
with_for_update=with_for_update,
- only_load_props=attribute_names) is None:
+ only_load_props=attribute_names,
+ )
+ is None
+ ):
raise sa_exc.InvalidRequestError(
- "Could not refresh instance '%s'" %
- instance_str(instance))
+ "Could not refresh instance '%s'" % instance_str(instance)
+ )
def expire_all(self):
"""Expires all persistent instances within this Session.
@@ -1662,8 +1730,9 @@ class Session(_SessionClassMethods):
else:
# pre-fetch the full cascade since the expire is going to
# remove associations
- cascaded = list(state.manager.mapper.cascade_iterator(
- 'refresh-expire', state))
+ cascaded = list(
+ state.manager.mapper.cascade_iterator("refresh-expire", state)
+ )
self._conditional_expire(state)
for o, m, st_, dct_ in cascaded:
self._conditional_expire(st_)
@@ -1677,8 +1746,11 @@ class Session(_SessionClassMethods):
self._new.pop(state)
state._detach(self)
- @util.deprecated("0.7", "The non-weak-referencing identity map "
- "feature is no longer needed.")
+ @util.deprecated(
+ "0.7",
+ "The non-weak-referencing identity map "
+ "feature is no longer needed.",
+ )
def prune(self):
"""Remove unreferenced instances cached in the identity map.
@@ -1705,14 +1777,13 @@ class Session(_SessionClassMethods):
raise exc.UnmappedInstanceError(instance)
if state.session_id is not self.hash_key:
raise sa_exc.InvalidRequestError(
- "Instance %s is not present in this Session" %
- state_str(state))
+ "Instance %s is not present in this Session" % state_str(state)
+ )
- cascaded = list(state.manager.mapper.cascade_iterator(
- 'expunge', state))
- self._expunge_states(
- [state] + [st_ for o, m, st_, dct_ in cascaded]
+ cascaded = list(
+ state.manager.mapper.cascade_iterator("expunge", state)
)
+ self._expunge_states([state] + [st_ for o, m, st_, dct_ in cascaded])
def _expunge_states(self, states, to_transient=False):
for state in states:
@@ -1726,7 +1797,8 @@ class Session(_SessionClassMethods):
# in the transaction snapshot
self.transaction._deleted.pop(state, None)
statelib.InstanceState._detach_states(
- states, self, to_transient=to_transient)
+ states, self, to_transient=to_transient
+ )
def _register_newly_persistent(self, states):
pending_to_persistent = self.dispatch.pending_to_persistent or None
@@ -1739,9 +1811,11 @@ class Session(_SessionClassMethods):
instance_key = mapper._identity_key_from_state(state)
- if _none_set.intersection(instance_key[1]) and \
- not mapper.allow_partial_pks or \
- _none_set.issuperset(instance_key[1]):
+ if (
+ _none_set.intersection(instance_key[1])
+ and not mapper.allow_partial_pks
+ or _none_set.issuperset(instance_key[1])
+ ):
raise exc.FlushError(
"Instance %s has a NULL identity key. If this is an "
"auto-generated value, check that the database table "
@@ -1765,15 +1839,16 @@ class Session(_SessionClassMethods):
else:
orig_key = state.key
self.transaction._key_switches[state] = (
- orig_key, instance_key)
+ orig_key,
+ instance_key,
+ )
state.key = instance_key
self.identity_map.replace(state)
state._orphaned_outside_of_session = False
statelib.InstanceState._commit_all_states(
- ((state, state.dict) for state in states),
- self.identity_map
+ ((state, state.dict) for state in states), self.identity_map
)
self._register_altered(states)
@@ -1849,9 +1924,8 @@ class Session(_SessionClassMethods):
mapper = _state_mapper(state)
for o, m, st_, dct_ in mapper.cascade_iterator(
- 'save-update',
- state,
- halt_on=self._contains_state):
+ "save-update", state, halt_on=self._contains_state
+ ):
self._save_or_update_impl(st_)
def delete(self, instance):
@@ -1875,8 +1949,8 @@ class Session(_SessionClassMethods):
if state.key is None:
if head:
raise sa_exc.InvalidRequestError(
- "Instance '%s' is not persisted" %
- state_str(state))
+ "Instance '%s' is not persisted" % state_str(state)
+ )
else:
return
@@ -1894,8 +1968,9 @@ class Session(_SessionClassMethods):
# grab the cascades before adding the item to the deleted list
# so that autoflush does not delete the item
# the strong reference to the instance itself is significant here
- cascade_states = list(state.manager.mapper.cascade_iterator(
- 'delete', state))
+ cascade_states = list(
+ state.manager.mapper.cascade_iterator("delete", state)
+ )
self._deleted[state] = obj
@@ -1975,13 +2050,21 @@ class Session(_SessionClassMethods):
return self._merge(
attributes.instance_state(instance),
attributes.instance_dict(instance),
- load=load, _recursive=_recursive,
- _resolve_conflict_map=_resolve_conflict_map)
+ load=load,
+ _recursive=_recursive,
+ _resolve_conflict_map=_resolve_conflict_map,
+ )
finally:
self.autoflush = autoflush
- def _merge(self, state, state_dict, load=True, _recursive=None,
- _resolve_conflict_map=None):
+ def _merge(
+ self,
+ state,
+ state_dict,
+ load=True,
+ _recursive=None,
+ _resolve_conflict_map=None,
+ ):
mapper = _state_mapper(state)
if state in _recursive:
return _recursive[state]
@@ -1995,11 +2078,15 @@ class Session(_SessionClassMethods):
"merge() with load=False option does not support "
"objects transient (i.e. unpersisted) objects. flush() "
"all changes on mapped instances before merging with "
- "load=False.")
+ "load=False."
+ )
key = mapper._identity_key_from_state(state)
key_is_persistent = attributes.NEVER_SET not in key[1] and (
- not _none_set.intersection(key[1]) or
- (mapper.allow_partial_pks and not _none_set.issuperset(key[1]))
+ not _none_set.intersection(key[1])
+ or (
+ mapper.allow_partial_pks
+ and not _none_set.issuperset(key[1])
+ )
)
else:
key_is_persistent = True
@@ -2022,7 +2109,8 @@ class Session(_SessionClassMethods):
raise sa_exc.InvalidRequestError(
"merge() with load=False option does not support "
"objects marked as 'dirty'. flush() all changes on "
- "mapped instances before merging with load=False.")
+ "mapped instances before merging with load=False."
+ )
merged = mapper.class_manager.new_instance()
merged_state = attributes.instance_state(merged)
merged_state.key = key
@@ -2054,17 +2142,21 @@ class Session(_SessionClassMethods):
state,
state_dict,
mapper.version_id_col,
- passive=attributes.PASSIVE_NO_INITIALIZE)
+ passive=attributes.PASSIVE_NO_INITIALIZE,
+ )
merged_version = mapper._get_state_attr_by_column(
merged_state,
merged_dict,
mapper.version_id_col,
- passive=attributes.PASSIVE_NO_INITIALIZE)
+ passive=attributes.PASSIVE_NO_INITIALIZE,
+ )
- if existing_version is not attributes.PASSIVE_NO_RESULT and \
- merged_version is not attributes.PASSIVE_NO_RESULT and \
- existing_version != merged_version:
+ if (
+ existing_version is not attributes.PASSIVE_NO_RESULT
+ and merged_version is not attributes.PASSIVE_NO_RESULT
+ and existing_version != merged_version
+ ):
raise exc.StaleDataError(
"Version id '%s' on merged state %s "
"does not match existing version '%s'. "
@@ -2073,8 +2165,9 @@ class Session(_SessionClassMethods):
% (
existing_version,
state_str(merged_state),
- merged_version
- ))
+ merged_version,
+ )
+ )
merged_state.load_path = state.load_path
merged_state.load_options = state.load_options
@@ -2087,9 +2180,16 @@ class Session(_SessionClassMethods):
merged_state._copy_callables(state)
for prop in mapper.iterate_properties:
- prop.merge(self, state, state_dict,
- merged_state, merged_dict,
- load, _recursive, _resolve_conflict_map)
+ prop.merge(
+ self,
+ state,
+ state_dict,
+ merged_state,
+ merged_dict,
+ load,
+ _recursive,
+ _resolve_conflict_map,
+ )
if not load:
# remove any history
@@ -2102,14 +2202,16 @@ class Session(_SessionClassMethods):
def _validate_persistent(self, state):
if not self.identity_map.contains_state(state):
raise sa_exc.InvalidRequestError(
- "Instance '%s' is not persistent within this Session" %
- state_str(state))
+ "Instance '%s' is not persistent within this Session"
+ % state_str(state)
+ )
def _save_impl(self, state):
if state.key is not None:
raise sa_exc.InvalidRequestError(
"Object '%s' already has an identity - "
- "it can't be registered as pending" % state_str(state))
+ "it can't be registered as pending" % state_str(state)
+ )
obj = state.obj()
to_attach = self._before_attach(state, obj)
@@ -2122,8 +2224,8 @@ class Session(_SessionClassMethods):
def _update_impl(self, state, revert_deletion=False):
if state.key is None:
raise sa_exc.InvalidRequestError(
- "Instance '%s' is not persisted" %
- state_str(state))
+ "Instance '%s' is not persisted" % state_str(state)
+ )
if state._deleted:
if revert_deletion:
@@ -2135,8 +2237,7 @@ class Session(_SessionClassMethods):
"Instance '%s' has been deleted. "
"Use the make_transient() "
"function to send this object back "
- "to the transient state." %
- state_str(state)
+ "to the transient state." % state_str(state)
)
obj = state.obj()
@@ -2234,8 +2335,9 @@ class Session(_SessionClassMethods):
if state.session_id and state.session_id in _sessions:
raise sa_exc.InvalidRequestError(
"Object '%s' is already attached to session '%s' "
- "(this is '%s')" % (state_str(state),
- state.session_id, self.hash_key))
+ "(this is '%s')"
+ % (state_str(state), state.session_id, self.hash_key)
+ )
self.dispatch.before_attach(self, obj)
@@ -2271,7 +2373,8 @@ class Session(_SessionClassMethods):
"""
return iter(
- list(self._new.values()) + list(self.identity_map.values()))
+ list(self._new.values()) + list(self.identity_map.values())
+ )
def _contains_state(self, state):
return state in self._new or self.identity_map.contains_state(state)
@@ -2319,13 +2422,15 @@ class Session(_SessionClassMethods):
"Usage of the '%s' operation is not currently supported "
"within the execution stage of the flush process. "
"Results may not be consistent. Consider using alternative "
- "event listeners or connection-level operations instead."
- % method)
+ "event listeners or connection-level operations instead." % method
+ )
def _is_clean(self):
- return not self.identity_map.check_modified() and \
- not self._deleted and \
- not self._new
+ return (
+ not self.identity_map.check_modified()
+ and not self._deleted
+ and not self._new
+ )
def _flush(self, objects=None):
@@ -2375,12 +2480,16 @@ class Session(_SessionClassMethods):
is_persistent_orphan = is_orphan and state.has_identity
- if is_orphan and not is_persistent_orphan and \
- state._orphaned_outside_of_session:
+ if (
+ is_orphan
+ and not is_persistent_orphan
+ and state._orphaned_outside_of_session
+ ):
self._expunge_states([state])
else:
_reg = flush_context.register_object(
- state, isdelete=is_persistent_orphan)
+ state, isdelete=is_persistent_orphan
+ )
assert _reg, "Failed to add object to the flush context!"
processed.add(state)
@@ -2397,7 +2506,8 @@ class Session(_SessionClassMethods):
return
flush_context.transaction = transaction = self.begin(
- subtransactions=True)
+ subtransactions=True
+ )
try:
self._warn_on_events = True
try:
@@ -2413,16 +2523,20 @@ class Session(_SessionClassMethods):
len_ = len(self.identity_map._modified)
statelib.InstanceState._commit_all_states(
- [(state, state.dict) for state in
- self.identity_map._modified],
- instance_dict=self.identity_map)
- util.warn("Attribute history events accumulated on %d "
- "previously clean instances "
- "within inner-flush event handlers have been "
- "reset, and will not result in database updates. "
- "Consider using set_committed_value() within "
- "inner-flush event handlers to avoid this warning."
- % len_)
+ [
+ (state, state.dict)
+ for state in self.identity_map._modified
+ ],
+ instance_dict=self.identity_map,
+ )
+ util.warn(
+ "Attribute history events accumulated on %d "
+ "previously clean instances "
+ "within inner-flush event handlers have been "
+ "reset, and will not result in database updates. "
+ "Consider using set_committed_value() within "
+ "inner-flush event handlers to avoid this warning." % len_
+ )
# useful assertions:
# if not objects:
@@ -2440,8 +2554,12 @@ class Session(_SessionClassMethods):
transaction.rollback(_capture_exception=True)
def bulk_save_objects(
- self, objects, return_defaults=False, update_changed_only=True,
- preserve_order=True):
+ self,
+ objects,
+ return_defaults=False,
+ update_changed_only=True,
+ preserve_order=True,
+ ):
"""Perform a bulk save of the given list of objects.
The bulk save feature allows mapped objects to be used as the
@@ -2520,6 +2638,7 @@ class Session(_SessionClassMethods):
:meth:`.Session.bulk_update_mappings`
"""
+
def key(state):
return (state.mapper, state.key is not None)
@@ -2527,15 +2646,20 @@ class Session(_SessionClassMethods):
if not preserve_order:
obj_states = sorted(obj_states, key=key)
- for (mapper, isupdate), states in itertools.groupby(
- obj_states, key
- ):
+ for (mapper, isupdate), states in itertools.groupby(obj_states, key):
self._bulk_save_mappings(
- mapper, states, isupdate, True,
- return_defaults, update_changed_only, False)
+ mapper,
+ states,
+ isupdate,
+ True,
+ return_defaults,
+ update_changed_only,
+ False,
+ )
def bulk_insert_mappings(
- self, mapper, mappings, return_defaults=False, render_nulls=False):
+ self, mapper, mappings, return_defaults=False, render_nulls=False
+ ):
"""Perform a bulk insert of the given list of mapping dictionaries.
The bulk insert feature allows plain Python dictionaries to be used as
@@ -2622,8 +2746,14 @@ class Session(_SessionClassMethods):
"""
self._bulk_save_mappings(
- mapper, mappings, False, False,
- return_defaults, False, render_nulls)
+ mapper,
+ mappings,
+ False,
+ False,
+ return_defaults,
+ False,
+ render_nulls,
+ )
def bulk_update_mappings(self, mapper, mappings):
"""Perform a bulk update of the given list of mapping dictionaries.
@@ -2673,25 +2803,41 @@ class Session(_SessionClassMethods):
"""
self._bulk_save_mappings(
- mapper, mappings, True, False, False, False, False)
+ mapper, mappings, True, False, False, False, False
+ )
def _bulk_save_mappings(
- self, mapper, mappings, isupdate, isstates,
- return_defaults, update_changed_only, render_nulls):
+ self,
+ mapper,
+ mappings,
+ isupdate,
+ isstates,
+ return_defaults,
+ update_changed_only,
+ render_nulls,
+ ):
mapper = _class_to_mapper(mapper)
self._flushing = True
- transaction = self.begin(
- subtransactions=True)
+ transaction = self.begin(subtransactions=True)
try:
if isupdate:
persistence._bulk_update(
- mapper, mappings, transaction,
- isstates, update_changed_only)
+ mapper,
+ mappings,
+ transaction,
+ isstates,
+ update_changed_only,
+ )
else:
persistence._bulk_insert(
- mapper, mappings, transaction,
- isstates, return_defaults, render_nulls)
+ mapper,
+ mappings,
+ transaction,
+ isstates,
+ return_defaults,
+ render_nulls,
+ )
transaction.commit()
except:
@@ -2700,8 +2846,7 @@ class Session(_SessionClassMethods):
finally:
self._flushing = False
- def is_modified(self, instance, include_collections=True,
- passive=True):
+ def is_modified(self, instance, include_collections=True, passive=True):
r"""Return ``True`` if the given instance has locally
modified attributes.
@@ -2775,16 +2920,15 @@ class Session(_SessionClassMethods):
dict_ = state.dict
for attr in state.manager.attributes:
- if \
- (
- not include_collections and
- hasattr(attr.impl, 'get_collection')
- ) or not hasattr(attr.impl, 'get_history'):
+ if (
+ not include_collections
+ and hasattr(attr.impl, "get_collection")
+ ) or not hasattr(attr.impl, "get_history"):
continue
- (added, unchanged, deleted) = \
- attr.impl.get_history(state, dict_,
- passive=attributes.NO_CHANGE)
+ (added, unchanged, deleted) = attr.impl.get_history(
+ state, dict_, passive=attributes.NO_CHANGE
+ )
if added or deleted:
return True
@@ -2898,9 +3042,12 @@ class Session(_SessionClassMethods):
"""
return util.IdentitySet(
- [state.obj()
- for state in self._dirty_states
- if state not in self._deleted])
+ [
+ state.obj()
+ for state in self._dirty_states
+ if state not in self._deleted
+ ]
+ )
@property
def deleted(self):
@@ -2961,10 +3108,16 @@ class sessionmaker(_SessionClassMethods):
"""
- def __init__(self, bind=None, class_=Session, autoflush=True,
- autocommit=False,
- expire_on_commit=True,
- info=None, **kw):
+ def __init__(
+ self,
+ bind=None,
+ class_=Session,
+ autoflush=True,
+ autocommit=False,
+ expire_on_commit=True,
+ info=None,
+ **kw
+ ):
r"""Construct a new :class:`.sessionmaker`.
All arguments here except for ``class_`` correspond to arguments
@@ -2992,12 +3145,12 @@ class sessionmaker(_SessionClassMethods):
constructor of newly created :class:`.Session` objects.
"""
- kw['bind'] = bind
- kw['autoflush'] = autoflush
- kw['autocommit'] = autocommit
- kw['expire_on_commit'] = expire_on_commit
+ kw["bind"] = bind
+ kw["autoflush"] = autoflush
+ kw["autocommit"] = autocommit
+ kw["expire_on_commit"] = expire_on_commit
if info is not None:
- kw['info'] = info
+ kw["info"] = info
self.kw = kw
# make our own subclass of the given class, so that
# events can be associated with it specifically.
@@ -3015,10 +3168,10 @@ class sessionmaker(_SessionClassMethods):
"""
for k, v in self.kw.items():
- if k == 'info' and 'info' in local_kw:
+ if k == "info" and "info" in local_kw:
d = v.copy()
- d.update(local_kw['info'])
- local_kw['info'] = d
+ d.update(local_kw["info"])
+ local_kw["info"] = d
else:
local_kw.setdefault(k, v)
return self.class_(**local_kw)
@@ -3038,7 +3191,7 @@ class sessionmaker(_SessionClassMethods):
return "%s(class_=%r, %s)" % (
self.__class__.__name__,
self.class_.__name__,
- ", ".join("%s=%r" % (k, v) for k, v in self.kw.items())
+ ", ".join("%s=%r" % (k, v) for k, v in self.kw.items()),
)
@@ -3139,8 +3292,7 @@ def make_transient_to_detached(instance):
"""
state = attributes.instance_state(instance)
if state.session_id or state.key:
- raise sa_exc.InvalidRequestError(
- "Given object must be transient")
+ raise sa_exc.InvalidRequestError("Given object must be transient")
state.key = state.mapper._identity_key_from_state(state)
if state._deleted:
del state._deleted
diff --git a/lib/sqlalchemy/orm/state.py b/lib/sqlalchemy/orm/state.py
index 944dc8177..c36d8817b 100644
--- a/lib/sqlalchemy/orm/state.py
+++ b/lib/sqlalchemy/orm/state.py
@@ -18,8 +18,16 @@ from .. import inspection
from .. import exc as sa_exc
from . import exc as orm_exc, interfaces
from .path_registry import PathRegistry
-from .base import PASSIVE_NO_RESULT, SQL_OK, NEVER_SET, ATTR_WAS_SET, \
- NO_VALUE, PASSIVE_NO_INITIALIZE, INIT_OK, PASSIVE_OFF
+from .base import (
+ PASSIVE_NO_RESULT,
+ SQL_OK,
+ NEVER_SET,
+ ATTR_WAS_SET,
+ NO_VALUE,
+ PASSIVE_NO_INITIALIZE,
+ INIT_OK,
+ PASSIVE_OFF,
+)
from . import base
@@ -106,10 +114,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
"""
return util.ImmutableProperties(
- dict(
- (key, AttributeState(self, key))
- for key in self.manager
- )
+ dict((key, AttributeState(self, key)) for key in self.manager)
)
@property
@@ -121,8 +126,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
:ref:`session_object_states`
"""
- return self.key is None and \
- not self._attached
+ return self.key is None and not self._attached
@property
def pending(self):
@@ -134,8 +138,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
:ref:`session_object_states`
"""
- return self.key is None and \
- self._attached
+ return self.key is None and self._attached
@property
def deleted(self):
@@ -164,8 +167,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
:ref:`session_object_states`
"""
- return self.key is not None and \
- self._attached and self._deleted
+ return self.key is not None and self._attached and self._deleted
@property
def was_deleted(self):
@@ -210,8 +212,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
:ref:`session_object_states`
"""
- return self.key is not None and \
- self._attached and not self._deleted
+ return self.key is not None and self._attached and not self._deleted
@property
def detached(self):
@@ -227,8 +228,10 @@ class InstanceState(interfaces.InspectionAttrInfo):
@property
@util.dependencies("sqlalchemy.orm.session")
def _attached(self, sessionlib):
- return self.session_id is not None and \
- self.session_id in sessionlib._sessions
+ return (
+ self.session_id is not None
+ and self.session_id in sessionlib._sessions
+ )
def _track_last_known_value(self, key):
"""Track the last known value of a particular key after expiration
@@ -323,14 +326,14 @@ class InstanceState(interfaces.InspectionAttrInfo):
@classmethod
def _detach_states(self, states, session, to_transient=False):
- persistent_to_detached = \
+ persistent_to_detached = (
session.dispatch.persistent_to_detached or None
- deleted_to_detached = \
- session.dispatch.deleted_to_detached or None
- pending_to_transient = \
- session.dispatch.pending_to_transient or None
- persistent_to_transient = \
+ )
+ deleted_to_detached = session.dispatch.deleted_to_detached or None
+ pending_to_transient = session.dispatch.pending_to_transient or None
+ persistent_to_transient = (
session.dispatch.persistent_to_transient or None
+ )
for state in states:
deleted = state._deleted
@@ -448,23 +451,33 @@ class InstanceState(interfaces.InspectionAttrInfo):
return self._pending_mutations[key]
def __getstate__(self):
- state_dict = {'instance': self.obj()}
+ state_dict = {"instance": self.obj()}
state_dict.update(
- (k, self.__dict__[k]) for k in (
- 'committed_state', '_pending_mutations', 'modified',
- 'expired', 'callables', 'key', 'parents', 'load_options',
- 'class_', 'expired_attributes', 'info'
- ) if k in self.__dict__
+ (k, self.__dict__[k])
+ for k in (
+ "committed_state",
+ "_pending_mutations",
+ "modified",
+ "expired",
+ "callables",
+ "key",
+ "parents",
+ "load_options",
+ "class_",
+ "expired_attributes",
+ "info",
+ )
+ if k in self.__dict__
)
if self.load_path:
- state_dict['load_path'] = self.load_path.serialize()
+ state_dict["load_path"] = self.load_path.serialize()
- state_dict['manager'] = self.manager._serialize(self, state_dict)
+ state_dict["manager"] = self.manager._serialize(self, state_dict)
return state_dict
def __setstate__(self, state_dict):
- inst = state_dict['instance']
+ inst = state_dict["instance"]
if inst is not None:
self.obj = weakref.ref(inst, self._cleanup)
self.class_ = inst.__class__
@@ -473,20 +486,20 @@ class InstanceState(interfaces.InspectionAttrInfo):
# due to storage of state in "parents". "class_"
# also new.
self.obj = None
- self.class_ = state_dict['class_']
-
- self.committed_state = state_dict.get('committed_state', {})
- self._pending_mutations = state_dict.get('_pending_mutations', {})
- self.parents = state_dict.get('parents', {})
- self.modified = state_dict.get('modified', False)
- self.expired = state_dict.get('expired', False)
- if 'info' in state_dict:
- self.info.update(state_dict['info'])
- if 'callables' in state_dict:
- self.callables = state_dict['callables']
+ self.class_ = state_dict["class_"]
+
+ self.committed_state = state_dict.get("committed_state", {})
+ self._pending_mutations = state_dict.get("_pending_mutations", {})
+ self.parents = state_dict.get("parents", {})
+ self.modified = state_dict.get("modified", False)
+ self.expired = state_dict.get("expired", False)
+ if "info" in state_dict:
+ self.info.update(state_dict["info"])
+ if "callables" in state_dict:
+ self.callables = state_dict["callables"]
try:
- self.expired_attributes = state_dict['expired_attributes']
+ self.expired_attributes = state_dict["expired_attributes"]
except KeyError:
self.expired_attributes = set()
# 0.9 and earlier compat
@@ -495,30 +508,31 @@ class InstanceState(interfaces.InspectionAttrInfo):
self.expired_attributes.add(k)
del self.callables[k]
else:
- if 'expired_attributes' in state_dict:
- self.expired_attributes = state_dict['expired_attributes']
+ if "expired_attributes" in state_dict:
+ self.expired_attributes = state_dict["expired_attributes"]
else:
self.expired_attributes = set()
- self.__dict__.update([
- (k, state_dict[k]) for k in (
- 'key', 'load_options'
- ) if k in state_dict
- ])
+ self.__dict__.update(
+ [
+ (k, state_dict[k])
+ for k in ("key", "load_options")
+ if k in state_dict
+ ]
+ )
if self.key:
try:
self.identity_token = self.key[2]
except IndexError:
# 1.1 and earlier compat before identity_token
assert len(self.key) == 2
- self.key = self.key + (None, )
+ self.key = self.key + (None,)
self.identity_token = None
- if 'load_path' in state_dict:
- self.load_path = PathRegistry.\
- deserialize(state_dict['load_path'])
+ if "load_path" in state_dict:
+ self.load_path = PathRegistry.deserialize(state_dict["load_path"])
- state_dict['manager'](self, inst, state_dict)
+ state_dict["manager"](self, inst, state_dict)
def _reset(self, dict_, key):
"""Remove the given attribute and any
@@ -532,25 +546,29 @@ class InstanceState(interfaces.InspectionAttrInfo):
self.callables.pop(key, None)
def _copy_callables(self, from_):
- if 'callables' in from_.__dict__:
+ if "callables" in from_.__dict__:
self.callables = dict(from_.callables)
@classmethod
def _instance_level_callable_processor(cls, manager, fn, key):
impl = manager[key].impl
if impl.collection:
+
def _set_callable(state, dict_, row):
- if 'callables' not in state.__dict__:
+ if "callables" not in state.__dict__:
state.callables = {}
old = dict_.pop(key, None)
if old is not None:
impl._invalidate_collection(old)
state.callables[key] = fn
+
else:
+
def _set_callable(state, dict_, row):
- if 'callables' not in state.__dict__:
+ if "callables" not in state.__dict__:
state.callables = {}
state.callables[key] = fn
+
return _set_callable
def _expire(self, dict_, modified_set):
@@ -563,15 +581,18 @@ class InstanceState(interfaces.InspectionAttrInfo):
self._strong_obj = None
- if '_pending_mutations' in self.__dict__:
- del self.__dict__['_pending_mutations']
+ if "_pending_mutations" in self.__dict__:
+ del self.__dict__["_pending_mutations"]
- if 'parents' in self.__dict__:
- del self.__dict__['parents']
+ if "parents" in self.__dict__:
+ del self.__dict__["parents"]
self.expired_attributes.update(
- [impl.key for impl in self.manager._scalar_loader_impls
- if impl.expire_missing or impl.key in dict_]
+ [
+ impl.key
+ for impl in self.manager._scalar_loader_impls
+ if impl.expire_missing or impl.key in dict_
+ ]
)
if self.callables:
@@ -584,8 +605,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
if self._last_known_values:
self._last_known_values.update(
- (k, dict_[k]) for k in self._last_known_values
- if k in dict_
+ (k, dict_[k]) for k in self._last_known_values if k in dict_
)
for key in self.manager._all_key_set.intersection(dict_):
@@ -594,17 +614,14 @@ class InstanceState(interfaces.InspectionAttrInfo):
self.manager.dispatch.expire(self, None)
def _expire_attributes(self, dict_, attribute_names, no_loader=False):
- pending = self.__dict__.get('_pending_mutations', None)
+ pending = self.__dict__.get("_pending_mutations", None)
callables = self.callables
for key in attribute_names:
impl = self.manager[key].impl
if impl.accepts_scalar_loader:
- if no_loader and (
- impl.callable_ or
- key in callables
- ):
+ if no_loader and (impl.callable_ or key in callables):
continue
self.expired_attributes.add(key)
@@ -614,8 +631,11 @@ class InstanceState(interfaces.InspectionAttrInfo):
if impl.collection and old is not NO_VALUE:
impl._invalidate_collection(old)
- if self._last_known_values and key in self._last_known_values \
- and old is not NO_VALUE:
+ if (
+ self._last_known_values
+ and key in self._last_known_values
+ and old is not NO_VALUE
+ ):
self._last_known_values[key] = old
self.committed_state.pop(key, None)
@@ -634,8 +654,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
if not passive & SQL_OK:
return PASSIVE_NO_RESULT
- toload = self.expired_attributes.\
- intersection(self.unmodified)
+ toload = self.expired_attributes.intersection(self.unmodified)
self.manager.deferred_scalar_loader(self, toload)
@@ -656,9 +675,11 @@ class InstanceState(interfaces.InspectionAttrInfo):
def unmodified_intersection(self, keys):
"""Return self.unmodified.intersection(keys)."""
-
- return set(keys).intersection(self.manager).\
- difference(self.committed_state)
+ return (
+ set(keys)
+ .intersection(self.manager)
+ .difference(self.committed_state)
+ )
@property
def unloaded(self):
@@ -668,9 +689,11 @@ class InstanceState(interfaces.InspectionAttrInfo):
was never populated or modified.
"""
- return set(self.manager).\
- difference(self.committed_state).\
- difference(self.dict)
+ return (
+ set(self.manager)
+ .difference(self.committed_state)
+ .difference(self.dict)
+ )
@property
def unloaded_expirable(self):
@@ -681,13 +704,16 @@ class InstanceState(interfaces.InspectionAttrInfo):
"""
return self.unloaded.intersection(
- attr for attr in self.manager
- if self.manager[attr].impl.expire_missing)
+ attr
+ for attr in self.manager
+ if self.manager[attr].impl.expire_missing
+ )
@property
def _unloaded_non_object(self):
return self.unloaded.intersection(
- attr for attr in self.manager
+ attr
+ for attr in self.manager
if self.manager[attr].impl.accepts_scalar_loader
)
@@ -695,14 +721,16 @@ class InstanceState(interfaces.InspectionAttrInfo):
return None
def _modified_event(
- self, dict_, attr, previous, collection=False, is_userland=False):
+ self, dict_, attr, previous, collection=False, is_userland=False
+ ):
if attr:
if not attr.send_modified_events:
return
if is_userland and attr.key not in dict_:
raise sa_exc.InvalidRequestError(
"Can't flag attribute '%s' modified; it's not present in "
- "the object state" % attr.key)
+ "the object state" % attr.key
+ )
if attr.key not in self.committed_state or is_userland:
if collection:
if previous is NEVER_SET:
@@ -718,8 +746,7 @@ class InstanceState(interfaces.InspectionAttrInfo):
# assert self._strong_obj is None or self.modified
- if (self.session_id and self._strong_obj is None) \
- or not self.modified:
+ if (self.session_id and self._strong_obj is None) or not self.modified:
self.modified = True
instance_dict = self._instance_dict()
if instance_dict:
@@ -737,10 +764,8 @@ class InstanceState(interfaces.InspectionAttrInfo):
"Can't emit change event for attribute '%s' - "
"parent object of type %s has been garbage "
"collected."
- % (
- self.manager[attr.key],
- base.state_class_str(self)
- ))
+ % (self.manager[attr.key], base.state_class_str(self))
+ )
def _commit(self, dict_, keys):
"""Commit attributes.
@@ -758,17 +783,18 @@ class InstanceState(interfaces.InspectionAttrInfo):
self.expired = False
self.expired_attributes.difference_update(
- set(keys).intersection(dict_))
+ set(keys).intersection(dict_)
+ )
# the per-keys commit removes object-level callables,
# while that of commit_all does not. it's not clear
# if this behavior has a clear rationale, however tests do
# ensure this is what it does.
if self.callables:
- for key in set(self.callables).\
- intersection(keys).\
- intersection(dict_):
- del self.callables[key]
+ for key in (
+ set(self.callables).intersection(keys).intersection(dict_)
+ ):
+ del self.callables[key]
def _commit_all(self, dict_, instance_dict=None):
"""commit all attributes unconditionally.
@@ -797,8 +823,8 @@ class InstanceState(interfaces.InspectionAttrInfo):
state.committed_state.clear()
- if '_pending_mutations' in state_dict:
- del state_dict['_pending_mutations']
+ if "_pending_mutations" in state_dict:
+ del state_dict["_pending_mutations"]
state.expired_attributes.difference_update(dict_)
@@ -848,7 +874,8 @@ class AttributeState(object):
"""
return self.state.manager[self.key].__get__(
- self.state.obj(), self.state.class_)
+ self.state.obj(), self.state.class_
+ )
@property
def history(self):
@@ -866,8 +893,7 @@ class AttributeState(object):
:func:`.attributes.get_history` - underlying function
"""
- return self.state.get_history(self.key,
- PASSIVE_NO_INITIALIZE)
+ return self.state.get_history(self.key, PASSIVE_NO_INITIALIZE)
def load_history(self):
"""Return the current pre-flush change history for
@@ -885,8 +911,7 @@ class AttributeState(object):
.. versionadded:: 0.9.0
"""
- return self.state.get_history(self.key,
- PASSIVE_OFF ^ INIT_OK)
+ return self.state.get_history(self.key, PASSIVE_OFF ^ INIT_OK)
class PendingCollection(object):
diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py
index 47791f9b9..5c972b26b 100644
--- a/lib/sqlalchemy/orm/strategies.py
+++ b/lib/sqlalchemy/orm/strategies.py
@@ -13,22 +13,27 @@ from .. import util, log, event
from ..sql import util as sql_util, visitors
from .. import sql
from . import (
- attributes, interfaces, exc as orm_exc, loading,
- unitofwork, util as orm_util, query
+ attributes,
+ interfaces,
+ exc as orm_exc,
+ loading,
+ unitofwork,
+ util as orm_util,
+ query,
)
from .state import InstanceState
from .util import _none_set, aliased
from . import properties
-from .interfaces import (
- LoaderStrategy, StrategizedProperty
-)
+from .interfaces import LoaderStrategy, StrategizedProperty
from .base import _SET_DEFERRED_EXPIRED, _DEFER_FOR_STATE
from .session import _state_session
import itertools
def _register_attribute(
- prop, mapper, useobject,
+ prop,
+ mapper,
+ useobject,
compare_function=None,
typecallable=None,
callable_=None,
@@ -51,8 +56,8 @@ def _register_attribute(
fn, opts = prop.parent.validators[prop.key]
listen_hooks.append(
lambda desc, prop: orm_util._validator_events(
- desc,
- prop.key, fn, **opts)
+ desc, prop.key, fn, **opts
+ )
)
if useobject:
@@ -65,9 +70,7 @@ def _register_attribute(
if backref:
listen_hooks.append(
lambda desc, prop: attributes.backref_listeners(
- desc,
- backref,
- uselist
+ desc, backref, uselist
)
)
@@ -83,8 +86,9 @@ def _register_attribute(
# on mappers not already being set up so we have to check each one.
for m in mapper.self_and_descendants:
- if prop is m._props.get(prop.key) and \
- not m.class_manager._attr_has_impl(prop.key):
+ if prop is m._props.get(
+ prop.key
+ ) and not m.class_manager._attr_has_impl(prop.key):
desc = attributes.register_attribute_impl(
m.class_,
@@ -94,9 +98,11 @@ def _register_attribute(
compare_function=compare_function,
useobject=useobject,
extension=attribute_ext,
- trackparent=useobject and (
- prop.single_parent or
- prop.direction is interfaces.ONETOMANY),
+ trackparent=useobject
+ and (
+ prop.single_parent
+ or prop.direction is interfaces.ONETOMANY
+ ),
typecallable=typecallable,
callable_=callable_,
active_history=active_history,
@@ -118,23 +124,31 @@ class UninstrumentedColumnLoader(LoaderStrategy):
if the argument is against the with_polymorphic selectable.
"""
- __slots__ = 'columns',
+
+ __slots__ = ("columns",)
def __init__(self, parent, strategy_key):
super(UninstrumentedColumnLoader, self).__init__(parent, strategy_key)
self.columns = self.parent_property.columns
def setup_query(
- self, context, entity, path, loadopt, adapter,
- column_collection=None, **kwargs):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection=None,
+ **kwargs
+ ):
for c in self.columns:
if adapter:
c = adapter.columns[c]
column_collection.append(c)
def create_row_processor(
- self, context, path, loadopt,
- mapper, result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
pass
@@ -143,16 +157,24 @@ class UninstrumentedColumnLoader(LoaderStrategy):
class ColumnLoader(LoaderStrategy):
"""Provide loading behavior for a :class:`.ColumnProperty`."""
- __slots__ = 'columns', 'is_composite'
+ __slots__ = "columns", "is_composite"
def __init__(self, parent, strategy_key):
super(ColumnLoader, self).__init__(parent, strategy_key)
self.columns = self.parent_property.columns
- self.is_composite = hasattr(self.parent_property, 'composite_class')
+ self.is_composite = hasattr(self.parent_property, "composite_class")
def setup_query(
- self, context, entity, path, loadopt,
- adapter, column_collection, memoized_populators, **kwargs):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection,
+ memoized_populators,
+ **kwargs
+ ):
for c in self.columns:
if adapter:
@@ -168,19 +190,23 @@ class ColumnLoader(LoaderStrategy):
self.is_class_level = True
coltype = self.columns[0].type
# TODO: check all columns ? check for foreign key as well?
- active_history = self.parent_property.active_history or \
- self.columns[0].primary_key or \
- mapper.version_id_col in set(self.columns)
+ active_history = (
+ self.parent_property.active_history
+ or self.columns[0].primary_key
+ or mapper.version_id_col in set(self.columns)
+ )
_register_attribute(
- self.parent_property, mapper, useobject=False,
+ self.parent_property,
+ mapper,
+ useobject=False,
compare_function=coltype.compare_values,
- active_history=active_history
+ active_history=active_history,
)
def create_row_processor(
- self, context, path,
- loadopt, mapper, result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
# look through list of columns represented here
# to see which, if any, is present in the row.
for col in self.columns:
@@ -201,8 +227,16 @@ class ExpressionColumnLoader(ColumnLoader):
super(ExpressionColumnLoader, self).__init__(parent, strategy_key)
def setup_query(
- self, context, entity, path, loadopt,
- adapter, column_collection, memoized_populators, **kwargs):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection,
+ memoized_populators,
+ **kwargs
+ ):
if loadopt and "expression" in loadopt.local_opts:
columns = [loadopt.local_opts["expression"]]
@@ -218,8 +252,8 @@ class ExpressionColumnLoader(ColumnLoader):
memoized_populators[self.parent_property] = fetch
def create_row_processor(
- self, context, path,
- loadopt, mapper, result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
# look through list of columns represented here
# to see which, if any, is present in the row.
if loadopt and "expression" in loadopt.local_opts:
@@ -239,9 +273,11 @@ class ExpressionColumnLoader(ColumnLoader):
self.is_class_level = True
_register_attribute(
- self.parent_property, mapper, useobject=False,
+ self.parent_property,
+ mapper,
+ useobject=False,
compare_function=self.columns[0].type.compare_values,
- accepts_scalar_loader=False
+ accepts_scalar_loader=False,
)
@@ -251,27 +287,29 @@ class ExpressionColumnLoader(ColumnLoader):
class DeferredColumnLoader(LoaderStrategy):
"""Provide loading behavior for a deferred :class:`.ColumnProperty`."""
- __slots__ = 'columns', 'group'
+ __slots__ = "columns", "group"
def __init__(self, parent, strategy_key):
super(DeferredColumnLoader, self).__init__(parent, strategy_key)
- if hasattr(self.parent_property, 'composite_class'):
- raise NotImplementedError("Deferred loading for composite "
- "types not implemented yet")
+ if hasattr(self.parent_property, "composite_class"):
+ raise NotImplementedError(
+ "Deferred loading for composite " "types not implemented yet"
+ )
self.columns = self.parent_property.columns
self.group = self.parent_property.group
def create_row_processor(
- self, context, path, loadopt,
- mapper, result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
# this path currently does not check the result
# for the column; this is because in most cases we are
# working just with the setup_query() directive which does
# not support this, and the behavior here should be consistent.
if not self.is_class_level:
- set_deferred_for_local_state = \
+ set_deferred_for_local_state = (
self.parent_property._deferred_column_loader
+ )
populators["new"].append((self.key, set_deferred_for_local_state))
else:
populators["expire"].append((self.key, False))
@@ -280,41 +318,56 @@ class DeferredColumnLoader(LoaderStrategy):
self.is_class_level = True
_register_attribute(
- self.parent_property, mapper, useobject=False,
+ self.parent_property,
+ mapper,
+ useobject=False,
compare_function=self.columns[0].type.compare_values,
callable_=self._load_for_state,
- expire_missing=False
+ expire_missing=False,
)
def setup_query(
- self, context, entity, path, loadopt,
- adapter, column_collection, memoized_populators,
- only_load_props=None, **kw):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection,
+ memoized_populators,
+ only_load_props=None,
+ **kw
+ ):
if (
(
- loadopt and
- 'undefer_pks' in loadopt.local_opts and
- set(self.columns).intersection(
- self.parent._should_undefer_in_wildcard)
- )
- or
- (
- loadopt and
- self.group and
- loadopt.local_opts.get('undefer_group_%s' % self.group, False)
+ loadopt
+ and "undefer_pks" in loadopt.local_opts
+ and set(self.columns).intersection(
+ self.parent._should_undefer_in_wildcard
+ )
)
- or
- (
- only_load_props and self.key in only_load_props
+ or (
+ loadopt
+ and self.group
+ and loadopt.local_opts.get(
+ "undefer_group_%s" % self.group, False
+ )
)
+ or (only_load_props and self.key in only_load_props)
):
self.parent_property._get_strategy(
(("deferred", False), ("instrument", True))
).setup_query(
- context, entity,
- path, loadopt, adapter,
- column_collection, memoized_populators, **kw)
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection,
+ memoized_populators,
+ **kw
+ )
elif self.is_class_level:
memoized_populators[self.parent_property] = _SET_DEFERRED_EXPIRED
else:
@@ -331,11 +384,11 @@ class DeferredColumnLoader(LoaderStrategy):
if self.group:
toload = [
- p.key for p in
- localparent.iterate_properties
- if isinstance(p, StrategizedProperty) and
- isinstance(p.strategy, DeferredColumnLoader) and
- p.group == self.group
+ p.key
+ for p in localparent.iterate_properties
+ if isinstance(p, StrategizedProperty)
+ and isinstance(p.strategy, DeferredColumnLoader)
+ and p.group == self.group
]
else:
toload = [self.key]
@@ -347,14 +400,17 @@ class DeferredColumnLoader(LoaderStrategy):
if session is None:
raise orm_exc.DetachedInstanceError(
"Parent instance %s is not bound to a Session; "
- "deferred load operation of attribute '%s' cannot proceed" %
- (orm_util.state_str(state), self.key)
+ "deferred load operation of attribute '%s' cannot proceed"
+ % (orm_util.state_str(state), self.key)
)
query = session.query(localparent)
- if loading.load_on_ident(
- query, state.key,
- only_load_props=group, refresh_state=state) is None:
+ if (
+ loading.load_on_ident(
+ query, state.key, only_load_props=group, refresh_state=state
+ )
+ is None
+ ):
raise orm_exc.ObjectDeletedError(state)
return attributes.ATTR_WAS_SET
@@ -378,7 +434,7 @@ class LoadDeferredColumns(object):
class AbstractRelationshipLoader(LoaderStrategy):
"""LoaderStratgies which deal with related objects."""
- __slots__ = 'mapper', 'target', 'uselist'
+ __slots__ = "mapper", "target", "uselist"
def __init__(self, parent, strategy_key):
super(AbstractRelationshipLoader, self).__init__(parent, strategy_key)
@@ -414,19 +470,21 @@ class NoLoader(AbstractRelationshipLoader):
self.is_class_level = True
_register_attribute(
- self.parent_property, mapper,
+ self.parent_property,
+ mapper,
useobject=True,
typecallable=self.parent_property.collection_class,
)
def create_row_processor(
- self, context, path, loadopt, mapper,
- result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
def invoke_no_load(state, dict_, row):
if self.uselist:
state.manager.get_impl(self.key).initialize(state, dict_)
else:
dict_[self.key] = None
+
populators["new"].append((self.key, invoke_no_load))
@@ -443,10 +501,18 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
"""
__slots__ = (
- '_lazywhere', '_rev_lazywhere', 'use_get', '_bind_to_col',
- '_equated_columns', '_rev_bind_to_col', '_rev_equated_columns',
- '_simple_lazy_clause', '_raise_always', '_raise_on_sql',
- '_bakery')
+ "_lazywhere",
+ "_rev_lazywhere",
+ "use_get",
+ "_bind_to_col",
+ "_equated_columns",
+ "_rev_bind_to_col",
+ "_rev_equated_columns",
+ "_simple_lazy_clause",
+ "_raise_always",
+ "_raise_on_sql",
+ "_bakery",
+ )
def __init__(self, parent, strategy_key):
super(LazyLoader, self).__init__(parent, strategy_key)
@@ -454,25 +520,23 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
self._raise_on_sql = self.strategy_opts["lazy"] == "raise_on_sql"
join_condition = self.parent_property._join_condition
- self._lazywhere, \
- self._bind_to_col, \
- self._equated_columns = join_condition.create_lazy_clause()
+ self._lazywhere, self._bind_to_col, self._equated_columns = (
+ join_condition.create_lazy_clause()
+ )
- self._rev_lazywhere, \
- self._rev_bind_to_col, \
- self._rev_equated_columns = join_condition.create_lazy_clause(
- reverse_direction=True)
+ self._rev_lazywhere, self._rev_bind_to_col, self._rev_equated_columns = join_condition.create_lazy_clause(
+ reverse_direction=True
+ )
self.logger.info("%s lazy loading clause %s", self, self._lazywhere)
# determine if our "lazywhere" clause is the same as the mapper's
# get() clause. then we can just use mapper.get()
- self.use_get = not self.uselist and \
- self.mapper._get_clause[0].compare(
- self._lazywhere,
- use_proxies=True,
- equivalents=self.mapper._equivalent_columns
- )
+ self.use_get = not self.uselist and self.mapper._get_clause[0].compare(
+ self._lazywhere,
+ use_proxies=True,
+ equivalents=self.mapper._equivalent_columns,
+ )
if self.use_get:
for col in list(self._equated_columns):
@@ -480,16 +544,17 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
for c in self.mapper._equivalent_columns[col]:
self._equated_columns[c] = self._equated_columns[col]
- self.logger.info("%s will use query.get() to "
- "optimize instance loads", self)
+ self.logger.info(
+ "%s will use query.get() to " "optimize instance loads", self
+ )
def init_class_attribute(self, mapper):
self.is_class_level = True
active_history = (
- self.parent_property.active_history or
- self.parent_property.direction is not interfaces.MANYTOONE or
- not self.use_get
+ self.parent_property.active_history
+ or self.parent_property.direction is not interfaces.MANYTOONE
+ or not self.use_get
)
# MANYTOONE currently only needs the
@@ -504,28 +569,29 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
useobject=True,
callable_=self._load_for_state,
typecallable=self.parent_property.collection_class,
- active_history=active_history
+ active_history=active_history,
)
def _memoized_attr__simple_lazy_clause(self):
- criterion, bind_to_col = (
- self._lazywhere,
- self._bind_to_col
- )
+ criterion, bind_to_col = (self._lazywhere, self._bind_to_col)
params = []
def visit_bindparam(bindparam):
bindparam.unique = False
if bindparam._identifying_key in bind_to_col:
- params.append((
- bindparam.key, bind_to_col[bindparam._identifying_key],
- None))
+ params.append(
+ (
+ bindparam.key,
+ bind_to_col[bindparam._identifying_key],
+ None,
+ )
+ )
elif bindparam.callable is None:
params.append((bindparam.key, None, bindparam.value))
criterion = visitors.cloned_traverse(
- criterion, {}, {'bindparam': visit_bindparam}
+ criterion, {}, {"bindparam": visit_bindparam}
)
return criterion, params
@@ -535,7 +601,8 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
if state is None:
return sql_util.adapt_criterion_to_null(
- criterion, [key for key, ident, value in param_keys])
+ criterion, [key for key, ident, value in param_keys]
+ )
mapper = self.parent_property.parent
@@ -550,10 +617,12 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
if ident is not None:
if passive and passive & attributes.LOAD_AGAINST_COMMITTED:
value = mapper._get_committed_state_attr_by_column(
- state, dict_, ident, passive)
+ state, dict_, ident, passive
+ )
else:
value = mapper._get_state_attr_by_column(
- state, dict_, ident, passive)
+ state, dict_, ident, passive
+ )
params[key] = value
@@ -567,21 +636,19 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
def _load_for_state(self, state, passive):
if not state.key and (
- (
- not self.parent_property.load_on_pending
- and not state._load_pending
- )
- or not state.session_id
+ (
+ not self.parent_property.load_on_pending
+ and not state._load_pending
+ )
+ or not state.session_id
):
return attributes.ATTR_EMPTY
pending = not state.key
primary_key_identity = None
- if (
- (not passive & attributes.SQL_OK and not self.use_get)
- or
- (not passive & attributes.NON_PERSISTENT_OK and pending)
+ if (not passive & attributes.SQL_OK and not self.use_get) or (
+ not passive & attributes.NON_PERSISTENT_OK and pending
):
return attributes.PASSIVE_NO_RESULT
@@ -595,17 +662,15 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
raise orm_exc.DetachedInstanceError(
"Parent instance %s is not bound to a Session; "
- "lazy load operation of attribute '%s' cannot proceed" %
- (orm_util.state_str(state), self.key)
+ "lazy load operation of attribute '%s' cannot proceed"
+ % (orm_util.state_str(state), self.key)
)
# if we have a simple primary key load, check the
# identity map without generating a Query at all
if self.use_get:
primary_key_identity = self._get_ident_for_use_get(
- session,
- state,
- passive
+ session, state, passive
)
if attributes.PASSIVE_NO_RESULT in primary_key_identity:
return attributes.PASSIVE_NO_RESULT
@@ -620,18 +685,23 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
# does this, including how it decides what the correct
# identity_token would be for this identity.
instance = session.query()._identity_lookup(
- self.mapper, primary_key_identity, passive=passive,
- lazy_loaded_from=state
+ self.mapper,
+ primary_key_identity,
+ passive=passive,
+ lazy_loaded_from=state,
)
if instance is not None:
return instance
- elif not passive & attributes.SQL_OK or \
- not passive & attributes.RELATED_OBJECT_OK:
+ elif (
+ not passive & attributes.SQL_OK
+ or not passive & attributes.RELATED_OBJECT_OK
+ ):
return attributes.PASSIVE_NO_RESULT
return self._emit_lazyload(
- session, state, primary_key_identity, passive)
+ session, state, primary_key_identity, passive
+ )
def _get_ident_for_use_get(self, session, state, passive):
instance_mapper = state.manager.mapper
@@ -644,11 +714,7 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
dict_ = state.dict
return [
- get_attr(
- state,
- dict_,
- self._equated_columns[pk],
- passive=passive)
+ get_attr(state, dict_, self._equated_columns[pk], passive=passive)
for pk in self.mapper.primary_key
]
@@ -656,11 +722,10 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
def _memoized_attr__bakery(self, baked):
return baked.bakery(size=50)
- @util.dependencies(
- "sqlalchemy.orm.strategy_options")
+ @util.dependencies("sqlalchemy.orm.strategy_options")
def _emit_lazyload(
- self, strategy_options, session, state,
- primary_key_identity, passive):
+ self, strategy_options, session, state, primary_key_identity, passive
+ ):
# emit lazy load now using BakedQuery, to cut way down on the overhead
# of generating queries.
# there are two big things we are trying to guard against here:
@@ -688,15 +753,18 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
q.add_criteria(
lambda q: q._adapt_all_clauses()._with_invoke_all_eagers(False),
- self.parent_property)
+ self.parent_property,
+ )
if not self.parent_property.bake_queries:
q.spoil(full=True)
if self.parent_property.secondary is not None:
q.add_criteria(
- lambda q:
- q.select_from(self.mapper, self.parent_property.secondary))
+ lambda q: q.select_from(
+ self.mapper, self.parent_property.secondary
+ )
+ )
pending = not state.key
@@ -712,35 +780,38 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
# is usually a throwaway object.
effective_path = state.load_path[self.parent_property]
- q._add_lazyload_options(
- state.load_options, effective_path
- )
+ q._add_lazyload_options(state.load_options, effective_path)
if self.use_get:
if self._raise_on_sql:
self._invoke_raise_load(state, passive, "raise_on_sql")
- return q(session).\
- with_post_criteria(lambda q: q._set_lazyload_from(state)).\
- _load_on_pk_identity(
- session.query(self.mapper),
- primary_key_identity)
+ return (
+ q(session)
+ .with_post_criteria(lambda q: q._set_lazyload_from(state))
+ ._load_on_pk_identity(
+ session.query(self.mapper), primary_key_identity
+ )
+ )
if self.parent_property.order_by:
q.add_criteria(
- lambda q:
- q.order_by(*util.to_list(self.parent_property.order_by)))
+ lambda q: q.order_by(
+ *util.to_list(self.parent_property.order_by)
+ )
+ )
for rev in self.parent_property._reverse_property:
# reverse props that are MANYTOONE are loading *this*
# object from get(), so don't need to eager out to those.
- if rev.direction is interfaces.MANYTOONE and \
- rev._use_get and \
- not isinstance(rev.strategy, LazyLoader):
+ if (
+ rev.direction is interfaces.MANYTOONE
+ and rev._use_get
+ and not isinstance(rev.strategy, LazyLoader)
+ ):
q.add_criteria(
- lambda q:
- q.options(
+ lambda q: q.options(
strategy_options.Load.for_existing_path(
q._current_path[rev.parent]
).lazyload(rev.key)
@@ -750,8 +821,7 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
lazy_clause, params = self._generate_lazy_clause(state, passive)
if pending:
- if util.has_intersection(
- orm_util._none_set, params.values()):
+ if util.has_intersection(orm_util._none_set, params.values()):
return None
elif util.has_intersection(orm_util._never_set, params.values()):
@@ -769,9 +839,12 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
q._params = params
return q
- result = q(session).\
- with_post_criteria(lambda q: q._set_lazyload_from(state)).\
- with_post_criteria(set_default_params).all()
+ result = (
+ q(session)
+ .with_post_criteria(lambda q: q._set_lazyload_from(state))
+ .with_post_criteria(set_default_params)
+ .all()
+ )
if self.uselist:
return result
else:
@@ -781,15 +854,16 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
util.warn(
"Multiple rows returned with "
"uselist=False for lazily-loaded attribute '%s' "
- % self.parent_property)
+ % self.parent_property
+ )
return result[0]
else:
return None
def create_row_processor(
- self, context, path, loadopt,
- mapper, result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
key = self.key
if not self.is_class_level:
@@ -802,11 +876,12 @@ class LazyLoader(AbstractRelationshipLoader, util.MemoizedSlots):
# attribute - "eager" attributes always have a
# class-level lazyloader installed.
set_lazy_callable = InstanceState._instance_level_callable_processor(
- mapper.class_manager,
- LoadLazyAttribute(key, self), key)
+ mapper.class_manager, LoadLazyAttribute(key, self), key
+ )
populators["new"].append((self.key, set_lazy_callable))
elif context.populate_existing or mapper.always_refresh:
+
def reset_for_lazy_callable(state, dict_, row):
# we are the primary manager for this attribute on
# this class - reset its
@@ -842,19 +917,26 @@ class ImmediateLoader(AbstractRelationshipLoader):
__slots__ = ()
def init_class_attribute(self, mapper):
- self.parent_property.\
- _get_strategy((("lazy", "select"),)).\
- init_class_attribute(mapper)
+ self.parent_property._get_strategy(
+ (("lazy", "select"),)
+ ).init_class_attribute(mapper)
def setup_query(
- self, context, entity,
- path, loadopt, adapter, column_collection=None,
- parentmapper=None, **kwargs):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection=None,
+ parentmapper=None,
+ **kwargs
+ ):
pass
def create_row_processor(
- self, context, path, loadopt,
- mapper, result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
def load_immediate(state, dict_, row):
state.get_impl(self.key).get(state, dict_)
@@ -864,22 +946,28 @@ class ImmediateLoader(AbstractRelationshipLoader):
@log.class_logger
@properties.RelationshipProperty.strategy_for(lazy="subquery")
class SubqueryLoader(AbstractRelationshipLoader):
- __slots__ = 'join_depth',
+ __slots__ = ("join_depth",)
def __init__(self, parent, strategy_key):
super(SubqueryLoader, self).__init__(parent, strategy_key)
self.join_depth = self.parent_property.join_depth
def init_class_attribute(self, mapper):
- self.parent_property.\
- _get_strategy((("lazy", "select"),)).\
- init_class_attribute(mapper)
+ self.parent_property._get_strategy(
+ (("lazy", "select"),)
+ ).init_class_attribute(mapper)
def setup_query(
- self, context, entity,
- path, loadopt, adapter,
- column_collection=None,
- parentmapper=None, **kwargs):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection=None,
+ parentmapper=None,
+ **kwargs
+ ):
if not context.query._enable_eagerloads:
return
@@ -891,16 +979,16 @@ class SubqueryLoader(AbstractRelationshipLoader):
# build up a path indicating the path from the leftmost
# entity to the thing we're subquery loading.
with_poly_info = path.get(
- context.attributes,
- "path_with_polymorphic", None)
+ context.attributes, "path_with_polymorphic", None
+ )
if with_poly_info is not None:
effective_entity = with_poly_info.entity
else:
effective_entity = self.mapper
subq_path = context.attributes.get(
- ('subquery_path', None),
- orm_util.PathRegistry.root)
+ ("subquery_path", None), orm_util.PathRegistry.root
+ )
subq_path = subq_path + path
@@ -909,27 +997,33 @@ class SubqueryLoader(AbstractRelationshipLoader):
if not path.contains(context.attributes, "loader"):
if self.join_depth:
if (
- (context.query._current_path.length
- if context.query._current_path else 0) +
- path.length
+ (
+ context.query._current_path.length
+ if context.query._current_path
+ else 0
+ )
+ + path.length
) / 2 > self.join_depth:
return
elif subq_path.contains_mapper(self.mapper):
return
- leftmost_mapper, leftmost_attr, leftmost_relationship = \
- self._get_leftmost(subq_path)
+ leftmost_mapper, leftmost_attr, leftmost_relationship = self._get_leftmost(
+ subq_path
+ )
orig_query = context.attributes.get(
- ("orig_query", SubqueryLoader),
- context.query)
+ ("orig_query", SubqueryLoader), context.query
+ )
# generate a new Query from the original, then
# produce a subquery from it.
left_alias = self._generate_from_original_query(
- orig_query, leftmost_mapper,
- leftmost_attr, leftmost_relationship,
- entity.entity_zero
+ orig_query,
+ leftmost_mapper,
+ leftmost_attr,
+ leftmost_relationship,
+ entity.entity_zero,
)
# generate another Query that will join the
@@ -940,17 +1034,18 @@ class SubqueryLoader(AbstractRelationshipLoader):
q = orig_query.session.query(effective_entity)
q._attributes = {
("orig_query", SubqueryLoader): orig_query,
- ('subquery_path', None): subq_path
+ ("subquery_path", None): subq_path,
}
q = q._set_enable_single_crit(False)
- to_join, local_attr, parent_alias = \
- self._prep_for_joins(left_alias, subq_path)
+ to_join, local_attr, parent_alias = self._prep_for_joins(
+ left_alias, subq_path
+ )
q = q.order_by(*local_attr)
q = q.add_columns(*local_attr)
q = self._apply_joins(
- q, to_join, left_alias,
- parent_alias, effective_entity)
+ q, to_join, left_alias, parent_alias, effective_entity
+ )
q = self._setup_options(q, subq_path, orig_query, effective_entity)
q = self._setup_outermost_orderby(q)
@@ -964,21 +1059,20 @@ class SubqueryLoader(AbstractRelationshipLoader):
subq_mapper = orm_util._class_to_mapper(subq_path[0])
# determine attributes of the leftmost mapper
- if self.parent.isa(subq_mapper) and \
- self.parent_property is subq_path[1]:
- leftmost_mapper, leftmost_prop = \
- self.parent, self.parent_property
+ if (
+ self.parent.isa(subq_mapper)
+ and self.parent_property is subq_path[1]
+ ):
+ leftmost_mapper, leftmost_prop = self.parent, self.parent_property
else:
- leftmost_mapper, leftmost_prop = \
- subq_mapper, \
- subq_path[1]
+ leftmost_mapper, leftmost_prop = subq_mapper, subq_path[1]
leftmost_cols = leftmost_prop.local_columns
leftmost_attr = [
getattr(
- subq_path[0].entity,
- leftmost_mapper._columntoproperty[c].key)
+ subq_path[0].entity, leftmost_mapper._columntoproperty[c].key
+ )
for c in leftmost_cols
]
@@ -986,8 +1080,11 @@ class SubqueryLoader(AbstractRelationshipLoader):
def _generate_from_original_query(
self,
- orig_query, leftmost_mapper,
- leftmost_attr, leftmost_relationship, orig_entity
+ orig_query,
+ leftmost_mapper,
+ leftmost_attr,
+ leftmost_relationship,
+ orig_entity,
):
# reformat the original query
# to look only for significant columns
@@ -999,11 +1096,16 @@ class SubqueryLoader(AbstractRelationshipLoader):
# all entities mentioned in things like WHERE, JOIN, etc.
if not q._from_obj:
q._set_select_from(
- list(set([
- ent['entity'] for ent in orig_query.column_descriptions
- if ent['entity'] is not None
- ])),
- False
+ list(
+ set(
+ [
+ ent["entity"]
+ for ent in orig_query.column_descriptions
+ if ent["entity"] is not None
+ ]
+ )
+ ),
+ False,
)
# select from the identity columns of the outer (specifically, these
@@ -1037,8 +1139,8 @@ class SubqueryLoader(AbstractRelationshipLoader):
embed_q = q.with_labels().subquery()
left_alias = orm_util.AliasedClass(
- leftmost_mapper, embed_q,
- use_mapper_path=True)
+ leftmost_mapper, embed_q, use_mapper_path=True
+ )
return left_alias
def _prep_for_joins(self, left_alias, subq_path):
@@ -1077,8 +1179,8 @@ class SubqueryLoader(AbstractRelationshipLoader):
# alias a plain mapper as we may be
# joining multiple times
parent_alias = orm_util.AliasedClass(
- info.entity,
- use_mapper_path=True)
+ info.entity, use_mapper_path=True
+ )
local_cols = self.parent_property.local_columns
@@ -1089,8 +1191,8 @@ class SubqueryLoader(AbstractRelationshipLoader):
return to_join, local_attr, parent_alias
def _apply_joins(
- self, q, to_join, left_alias, parent_alias,
- effective_entity):
+ self, q, to_join, left_alias, parent_alias, effective_entity
+ ):
ltj = len(to_join)
if ltj == 1:
@@ -1100,7 +1202,9 @@ class SubqueryLoader(AbstractRelationshipLoader):
elif ltj == 2:
to_join = [
getattr(left_alias, to_join[0][1]).of_type(parent_alias),
- getattr(parent_alias, to_join[-1][1]).of_type(effective_entity)
+ getattr(parent_alias, to_join[-1][1]).of_type(
+ effective_entity
+ ),
]
elif ltj > 2:
middle = [
@@ -1108,8 +1212,9 @@ class SubqueryLoader(AbstractRelationshipLoader):
orm_util.AliasedClass(item[0])
if not inspect(item[0]).is_aliased_class
else item[0].entity,
- item[1]
- ) for item in to_join[1:-1]
+ item[1],
+ )
+ for item in to_join[1:-1]
]
inner = []
@@ -1123,11 +1228,15 @@ class SubqueryLoader(AbstractRelationshipLoader):
inner.append(attr)
- to_join = [
- getattr(left_alias, to_join[0][1]).of_type(inner[0].parent)
- ] + inner + [
- getattr(parent_alias, to_join[-1][1]).of_type(effective_entity)
- ]
+ to_join = (
+ [getattr(left_alias, to_join[0][1]).of_type(inner[0].parent)]
+ + inner
+ + [
+ getattr(parent_alias, to_join[-1][1]).of_type(
+ effective_entity
+ )
+ ]
+ )
for attr in to_join:
q = q.join(attr, from_joinpoint=True)
@@ -1151,13 +1260,9 @@ class SubqueryLoader(AbstractRelationshipLoader):
# this really only picks up the "secondary" table
# right now.
eagerjoin = q._from_obj[0]
- eager_order_by = \
- eagerjoin._target_adapter.\
- copy_and_process(
- util.to_list(
- self.parent_property.order_by
- )
- )
+ eager_order_by = eagerjoin._target_adapter.copy_and_process(
+ util.to_list(self.parent_property.order_by)
+ )
q = q.order_by(*eager_order_by)
return q
@@ -1167,6 +1272,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
first moment a value is needed.
"""
+
_data = None
def __init__(self, subq):
@@ -1180,10 +1286,7 @@ class SubqueryLoader(AbstractRelationshipLoader):
def _load(self):
self._data = dict(
(k, [vv[0] for vv in v])
- for k, v in itertools.groupby(
- self.subq,
- lambda x: x[1:]
- )
+ for k, v in itertools.groupby(self.subq, lambda x: x[1:])
)
def loader(self, state, dict_, row):
@@ -1191,17 +1294,17 @@ class SubqueryLoader(AbstractRelationshipLoader):
self._load()
def create_row_processor(
- self, context, path, loadopt,
- mapper, result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
if not self.parent.class_manager[self.key].impl.supports_population:
raise sa_exc.InvalidRequestError(
"'%s' does not support object "
- "population - eager loading cannot be applied." %
- self)
+ "population - eager loading cannot be applied." % self
+ )
path = path[self.parent_property]
- subq = path.get(context.attributes, 'subquery')
+ subq = path.get(context.attributes, "subquery")
if subq is None:
return
@@ -1220,65 +1323,67 @@ class SubqueryLoader(AbstractRelationshipLoader):
collections = path.get(context.attributes, "collections")
if collections is None:
collections = self._SubqCollections(subq)
- path.set(context.attributes, 'collections', collections)
+ path.set(context.attributes, "collections", collections)
if adapter:
local_cols = [adapter.columns[c] for c in local_cols]
if self.uselist:
self._create_collection_loader(
- context, collections, local_cols, populators)
+ context, collections, local_cols, populators
+ )
else:
self._create_scalar_loader(
- context, collections, local_cols, populators)
+ context, collections, local_cols, populators
+ )
def _create_collection_loader(
- self, context, collections, local_cols, populators):
+ self, context, collections, local_cols, populators
+ ):
def load_collection_from_subq(state, dict_, row):
collection = collections.get(
- tuple([row[col] for col in local_cols]),
- ()
+ tuple([row[col] for col in local_cols]), ()
+ )
+ state.get_impl(self.key).set_committed_value(
+ state, dict_, collection
)
- state.get_impl(self.key).\
- set_committed_value(state, dict_, collection)
def load_collection_from_subq_existing_row(state, dict_, row):
if self.key not in dict_:
load_collection_from_subq(state, dict_, row)
- populators["new"].append(
- (self.key, load_collection_from_subq))
+ populators["new"].append((self.key, load_collection_from_subq))
populators["existing"].append(
- (self.key, load_collection_from_subq_existing_row))
+ (self.key, load_collection_from_subq_existing_row)
+ )
if context.invoke_all_eagers:
populators["eager"].append((self.key, collections.loader))
def _create_scalar_loader(
- self, context, collections, local_cols, populators):
+ self, context, collections, local_cols, populators
+ ):
def load_scalar_from_subq(state, dict_, row):
collection = collections.get(
- tuple([row[col] for col in local_cols]),
- (None,)
+ tuple([row[col] for col in local_cols]), (None,)
)
if len(collection) > 1:
util.warn(
"Multiple rows returned with "
- "uselist=False for eagerly-loaded attribute '%s' "
- % self)
+ "uselist=False for eagerly-loaded attribute '%s' " % self
+ )
scalar = collection[0]
- state.get_impl(self.key).\
- set_committed_value(state, dict_, scalar)
+ state.get_impl(self.key).set_committed_value(state, dict_, scalar)
def load_scalar_from_subq_existing_row(state, dict_, row):
if self.key not in dict_:
load_scalar_from_subq(state, dict_, row)
- populators["new"].append(
- (self.key, load_scalar_from_subq))
+ populators["new"].append((self.key, load_scalar_from_subq))
populators["existing"].append(
- (self.key, load_scalar_from_subq_existing_row))
+ (self.key, load_scalar_from_subq_existing_row)
+ )
if context.invoke_all_eagers:
populators["eager"].append((self.key, collections.loader))
@@ -1292,7 +1397,7 @@ class JoinedLoader(AbstractRelationshipLoader):
"""
- __slots__ = 'join_depth', '_aliased_class_pool'
+ __slots__ = "join_depth", "_aliased_class_pool"
def __init__(self, parent, strategy_key):
super(JoinedLoader, self).__init__(parent, strategy_key)
@@ -1300,14 +1405,22 @@ class JoinedLoader(AbstractRelationshipLoader):
self._aliased_class_pool = []
def init_class_attribute(self, mapper):
- self.parent_property.\
- _get_strategy((("lazy", "select"),)).init_class_attribute(mapper)
+ self.parent_property._get_strategy(
+ (("lazy", "select"),)
+ ).init_class_attribute(mapper)
def setup_query(
- self, context, entity, path, loadopt, adapter,
- column_collection=None, parentmapper=None,
- chained_from_outerjoin=False,
- **kwargs):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection=None,
+ parentmapper=None,
+ chained_from_outerjoin=False,
+ **kwargs
+ ):
"""Add a left outer join to the statement that's being constructed."""
if not context.query._enable_eagerloads:
@@ -1319,15 +1432,16 @@ class JoinedLoader(AbstractRelationshipLoader):
with_polymorphic = None
- user_defined_adapter = self._init_user_defined_eager_proc(
- loadopt, context) if loadopt else False
+ user_defined_adapter = (
+ self._init_user_defined_eager_proc(loadopt, context)
+ if loadopt
+ else False
+ )
if user_defined_adapter is not False:
- clauses, adapter, add_to_collection = \
- self._setup_query_on_user_defined_adapter(
- context, entity, path, adapter,
- user_defined_adapter
- )
+ clauses, adapter, add_to_collection = self._setup_query_on_user_defined_adapter(
+ context, entity, path, adapter, user_defined_adapter
+ )
else:
# if not via query option, check for
# a cycle
@@ -1338,16 +1452,19 @@ class JoinedLoader(AbstractRelationshipLoader):
elif path.contains_mapper(self.mapper):
return
- clauses, adapter, add_to_collection, chained_from_outerjoin = \
- self._generate_row_adapter(
- context, entity, path, loadopt, adapter,
- column_collection, parentmapper, chained_from_outerjoin
- )
+ clauses, adapter, add_to_collection, chained_from_outerjoin = self._generate_row_adapter(
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection,
+ parentmapper,
+ chained_from_outerjoin,
+ )
with_poly_info = path.get(
- context.attributes,
- "path_with_polymorphic",
- None
+ context.attributes, "path_with_polymorphic", None
)
if with_poly_info is not None:
with_polymorphic = with_poly_info.with_polymorphic_mappers
@@ -1357,14 +1474,20 @@ class JoinedLoader(AbstractRelationshipLoader):
path = path[self.mapper]
loading._setup_entity_query(
- context, self.mapper, entity,
- path, clauses, add_to_collection,
+ context,
+ self.mapper,
+ entity,
+ path,
+ clauses,
+ add_to_collection,
with_polymorphic=with_polymorphic,
parentmapper=self.mapper,
- chained_from_outerjoin=chained_from_outerjoin)
+ chained_from_outerjoin=chained_from_outerjoin,
+ )
- if with_poly_info is not None and \
- None in set(context.secondary_columns):
+ if with_poly_info is not None and None in set(
+ context.secondary_columns
+ ):
raise sa_exc.InvalidRequestError(
"Detected unaliased columns when generating joined "
"load. Make sure to use aliased=True or flat=True "
@@ -1383,8 +1506,8 @@ class JoinedLoader(AbstractRelationshipLoader):
# the option applies. check if the "user_defined_eager_row_processor"
# has been built up.
adapter = path.get(
- context.attributes,
- "user_defined_eager_row_processor", False)
+ context.attributes, "user_defined_eager_row_processor", False
+ )
if adapter is not False:
# just return it
return adapter
@@ -1394,38 +1517,39 @@ class JoinedLoader(AbstractRelationshipLoader):
root_mapper, prop = path[-2:]
- #from .mapper import Mapper
- #from .interfaces import MapperProperty
- #assert isinstance(root_mapper, Mapper)
- #assert isinstance(prop, MapperProperty)
+ # from .mapper import Mapper
+ # from .interfaces import MapperProperty
+ # assert isinstance(root_mapper, Mapper)
+ # assert isinstance(prop, MapperProperty)
if alias is not None:
if isinstance(alias, str):
alias = prop.target.alias(alias)
adapter = sql_util.ColumnAdapter(
- alias,
- equivalents=prop.mapper._equivalent_columns)
+ alias, equivalents=prop.mapper._equivalent_columns
+ )
else:
if path.contains(context.attributes, "path_with_polymorphic"):
with_poly_info = path.get(
- context.attributes,
- "path_with_polymorphic")
+ context.attributes, "path_with_polymorphic"
+ )
adapter = orm_util.ORMAdapter(
with_poly_info.entity,
- equivalents=prop.mapper._equivalent_columns)
+ equivalents=prop.mapper._equivalent_columns,
+ )
else:
adapter = context.query._polymorphic_adapters.get(
- prop.mapper, None)
+ prop.mapper, None
+ )
path.set(
- context.attributes,
- "user_defined_eager_row_processor",
- adapter)
+ context.attributes, "user_defined_eager_row_processor", adapter
+ )
return adapter
def _setup_query_on_user_defined_adapter(
- self, context, entity,
- path, adapter, user_defined_adapter):
+ self, context, entity, path, adapter, user_defined_adapter
+ ):
# apply some more wrapping to the "user defined adapter"
# if we are setting up the query for SQL render.
@@ -1434,13 +1558,17 @@ class JoinedLoader(AbstractRelationshipLoader):
if adapter and user_defined_adapter:
user_defined_adapter = user_defined_adapter.wrap(adapter)
path.set(
- context.attributes, "user_defined_eager_row_processor",
- user_defined_adapter)
+ context.attributes,
+ "user_defined_eager_row_processor",
+ user_defined_adapter,
+ )
elif adapter:
user_defined_adapter = adapter
path.set(
- context.attributes, "user_defined_eager_row_processor",
- user_defined_adapter)
+ context.attributes,
+ "user_defined_eager_row_processor",
+ user_defined_adapter,
+ )
add_to_collection = context.primary_columns
return user_defined_adapter, adapter, add_to_collection
@@ -1450,7 +1578,7 @@ class JoinedLoader(AbstractRelationshipLoader):
# we need one unique AliasedClass per query per appearance of our
# entity in the query.
- key = ('joinedloader_ac', self)
+ key = ("joinedloader_ac", self)
if key not in context.attributes:
context.attributes[key] = idx = 0
else:
@@ -1458,9 +1586,8 @@ class JoinedLoader(AbstractRelationshipLoader):
if idx >= len(self._aliased_class_pool):
to_adapt = orm_util.AliasedClass(
- self.mapper,
- flat=True,
- use_mapper_path=True)
+ self.mapper, flat=True, use_mapper_path=True
+ )
# load up the .columns collection on the Alias() before
# the object becomes shared among threads. this prevents
# races for column identities.
@@ -1471,13 +1598,18 @@ class JoinedLoader(AbstractRelationshipLoader):
return self._aliased_class_pool[idx]
def _generate_row_adapter(
- self,
- context, entity, path, loadopt, adapter,
- column_collection, parentmapper, chained_from_outerjoin):
+ self,
+ context,
+ entity,
+ path,
+ loadopt,
+ adapter,
+ column_collection,
+ parentmapper,
+ chained_from_outerjoin,
+ ):
with_poly_info = path.get(
- context.attributes,
- "path_with_polymorphic",
- None
+ context.attributes, "path_with_polymorphic", None
)
if with_poly_info:
to_adapt = with_poly_info.entity
@@ -1489,8 +1621,9 @@ class JoinedLoader(AbstractRelationshipLoader):
orm_util.ORMAdapter,
to_adapt,
equivalents=self.mapper._equivalent_columns,
- adapt_required=True, allow_label_resolve=False,
- anonymize_labels=True
+ adapt_required=True,
+ allow_label_resolve=False,
+ anonymize_labels=True,
)
assert clauses.aliased_class is not None
@@ -1499,8 +1632,7 @@ class JoinedLoader(AbstractRelationshipLoader):
context.multi_row_eager_loaders = True
innerjoin = (
- loadopt.local_opts.get(
- 'innerjoin', self.parent_property.innerjoin)
+ loadopt.local_opts.get("innerjoin", self.parent_property.innerjoin)
if loadopt is not None
else self.parent_property.innerjoin
)
@@ -1512,9 +1644,15 @@ class JoinedLoader(AbstractRelationshipLoader):
context.create_eager_joins.append(
(
- self._create_eager_join, context,
- entity, path, adapter,
- parentmapper, clauses, innerjoin, chained_from_outerjoin
+ self._create_eager_join,
+ context,
+ entity,
+ path,
+ adapter,
+ parentmapper,
+ clauses,
+ innerjoin,
+ chained_from_outerjoin,
)
)
@@ -1524,9 +1662,16 @@ class JoinedLoader(AbstractRelationshipLoader):
return clauses, adapter, add_to_collection, chained_from_outerjoin
def _create_eager_join(
- self, context, entity,
- path, adapter, parentmapper,
- clauses, innerjoin, chained_from_outerjoin):
+ self,
+ context,
+ entity,
+ path,
+ adapter,
+ parentmapper,
+ clauses,
+ innerjoin,
+ chained_from_outerjoin,
+ ):
if parentmapper is None:
localparent = entity.mapper
@@ -1536,16 +1681,21 @@ class JoinedLoader(AbstractRelationshipLoader):
# whether or not the Query will wrap the selectable in a subquery,
# and then attach eager load joins to that (i.e., in the case of
# LIMIT/OFFSET etc.)
- should_nest_selectable = context.multi_row_eager_loaders and \
- context.query._should_nest_selectable
+ should_nest_selectable = (
+ context.multi_row_eager_loaders
+ and context.query._should_nest_selectable
+ )
entity_key = None
- if entity not in context.eager_joins and \
- not should_nest_selectable and \
- context.from_clause:
+ if (
+ entity not in context.eager_joins
+ and not should_nest_selectable
+ and context.from_clause
+ ):
indexes = sql_util.find_left_clause_that_matches_given(
- context.from_clause, entity.selectable)
+ context.from_clause, entity.selectable
+ )
if len(indexes) > 1:
# for the eager load case, I can't reproduce this right
@@ -1553,7 +1703,8 @@ class JoinedLoader(AbstractRelationshipLoader):
raise sa_exc.InvalidRequestError(
"Can't identify which entity in which to joined eager "
"load from. Please use an exact match when specifying "
- "the join path.")
+ "the join path."
+ )
if indexes:
clause = context.from_clause[indexes[0]]
@@ -1569,29 +1720,27 @@ class JoinedLoader(AbstractRelationshipLoader):
towrap = context.eager_joins.setdefault(entity_key, default_towrap)
if adapter:
- if getattr(adapter, 'aliased_class', None):
+ if getattr(adapter, "aliased_class", None):
# joining from an adapted entity. The adapted entity
# might be a "with_polymorphic", so resolve that to our
# specific mapper's entity before looking for our attribute
# name on it.
- efm = inspect(adapter.aliased_class).\
- _entity_for_mapper(
- localparent
- if localparent.isa(self.parent) else self.parent)
+ efm = inspect(adapter.aliased_class)._entity_for_mapper(
+ localparent
+ if localparent.isa(self.parent)
+ else self.parent
+ )
# look for our attribute on the adapted entity, else fall back
# to our straight property
- onclause = getattr(
- efm.entity, self.key,
- self.parent_property)
+ onclause = getattr(efm.entity, self.key, self.parent_property)
else:
onclause = getattr(
orm_util.AliasedClass(
- self.parent,
- adapter.selectable,
- use_mapper_path=True
+ self.parent, adapter.selectable, use_mapper_path=True
),
- self.key, self.parent_property
+ self.key,
+ self.parent_property,
)
else:
@@ -1600,9 +1749,10 @@ class JoinedLoader(AbstractRelationshipLoader):
assert clauses.aliased_class is not None
attach_on_outside = (
- not chained_from_outerjoin or
- not innerjoin or innerjoin == 'unnested' or
- entity.entity_zero.represents_outer_join
+ not chained_from_outerjoin
+ or not innerjoin
+ or innerjoin == "unnested"
+ or entity.entity_zero.represents_outer_join
)
if attach_on_outside:
@@ -1611,16 +1761,17 @@ class JoinedLoader(AbstractRelationshipLoader):
towrap,
clauses.aliased_class,
onclause,
- isouter=not innerjoin or
- entity.entity_zero.represents_outer_join or
- (
- chained_from_outerjoin and isinstance(towrap, sql.Join)
- ), _left_memo=self.parent, _right_memo=self.mapper
+ isouter=not innerjoin
+ or entity.entity_zero.represents_outer_join
+ or (chained_from_outerjoin and isinstance(towrap, sql.Join)),
+ _left_memo=self.parent,
+ _right_memo=self.mapper,
)
else:
# all other cases are innerjoin=='nested' approach
eagerjoin = self._splice_nested_inner_join(
- path, towrap, clauses, onclause)
+ path, towrap, clauses, onclause
+ )
context.eager_joins[entity_key] = eagerjoin
@@ -1636,22 +1787,21 @@ class JoinedLoader(AbstractRelationshipLoader):
# This has the effect
# of "undefering" those columns.
for col in sql_util._find_columns(
- self.parent_property.primaryjoin):
+ self.parent_property.primaryjoin
+ ):
if localparent.mapped_table.c.contains_column(col):
if adapter:
col = adapter.columns[col]
context.primary_columns.append(col)
if self.parent_property.order_by:
- context.eager_order_by += eagerjoin._target_adapter.\
- copy_and_process(
- util.to_list(
- self.parent_property.order_by
- )
- )
+ context.eager_order_by += eagerjoin._target_adapter.copy_and_process(
+ util.to_list(self.parent_property.order_by)
+ )
def _splice_nested_inner_join(
- self, path, join_obj, clauses, onclause, splicing=False):
+ self, path, join_obj, clauses, onclause, splicing=False
+ ):
if splicing is False:
# first call is always handed a join object
@@ -1664,28 +1814,31 @@ class JoinedLoader(AbstractRelationshipLoader):
elif not isinstance(join_obj, orm_util._ORMJoin):
if path[-2] is splicing:
return orm_util._ORMJoin(
- join_obj, clauses.aliased_class,
- onclause, isouter=False,
+ join_obj,
+ clauses.aliased_class,
+ onclause,
+ isouter=False,
_left_memo=splicing,
- _right_memo=path[-1].mapper
+ _right_memo=path[-1].mapper,
)
else:
# only here if splicing == True
return None
target_join = self._splice_nested_inner_join(
- path, join_obj.right, clauses,
- onclause, join_obj._right_memo)
+ path, join_obj.right, clauses, onclause, join_obj._right_memo
+ )
if target_join is None:
right_splice = False
target_join = self._splice_nested_inner_join(
- path, join_obj.left, clauses,
- onclause, join_obj._left_memo)
+ path, join_obj.left, clauses, onclause, join_obj._left_memo
+ )
if target_join is None:
# should only return None when recursively called,
# e.g. splicing==True
- assert splicing is not False, \
- "assertion failed attempting to produce joined eager loads"
+ assert (
+ splicing is not False
+ ), "assertion failed attempting to produce joined eager loads"
return None
else:
right_splice = True
@@ -1698,21 +1851,30 @@ class JoinedLoader(AbstractRelationshipLoader):
eagerjoin = join_obj._splice_into_center(target_join)
else:
eagerjoin = orm_util._ORMJoin(
- join_obj.left, target_join,
- join_obj.onclause, isouter=join_obj.isouter,
- _left_memo=join_obj._left_memo)
+ join_obj.left,
+ target_join,
+ join_obj.onclause,
+ isouter=join_obj.isouter,
+ _left_memo=join_obj._left_memo,
+ )
else:
eagerjoin = orm_util._ORMJoin(
- target_join, join_obj.right,
- join_obj.onclause, isouter=join_obj.isouter,
- _right_memo=join_obj._right_memo)
+ target_join,
+ join_obj.right,
+ join_obj.onclause,
+ isouter=join_obj.isouter,
+ _right_memo=join_obj._right_memo,
+ )
eagerjoin._target_adapter = target_join._target_adapter
return eagerjoin
def _create_eager_adapter(self, context, result, adapter, path, loadopt):
- user_defined_adapter = self._init_user_defined_eager_proc(
- loadopt, context) if loadopt else False
+ user_defined_adapter = (
+ self._init_user_defined_eager_proc(loadopt, context)
+ if loadopt
+ else False
+ )
if user_defined_adapter is not False:
decorator = user_defined_adapter
@@ -1736,21 +1898,19 @@ class JoinedLoader(AbstractRelationshipLoader):
return False
def create_row_processor(
- self, context, path, loadopt, mapper,
- result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
if not self.parent.class_manager[self.key].impl.supports_population:
raise sa_exc.InvalidRequestError(
"'%s' does not support object "
- "population - eager loading cannot be applied." %
- self
+ "population - eager loading cannot be applied." % self
)
our_path = path[self.parent_property]
eager_adapter = self._create_eager_adapter(
- context,
- result,
- adapter, our_path, loadopt)
+ context, result, adapter, our_path, loadopt
+ )
if eager_adapter is not False:
key = self.key
@@ -1760,25 +1920,28 @@ class JoinedLoader(AbstractRelationshipLoader):
context,
result,
our_path[self.mapper],
- eager_adapter)
+ eager_adapter,
+ )
if not self.uselist:
self._create_scalar_loader(context, key, _instance, populators)
else:
self._create_collection_loader(
- context, key, _instance, populators)
+ context, key, _instance, populators
+ )
else:
- self.parent_property._get_strategy((("lazy", "select"),)).\
- create_row_processor(
- context, path, loadopt,
- mapper, result, adapter, populators)
+ self.parent_property._get_strategy(
+ (("lazy", "select"),)
+ ).create_row_processor(
+ context, path, loadopt, mapper, result, adapter, populators
+ )
def _create_collection_loader(self, context, key, _instance, populators):
def load_collection_from_joined_new_row(state, dict_, row):
- collection = attributes.init_state_collection(
- state, dict_, key)
- result_list = util.UniqueAppender(collection,
- 'append_without_event')
+ collection = attributes.init_state_collection(state, dict_, key)
+ result_list = util.UniqueAppender(
+ collection, "append_without_event"
+ )
context.attributes[(state, key)] = result_list
inst = _instance(row)
if inst is not None:
@@ -1793,10 +1956,11 @@ class JoinedLoader(AbstractRelationshipLoader):
# is used; the same instance may be present in two
# distinct sets of result columns
collection = attributes.init_state_collection(
- state, dict_, key)
+ state, dict_, key
+ )
result_list = util.UniqueAppender(
- collection,
- 'append_without_event')
+ collection, "append_without_event"
+ )
context.attributes[(state, key)] = result_list
inst = _instance(row)
if inst is not None:
@@ -1805,12 +1969,16 @@ class JoinedLoader(AbstractRelationshipLoader):
def load_collection_from_joined_exec(state, dict_, row):
_instance(row)
- populators["new"].append((self.key, load_collection_from_joined_new_row))
+ populators["new"].append(
+ (self.key, load_collection_from_joined_new_row)
+ )
populators["existing"].append(
- (self.key, load_collection_from_joined_existing_row))
+ (self.key, load_collection_from_joined_existing_row)
+ )
if context.invoke_all_eagers:
populators["eager"].append(
- (self.key, load_collection_from_joined_exec))
+ (self.key, load_collection_from_joined_exec)
+ )
def _create_scalar_loader(self, context, key, _instance, populators):
def load_scalar_from_joined_new_row(state, dict_, row):
@@ -1829,7 +1997,8 @@ class JoinedLoader(AbstractRelationshipLoader):
util.warn(
"Multiple rows returned with "
"uselist=False for eagerly-loaded attribute '%s' "
- % self)
+ % self
+ )
else:
# this case is when one row has multiple loads of the
# same entity (e.g. via aliasing), one has an attribute
@@ -1841,17 +2010,25 @@ class JoinedLoader(AbstractRelationshipLoader):
populators["new"].append((self.key, load_scalar_from_joined_new_row))
populators["existing"].append(
- (self.key, load_scalar_from_joined_existing_row))
+ (self.key, load_scalar_from_joined_existing_row)
+ )
if context.invoke_all_eagers:
- populators["eager"].append((self.key, load_scalar_from_joined_exec))
+ populators["eager"].append(
+ (self.key, load_scalar_from_joined_exec)
+ )
@log.class_logger
@properties.RelationshipProperty.strategy_for(lazy="selectin")
class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
__slots__ = (
- 'join_depth', 'omit_join', '_parent_alias', '_in_expr',
- '_pk_cols', '_zero_idx', '_bakery'
+ "join_depth",
+ "omit_join",
+ "_parent_alias",
+ "_in_expr",
+ "_pk_cols",
+ "_zero_idx",
+ "_bakery",
)
_chunksize = 500
@@ -1864,11 +2041,12 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
self.omit_join = self.parent_property.omit_join
else:
lazyloader = self.parent_property._get_strategy(
- (("lazy", "select"),))
+ (("lazy", "select"),)
+ )
self.omit_join = self.parent._get_clause[0].compare(
lazyloader._rev_lazywhere,
use_proxies=True,
- equivalents=self.parent._equivalent_columns
+ equivalents=self.parent._equivalent_columns,
)
if self.omit_join:
self._init_for_omit_join()
@@ -1886,8 +2064,8 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
)
self._pk_cols = fk_cols = [
- pk_to_fk[col]
- for col in self.parent.primary_key if col in pk_to_fk]
+ pk_to_fk[col] for col in self.parent.primary_key if col in pk_to_fk
+ ]
if len(fk_cols) > 1:
self._in_expr = sql.tuple_(*fk_cols)
self._zero_idx = False
@@ -1899,7 +2077,8 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
self._parent_alias = aliased(self.parent.class_)
pa_insp = inspect(self._parent_alias)
self._pk_cols = pk_cols = [
- pa_insp._adapt_element(col) for col in self.parent.primary_key]
+ pa_insp._adapt_element(col) for col in self.parent.primary_key
+ ]
if len(pk_cols) > 1:
self._in_expr = sql.tuple_(*pk_cols)
self._zero_idx = False
@@ -1908,26 +2087,26 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
self._zero_idx = True
def init_class_attribute(self, mapper):
- self.parent_property.\
- _get_strategy((("lazy", "select"),)).\
- init_class_attribute(mapper)
+ self.parent_property._get_strategy(
+ (("lazy", "select"),)
+ ).init_class_attribute(mapper)
@util.dependencies("sqlalchemy.ext.baked")
def _memoized_attr__bakery(self, baked):
return baked.bakery(size=50)
def create_row_processor(
- self, context, path, loadopt, mapper,
- result, adapter, populators):
+ self, context, path, loadopt, mapper, result, adapter, populators
+ ):
if not self.parent.class_manager[self.key].impl.supports_population:
raise sa_exc.InvalidRequestError(
"'%s' does not support object "
- "population - eager loading cannot be applied." %
- self
+ "population - eager loading cannot be applied." % self
)
selectin_path = (
- context.query._current_path or orm_util.PathRegistry.root) + path
+ context.query._current_path or orm_util.PathRegistry.root
+ ) + path
if not orm_util._entity_isa(path[-1], self.parent):
return
@@ -1941,8 +2120,8 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
# build up a path indicating the path from the leftmost
# entity to the thing we're subquery loading.
with_poly_info = path_w_prop.get(
- context.attributes,
- "path_with_polymorphic", None)
+ context.attributes, "path_with_polymorphic", None
+ )
if with_poly_info is not None:
effective_entity = with_poly_info.entity
@@ -1957,19 +2136,24 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
return
loading.PostLoad.callable_for_path(
- context, selectin_path, self.parent, self.key,
- self._load_for_path, effective_entity)
+ context,
+ selectin_path,
+ self.parent,
+ self.key,
+ self._load_for_path,
+ effective_entity,
+ )
@util.dependencies("sqlalchemy.ext.baked")
def _load_for_path(
- self, baked, context, path, states, load_only, effective_entity):
+ self, baked, context, path, states, load_only, effective_entity
+ ):
if load_only and self.key not in load_only:
return
our_states = [
- (state.key[1], state, overwrite)
- for state, overwrite in states
+ (state.key[1], state, overwrite) for state, overwrite in states
]
pk_cols = self._pk_cols
@@ -1984,17 +2168,15 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
# parent entity and do not need adaption.
insp = inspect(effective_entity)
if insp.is_aliased_class:
- pk_cols = [
- insp._adapt_element(col)
- for col in pk_cols
- ]
+ pk_cols = [insp._adapt_element(col) for col in pk_cols]
in_expr = insp._adapt_element(in_expr)
pk_cols = [insp._adapt_element(col) for col in pk_cols]
q = self._bakery(
lambda session: session.query(
- query.Bundle("pk", *pk_cols), effective_entity,
- ), self
+ query.Bundle("pk", *pk_cols), effective_entity
+ ),
+ self,
)
if self.omit_join:
@@ -2012,60 +2194,53 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
q.add_criteria(
lambda q: q.select_from(pa).join(
getattr(pa, self.parent_property.key).of_type(
- effective_entity)
+ effective_entity
+ )
)
)
q.add_criteria(
lambda q: q.filter(
- in_expr.in_(
- sql.bindparam("primary_keys", expanding=True))
- ).order_by(*pk_cols))
+ in_expr.in_(sql.bindparam("primary_keys", expanding=True))
+ ).order_by(*pk_cols)
+ )
orig_query = context.query
q._add_lazyload_options(
- orig_query._with_options,
- path[self.parent_property]
+ orig_query._with_options, path[self.parent_property]
)
if orig_query._populate_existing:
- q.add_criteria(
- lambda q: q.populate_existing()
- )
+ q.add_criteria(lambda q: q.populate_existing())
if self.parent_property.order_by:
if self.omit_join:
eager_order_by = self.parent_property.order_by
if insp.is_aliased_class:
eager_order_by = [
- insp._adapt_element(elem) for elem in
- eager_order_by
+ insp._adapt_element(elem) for elem in eager_order_by
]
- q.add_criteria(
- lambda q: q.order_by(*eager_order_by)
- )
+ q.add_criteria(lambda q: q.order_by(*eager_order_by))
else:
+
def _setup_outermost_orderby(q):
# imitate the same method that subquery eager loading uses,
# looking for the adapted "secondary" table
eagerjoin = q._from_obj[0]
- eager_order_by = \
- eagerjoin._target_adapter.\
- copy_and_process(
- util.to_list(self.parent_property.order_by)
- )
+ eager_order_by = eagerjoin._target_adapter.copy_and_process(
+ util.to_list(self.parent_property.order_by)
+ )
return q.order_by(*eager_order_by)
- q.add_criteria(
- _setup_outermost_orderby
- )
+
+ q.add_criteria(_setup_outermost_orderby)
uselist = self.uselist
_empty_result = () if uselist else None
while our_states:
- chunk = our_states[0:self._chunksize]
- our_states = our_states[self._chunksize:]
+ chunk = our_states[0 : self._chunksize]
+ our_states = our_states[self._chunksize :]
data = {
k: [vv[1] for vv in v]
@@ -2073,9 +2248,10 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
q(context.session).params(
primary_keys=[
key[0] if self._zero_idx else key
- for key, state, overwrite in chunk]
+ for key, state, overwrite in chunk
+ ]
),
- lambda x: x[0]
+ lambda x: x[0],
)
}
@@ -2091,13 +2267,15 @@ class SelectInLoader(AbstractRelationshipLoader, util.MemoizedSlots):
util.warn(
"Multiple rows returned with "
"uselist=False for eagerly-loaded "
- "attribute '%s' "
- % self)
+ "attribute '%s' " % self
+ )
state.get_impl(self.key).set_committed_value(
- state, state.dict, collection[0])
+ state, state.dict, collection[0]
+ )
else:
state.get_impl(self.key).set_committed_value(
- state, state.dict, collection)
+ state, state.dict, collection
+ )
def single_parent_validator(desc, prop):
@@ -2108,8 +2286,8 @@ def single_parent_validator(desc, prop):
raise sa_exc.InvalidRequestError(
"Instance %s is already associated with an instance "
"of %s via its %s attribute, and is only allowed a "
- "single parent." %
- (orm_util.instance_str(value), state.class_, prop)
+ "single parent."
+ % (orm_util.instance_str(value), state.class_, prop)
)
return value
@@ -2120,8 +2298,6 @@ def single_parent_validator(desc, prop):
return _do_check(state, value, oldvalue, initiator)
event.listen(
- desc, 'append', append, raw=True, retval=True,
- active_history=True)
- event.listen(
- desc, 'set', set_, raw=True, retval=True,
- active_history=True)
+ desc, "append", append, raw=True, retval=True, active_history=True
+ )
+ event.listen(desc, "set", set_, raw=True, retval=True, active_history=True)
diff --git a/lib/sqlalchemy/orm/strategy_options.py b/lib/sqlalchemy/orm/strategy_options.py
index f0d209110..b2f6bcb11 100644
--- a/lib/sqlalchemy/orm/strategy_options.py
+++ b/lib/sqlalchemy/orm/strategy_options.py
@@ -13,11 +13,19 @@ from .attributes import QueryableAttribute
from .. import util
from ..sql.base import _generative, Generative
from .. import exc as sa_exc, inspect
-from .base import _is_aliased_class, _class_to_mapper, _is_mapped_class, \
- InspectionAttr
+from .base import (
+ _is_aliased_class,
+ _class_to_mapper,
+ _is_mapped_class,
+ InspectionAttr,
+)
from . import util as orm_util
-from .path_registry import PathRegistry, TokenRegistry, \
- _WILDCARD_TOKEN, _DEFAULT_TOKEN
+from .path_registry import (
+ PathRegistry,
+ TokenRegistry,
+ _WILDCARD_TOKEN,
+ _DEFAULT_TOKEN,
+)
class Load(Generative, MapperOption):
@@ -94,12 +102,14 @@ class Load(Generative, MapperOption):
if (
# means loader_path and path are unrelated,
# this does not need to be part of a cache key
- chopped is None
+ chopped
+ is None
) or (
# means no additional path with loader_path + path
# and the endpoint isn't using of_type so isn't modified
# into an alias or other unsafe entity
- not chopped and not obj._of_type
+ not chopped
+ and not obj._of_type
):
continue
@@ -124,12 +134,18 @@ class Load(Generative, MapperOption):
serialized.append(
(
- tuple(serialized_path) +
- (obj.strategy or ()) +
- (tuple([
- (key, obj.local_opts[key])
- for key in sorted(obj.local_opts)
- ]) if obj.local_opts else ())
+ tuple(serialized_path)
+ + (obj.strategy or ())
+ + (
+ tuple(
+ [
+ (key, obj.local_opts[key])
+ for key in sorted(obj.local_opts)
+ ]
+ )
+ if obj.local_opts
+ else ()
+ )
)
)
if not serialized:
@@ -170,12 +186,13 @@ class Load(Generative, MapperOption):
if raiseerr and not path.has_entity:
if isinstance(path, TokenRegistry):
raise sa_exc.ArgumentError(
- "Wildcard token cannot be followed by another entity")
+ "Wildcard token cannot be followed by another entity"
+ )
else:
raise sa_exc.ArgumentError(
"Attribute '%s' of entity '%s' does not "
- "refer to a mapped entity" %
- (path.prop.key, path.parent.entity)
+ "refer to a mapped entity"
+ % (path.prop.key, path.parent.entity)
)
if isinstance(attr, util.string_types):
@@ -201,8 +218,7 @@ class Load(Generative, MapperOption):
if raiseerr:
raise sa_exc.ArgumentError(
"Can't find property named '%s' on the "
- "mapped entity %s in this Query. " % (
- attr, ent)
+ "mapped entity %s in this Query. " % (attr, ent)
)
else:
return None
@@ -215,7 +231,8 @@ class Load(Generative, MapperOption):
if raiseerr:
raise sa_exc.ArgumentError(
"Attribute '%s' does not "
- "link from element '%s'" % (attr, path.entity))
+ "link from element '%s'" % (attr, path.entity)
+ )
else:
return None
else:
@@ -225,22 +242,26 @@ class Load(Generative, MapperOption):
if raiseerr:
raise sa_exc.ArgumentError(
"Attribute '%s' does not "
- "link from element '%s'" % (attr, path.entity))
+ "link from element '%s'" % (attr, path.entity)
+ )
else:
return None
- if getattr(attr, '_of_type', None):
+ if getattr(attr, "_of_type", None):
ac = attr._of_type
ext_info = of_type_info = inspect(ac)
existing = path.entity_path[prop].get(
- self.context, "path_with_polymorphic")
+ self.context, "path_with_polymorphic"
+ )
if not ext_info.is_aliased_class:
ac = orm_util.with_polymorphic(
ext_info.mapper.base_mapper,
- ext_info.mapper, aliased=True,
+ ext_info.mapper,
+ aliased=True,
_use_mapper_path=True,
- _existing_alias=existing)
+ _existing_alias=existing,
+ )
ext_info = inspect(ac)
elif not ext_info.with_polymorphic_mappers:
ext_info = orm_util.AliasedInsp(
@@ -253,11 +274,12 @@ class Load(Generative, MapperOption):
ext_info._base_alias,
ext_info._use_mapper_path,
ext_info._adapt_on_names,
- ext_info.represents_outer_join
+ ext_info.represents_outer_join,
)
path.entity_path[prop].set(
- self.context, "path_with_polymorphic", ext_info)
+ self.context, "path_with_polymorphic", ext_info
+ )
# the path here will go into the context dictionary and
# needs to match up to how the class graph is traversed.
@@ -280,7 +302,7 @@ class Load(Generative, MapperOption):
return path
def __str__(self):
- return "Load(strategy=%r)" % (self.strategy, )
+ return "Load(strategy=%r)" % (self.strategy,)
def _coerce_strat(self, strategy):
if strategy is not None:
@@ -289,7 +311,8 @@ class Load(Generative, MapperOption):
@_generative
def set_relationship_strategy(
- self, attr, strategy, propagate_to_loaders=True):
+ self, attr, strategy, propagate_to_loaders=True
+ ):
strategy = self._coerce_strat(strategy)
self.is_class_strategy = False
@@ -365,12 +388,18 @@ class Load(Generative, MapperOption):
if effective_path.is_token:
for path in effective_path.generate_for_superclasses():
self._set_for_path(
- self.context, path, replace=True,
- merge_opts=self.is_opts_only)
+ self.context,
+ path,
+ replace=True,
+ merge_opts=self.is_opts_only,
+ )
else:
self._set_for_path(
- self.context, effective_path, replace=True,
- merge_opts=self.is_opts_only)
+ self.context,
+ effective_path,
+ replace=True,
+ merge_opts=self.is_opts_only,
+ )
def __getstate__(self):
d = self.__dict__.copy()
@@ -389,21 +418,26 @@ class Load(Generative, MapperOption):
# TODO: this is approximated from the _UnboundLoad
# version and probably has issues, not fully covered.
- if i == 0 and c_token.endswith(':' + _DEFAULT_TOKEN):
+ if i == 0 and c_token.endswith(":" + _DEFAULT_TOKEN):
return to_chop
- elif c_token != 'relationship:%s' % (_WILDCARD_TOKEN,) and \
- c_token != p_token.key:
+ elif (
+ c_token != "relationship:%s" % (_WILDCARD_TOKEN,)
+ and c_token != p_token.key
+ ):
return None
if c_token is p_token:
continue
- elif isinstance(c_token, InspectionAttr) and \
- c_token.is_mapper and p_token.is_mapper and \
- c_token.isa(p_token):
+ elif (
+ isinstance(c_token, InspectionAttr)
+ and c_token.is_mapper
+ and p_token.is_mapper
+ and c_token.isa(p_token)
+ ):
continue
else:
return None
- return to_chop[i + 1:]
+ return to_chop[i + 1 :]
class _UnboundLoad(Load):
@@ -431,9 +465,7 @@ class _UnboundLoad(Load):
if local_elem is not val_elem:
break
else:
- opt = val._bind_loader(
- [path.path[0]],
- None, None, False)
+ opt = val._bind_loader([path.path[0]], None, None, False)
if opt:
c_key = opt._generate_cache_key(path)
if c_key is False:
@@ -449,26 +481,29 @@ class _UnboundLoad(Load):
self._to_bind.append(self)
def _generate_path(self, path, attr, wildcard_key):
- if wildcard_key and isinstance(attr, util.string_types) and \
- attr in (_WILDCARD_TOKEN, _DEFAULT_TOKEN):
+ if (
+ wildcard_key
+ and isinstance(attr, util.string_types)
+ and attr in (_WILDCARD_TOKEN, _DEFAULT_TOKEN)
+ ):
if attr == _DEFAULT_TOKEN:
self.propagate_to_loaders = False
attr = "%s:%s" % (wildcard_key, attr)
if path and _is_mapped_class(path[-1]) and not self.is_class_strategy:
path = path[0:-1]
if attr:
- path = path + (attr, )
+ path = path + (attr,)
self.path = path
return path
def __getstate__(self):
d = self.__dict__.copy()
- d['path'] = self._serialize_path(self.path, filter_aliased_class=True)
+ d["path"] = self._serialize_path(self.path, filter_aliased_class=True)
return d
def __setstate__(self, state):
ret = []
- for key in state['path']:
+ for key in state["path"]:
if isinstance(key, tuple):
if len(key) == 2:
# support legacy
@@ -482,17 +517,20 @@ class _UnboundLoad(Load):
ret.append(prop)
else:
ret.append(key)
- state['path'] = tuple(ret)
+ state["path"] = tuple(ret)
self.__dict__ = state
def _process(self, query, raiseerr):
- dedupes = query._attributes['_unbound_load_dedupes']
+ dedupes = query._attributes["_unbound_load_dedupes"]
for val in self._to_bind:
if val not in dedupes:
dedupes.add(val)
val._bind_loader(
[ent.entity_zero for ent in query._mapper_entities],
- query._current_path, query._attributes, raiseerr)
+ query._current_path,
+ query._attributes,
+ raiseerr,
+ )
@classmethod
def _from_keys(cls, meth, keys, chained, kw):
@@ -502,13 +540,14 @@ class _UnboundLoad(Load):
if isinstance(key, util.string_types):
# coerce fooload('*') into "default loader strategy"
if key == _WILDCARD_TOKEN:
- return (_DEFAULT_TOKEN, )
+ return (_DEFAULT_TOKEN,)
# coerce fooload(".*") into "wildcard on default entity"
elif key.startswith("." + _WILDCARD_TOKEN):
key = key[1:]
return key.split(".")
else:
return (key,)
+
all_tokens = [token for key in keys for token in _split_key(key)]
for token in all_tokens[0:-1]:
@@ -526,21 +565,24 @@ class _UnboundLoad(Load):
def _chop_path(self, to_chop, path):
i = -1
for i, (c_token, (p_entity, p_prop)) in enumerate(
- zip(to_chop, path.pairs())):
+ zip(to_chop, path.pairs())
+ ):
if isinstance(c_token, util.string_types):
- if i == 0 and c_token.endswith(':' + _DEFAULT_TOKEN):
+ if i == 0 and c_token.endswith(":" + _DEFAULT_TOKEN):
return to_chop
- elif c_token != 'relationship:%s' % (
- _WILDCARD_TOKEN,) and c_token != p_prop.key:
+ elif (
+ c_token != "relationship:%s" % (_WILDCARD_TOKEN,)
+ and c_token != p_prop.key
+ ):
return None
elif isinstance(c_token, PropComparator):
- if c_token.property is not p_prop or \
- (
- c_token._parententity is not p_entity and (
- not c_token._parententity.is_mapper or
- not c_token._parententity.isa(p_entity)
- )
- ):
+ if c_token.property is not p_prop or (
+ c_token._parententity is not p_entity
+ and (
+ not c_token._parententity.is_mapper
+ or not c_token._parententity.isa(p_entity)
+ )
+ ):
return None
else:
i += 1
@@ -551,15 +593,16 @@ class _UnboundLoad(Load):
ret = []
for token in path:
if isinstance(token, QueryableAttribute):
- if filter_aliased_class and token._of_type and \
- inspect(token._of_type).is_aliased_class:
- ret.append(
- (token._parentmapper.class_,
- token.key, None))
+ if (
+ filter_aliased_class
+ and token._of_type
+ and inspect(token._of_type).is_aliased_class
+ ):
+ ret.append((token._parentmapper.class_, token.key, None))
else:
ret.append(
- (token._parentmapper.class_, token.key,
- token._of_type))
+ (token._parentmapper.class_, token.key, token._of_type)
+ )
elif isinstance(token, PropComparator):
ret.append((token._parentmapper.class_, token.key, None))
else:
@@ -605,7 +648,7 @@ class _UnboundLoad(Load):
start_path = self.path
if self.is_class_strategy and current_path:
- start_path += (entities[0], )
+ start_path += (entities[0],)
# _current_path implies we're in a
# secondary load with an existing path
@@ -621,23 +664,20 @@ class _UnboundLoad(Load):
token = start_path[0]
if isinstance(token, util.string_types):
- entity = self._find_entity_basestring(
- entities, token, raiseerr)
+ entity = self._find_entity_basestring(entities, token, raiseerr)
elif isinstance(token, PropComparator):
prop = token.property
entity = self._find_entity_prop_comparator(
- entities,
- prop.key,
- token._parententity,
- raiseerr)
+ entities, prop.key, token._parententity, raiseerr
+ )
elif self.is_class_strategy and _is_mapped_class(token):
entity = inspect(token)
if entity not in entities:
entity = None
else:
raise sa_exc.ArgumentError(
- "mapper option expects "
- "string key or list of attributes")
+ "mapper option expects " "string key or list of attributes"
+ )
if not entity:
return
@@ -663,7 +703,8 @@ class _UnboundLoad(Load):
if not loader.is_class_strategy:
for token in start_path:
if not loader._generate_path(
- loader.path, token, None, raiseerr):
+ loader.path, token, None, raiseerr
+ ):
return
loader.local_opts.update(self.local_opts)
@@ -680,14 +721,18 @@ class _UnboundLoad(Load):
if effective_path.is_token:
for path in effective_path.generate_for_superclasses():
loader._set_for_path(
- context, path,
+ context,
+ path,
replace=not self._is_chain_link,
- merge_opts=self.is_opts_only)
+ merge_opts=self.is_opts_only,
+ )
else:
loader._set_for_path(
- context, effective_path,
+ context,
+ effective_path,
replace=not self._is_chain_link,
- merge_opts=self.is_opts_only)
+ merge_opts=self.is_opts_only,
+ )
return loader
@@ -704,28 +749,27 @@ class _UnboundLoad(Load):
if not list(entities):
raise sa_exc.ArgumentError(
"Query has only expression-based entities - "
- "can't find property named '%s'."
- % (token, )
+ "can't find property named '%s'." % (token,)
)
else:
raise sa_exc.ArgumentError(
"Can't find property '%s' on any entity "
"specified in this Query. Note the full path "
"from root (%s) to target entity must be specified."
- % (token, ",".join(str(x) for
- x in entities))
+ % (token, ",".join(str(x) for x in entities))
)
else:
return None
def _find_entity_basestring(self, entities, token, raiseerr):
- if token.endswith(':' + _WILDCARD_TOKEN):
+ if token.endswith(":" + _WILDCARD_TOKEN):
if len(list(entities)) != 1:
if raiseerr:
raise sa_exc.ArgumentError(
"Wildcard loader can only be used with exactly "
"one entity. Use Load(ent) to specify "
- "specific entities.")
+ "specific entities."
+ )
elif token.endswith(_DEFAULT_TOKEN):
raiseerr = False
@@ -738,8 +782,7 @@ class _UnboundLoad(Load):
if raiseerr:
raise sa_exc.ArgumentError(
"Query has only expression-based entities - "
- "can't find property named '%s'."
- % (token, )
+ "can't find property named '%s'." % (token,)
)
else:
return None
@@ -766,7 +809,9 @@ class loader_option(object):
See :func:`.orm.%(name)s` for usage examples.
-""" % {"name": self.name}
+""" % {
+ "name": self.name
+ }
fn.__doc__ = fn_doc
return self
@@ -783,7 +828,9 @@ See :func:`.orm.%(name)s` for usage examples.
%(name)s("someattribute").%(name)s("anotherattribute")
)
-""" % {"name": self.name}
+""" % {
+ "name": self.name
+ }
return self
@@ -840,23 +887,22 @@ def contains_eager(loadopt, attr, alias=None):
info = inspect(alias)
alias = info.selectable
- elif getattr(attr, '_of_type', None):
+ elif getattr(attr, "_of_type", None):
ot = inspect(attr._of_type)
alias = ot.selectable
cloned = loadopt.set_relationship_strategy(
- attr,
- {"lazy": "joined"},
- propagate_to_loaders=False
+ attr, {"lazy": "joined"}, propagate_to_loaders=False
)
- cloned.local_opts['eager_from_alias'] = alias
+ cloned.local_opts["eager_from_alias"] = alias
return cloned
@contains_eager._add_unbound_fn
def contains_eager(*keys, **kw):
return _UnboundLoad()._from_keys(
- _UnboundLoad.contains_eager, keys, True, kw)
+ _UnboundLoad.contains_eager, keys, True, kw
+ )
@loader_option()
@@ -894,12 +940,11 @@ def load_only(loadopt, *attrs):
"""
cloned = loadopt.set_column_strategy(
- attrs,
- {"deferred": False, "instrument": True}
+ attrs, {"deferred": False, "instrument": True}
+ )
+ cloned.set_column_strategy(
+ "*", {"deferred": True, "instrument": True}, {"undefer_pks": True}
)
- cloned.set_column_strategy("*",
- {"deferred": True, "instrument": True},
- {"undefer_pks": True})
return cloned
@@ -996,20 +1041,18 @@ def joinedload(loadopt, attr, innerjoin=None):
"""
loader = loadopt.set_relationship_strategy(attr, {"lazy": "joined"})
if innerjoin is not None:
- loader.local_opts['innerjoin'] = innerjoin
+ loader.local_opts["innerjoin"] = innerjoin
return loader
@joinedload._add_unbound_fn
def joinedload(*keys, **kw):
- return _UnboundLoad._from_keys(
- _UnboundLoad.joinedload, keys, False, kw)
+ return _UnboundLoad._from_keys(_UnboundLoad.joinedload, keys, False, kw)
@joinedload._add_unbound_all_fn
def joinedload_all(*keys, **kw):
- return _UnboundLoad._from_keys(
- _UnboundLoad.joinedload, keys, True, kw)
+ return _UnboundLoad._from_keys(_UnboundLoad.joinedload, keys, True, kw)
@loader_option()
@@ -1152,8 +1195,7 @@ def immediateload(loadopt, attr):
@immediateload._add_unbound_fn
def immediateload(*keys):
- return _UnboundLoad._from_keys(
- _UnboundLoad.immediateload, keys, False, {})
+ return _UnboundLoad._from_keys(_UnboundLoad.immediateload, keys, False, {})
@loader_option()
@@ -1213,7 +1255,8 @@ def raiseload(loadopt, attr, sql_only=False):
"""
return loadopt.set_relationship_strategy(
- attr, {"lazy": "raise_on_sql" if sql_only else "raise"})
+ attr, {"lazy": "raise_on_sql" if sql_only else "raise"}
+ )
@raiseload._add_unbound_fn
@@ -1251,10 +1294,7 @@ def defaultload(loadopt, attr):
:ref:`deferred_loading_w_multiple`
"""
- return loadopt.set_relationship_strategy(
- attr,
- None
- )
+ return loadopt.set_relationship_strategy(attr, None)
@defaultload._add_unbound_fn
@@ -1315,15 +1355,15 @@ def defer(loadopt, key):
"""
return loadopt.set_column_strategy(
- (key, ),
- {"deferred": True, "instrument": True}
+ (key,), {"deferred": True, "instrument": True}
)
@defer._add_unbound_fn
def defer(key, *addl_attrs):
return _UnboundLoad._from_keys(
- _UnboundLoad.defer, (key, ) + addl_attrs, False, {})
+ _UnboundLoad.defer, (key,) + addl_attrs, False, {}
+ )
@loader_option()
@@ -1362,15 +1402,15 @@ def undefer(loadopt, key):
"""
return loadopt.set_column_strategy(
- (key, ),
- {"deferred": False, "instrument": True}
+ (key,), {"deferred": False, "instrument": True}
)
@undefer._add_unbound_fn
def undefer(key, *addl_attrs):
return _UnboundLoad._from_keys(
- _UnboundLoad.undefer, (key, ) + addl_attrs, False, {})
+ _UnboundLoad.undefer, (key,) + addl_attrs, False, {}
+ )
@loader_option()
@@ -1405,10 +1445,7 @@ def undefer_group(loadopt, name):
"""
return loadopt.set_column_strategy(
- "*",
- None,
- {"undefer_group_%s" % name: True},
- opts_only=True
+ "*", None, {"undefer_group_%s" % name: True}, opts_only=True
)
@@ -1448,21 +1485,18 @@ def with_expression(loadopt, key, expression):
"""
- expression = sql_expr._labeled(
- _orm_full_deannotate(expression))
+ expression = sql_expr._labeled(_orm_full_deannotate(expression))
return loadopt.set_column_strategy(
- (key, ),
- {"query_expression": True},
- opts={"expression": expression}
+ (key,), {"query_expression": True}, opts={"expression": expression}
)
@with_expression._add_unbound_fn
def with_expression(key, expression):
return _UnboundLoad._from_keys(
- _UnboundLoad.with_expression, (key, ),
- False, {"expression": expression})
+ _UnboundLoad.with_expression, (key,), False, {"expression": expression}
+ )
@loader_option()
@@ -1483,7 +1517,11 @@ def selectin_polymorphic(loadopt, classes):
"""
loadopt.set_class_strategy(
{"selectinload_polymorphic": True},
- opts={"entities": tuple(sorted((inspect(cls) for cls in classes), key=id))}
+ opts={
+ "entities": tuple(
+ sorted((inspect(cls) for cls in classes), key=id)
+ )
+ },
)
return loadopt
@@ -1492,8 +1530,6 @@ def selectin_polymorphic(loadopt, classes):
def selectin_polymorphic(base_cls, classes):
ul = _UnboundLoad()
ul.is_class_strategy = True
- ul.path = (inspect(base_cls), )
- ul.selectin_polymorphic(
- classes
- )
+ ul.path = (inspect(base_cls),)
+ ul.selectin_polymorphic(classes)
return ul
diff --git a/lib/sqlalchemy/orm/sync.py b/lib/sqlalchemy/orm/sync.py
index 08a66a8db..0cd488cbd 100644
--- a/lib/sqlalchemy/orm/sync.py
+++ b/lib/sqlalchemy/orm/sync.py
@@ -13,8 +13,15 @@ between instances based on join conditions.
from . import exc, util as orm_util, attributes
-def populate(source, source_mapper, dest, dest_mapper,
- synchronize_pairs, uowcommit, flag_cascaded_pks):
+def populate(
+ source,
+ source_mapper,
+ dest,
+ dest_mapper,
+ synchronize_pairs,
+ uowcommit,
+ flag_cascaded_pks,
+):
source_dict = source.dict
dest_dict = dest.dict
@@ -22,8 +29,9 @@ def populate(source, source_mapper, dest, dest_mapper,
try:
# inline of source_mapper._get_state_attr_by_column
prop = source_mapper._columntoproperty[l]
- value = source.manager[prop.key].impl.get(source, source_dict,
- attributes.PASSIVE_OFF)
+ value = source.manager[prop.key].impl.get(
+ source, source_dict, attributes.PASSIVE_OFF
+ )
except exc.UnmappedColumnError:
_raise_col_to_prop(False, source_mapper, l, dest_mapper, r)
@@ -39,14 +47,16 @@ def populate(source, source_mapper, dest, dest_mapper,
# how often this logic is invoked for memory/performance
# reasons, since we only need this info for a primary key
# destination.
- if flag_cascaded_pks and l.primary_key and \
- r.primary_key and \
- r.references(l):
+ if (
+ flag_cascaded_pks
+ and l.primary_key
+ and r.primary_key
+ and r.references(l)
+ ):
uowcommit.attributes[("pk_cascaded", dest, r)] = True
-def bulk_populate_inherit_keys(
- source_dict, source_mapper, synchronize_pairs):
+def bulk_populate_inherit_keys(source_dict, source_mapper, synchronize_pairs):
# a simplified version of populate() used by bulk insert mode
for l, r in synchronize_pairs:
try:
@@ -64,14 +74,15 @@ def bulk_populate_inherit_keys(
def clear(dest, dest_mapper, synchronize_pairs):
for l, r in synchronize_pairs:
- if r.primary_key and \
- dest_mapper._get_state_attr_by_column(
- dest, dest.dict, r) not in orm_util._none_set:
+ if (
+ r.primary_key
+ and dest_mapper._get_state_attr_by_column(dest, dest.dict, r)
+ not in orm_util._none_set
+ ):
raise AssertionError(
"Dependency rule tried to blank-out primary key "
- "column '%s' on instance '%s'" %
- (r, orm_util.state_str(dest))
+ "column '%s' on instance '%s'" % (r, orm_util.state_str(dest))
)
try:
dest_mapper._set_state_attr_by_column(dest, dest.dict, r, None)
@@ -83,9 +94,11 @@ def update(source, source_mapper, dest, old_prefix, synchronize_pairs):
for l, r in synchronize_pairs:
try:
oldvalue = source_mapper._get_committed_attr_by_column(
- source.obj(), l)
+ source.obj(), l
+ )
value = source_mapper._get_state_attr_by_column(
- source, source.dict, l, passive=attributes.PASSIVE_OFF)
+ source, source.dict, l, passive=attributes.PASSIVE_OFF
+ )
except exc.UnmappedColumnError:
_raise_col_to_prop(False, source_mapper, l, None, r)
dest[r.key] = value
@@ -96,7 +109,8 @@ def populate_dict(source, source_mapper, dict_, synchronize_pairs):
for l, r in synchronize_pairs:
try:
value = source_mapper._get_state_attr_by_column(
- source, source.dict, l, passive=attributes.PASSIVE_OFF)
+ source, source.dict, l, passive=attributes.PASSIVE_OFF
+ )
except exc.UnmappedColumnError:
_raise_col_to_prop(False, source_mapper, l, None, r)
@@ -114,27 +128,31 @@ def source_modified(uowcommit, source, source_mapper, synchronize_pairs):
except exc.UnmappedColumnError:
_raise_col_to_prop(False, source_mapper, l, None, r)
history = uowcommit.get_attribute_history(
- source, prop.key, attributes.PASSIVE_NO_INITIALIZE)
+ source, prop.key, attributes.PASSIVE_NO_INITIALIZE
+ )
if bool(history.deleted):
return True
else:
return False
-def _raise_col_to_prop(isdest, source_mapper, source_column,
- dest_mapper, dest_column):
+def _raise_col_to_prop(
+ isdest, source_mapper, source_column, dest_mapper, dest_column
+):
if isdest:
raise exc.UnmappedColumnError(
"Can't execute sync rule for "
"destination column '%s'; mapper '%s' does not map "
"this column. Try using an explicit `foreign_keys` "
"collection which does not include this column (or use "
- "a viewonly=True relation)." % (dest_column, dest_mapper))
+ "a viewonly=True relation)." % (dest_column, dest_mapper)
+ )
else:
raise exc.UnmappedColumnError(
"Can't execute sync rule for "
"source column '%s'; mapper '%s' does not map this "
"column. Try using an explicit `foreign_keys` "
"collection which does not include destination column "
- "'%s' (or use a viewonly=True relation)." %
- (source_column, source_mapper, dest_column))
+ "'%s' (or use a viewonly=True relation)."
+ % (source_column, source_mapper, dest_column)
+ )
diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py
index a83a99d78..545811bb4 100644
--- a/lib/sqlalchemy/orm/unitofwork.py
+++ b/lib/sqlalchemy/orm/unitofwork.py
@@ -41,9 +41,11 @@ def track_cascade_events(descriptor, prop):
prop = state.manager.mapper._props[key]
item_state = attributes.instance_state(item)
- if prop._cascade.save_update and \
- (prop.cascade_backrefs or key == initiator.key) and \
- not sess._contains_state(item_state):
+ if (
+ prop._cascade.save_update
+ and (prop.cascade_backrefs or key == initiator.key)
+ and not sess._contains_state(item_state)
+ ):
sess._save_or_update_state(item_state)
return item
@@ -59,12 +61,15 @@ def track_cascade_events(descriptor, prop):
sess._flush_warning(
"collection remove"
if prop.uselist
- else "related attribute delete")
+ else "related attribute delete"
+ )
- if item is not None and \
- item is not attributes.NEVER_SET and \
- item is not attributes.PASSIVE_NO_RESULT and \
- prop._cascade.delete_orphan:
+ if (
+ item is not None
+ and item is not attributes.NEVER_SET
+ and item is not attributes.PASSIVE_NO_RESULT
+ and prop._cascade.delete_orphan
+ ):
# expunge pending orphans
item_state = attributes.instance_state(item)
@@ -93,26 +98,31 @@ def track_cascade_events(descriptor, prop):
prop = state.manager.mapper._props[key]
if newvalue is not None:
newvalue_state = attributes.instance_state(newvalue)
- if prop._cascade.save_update and \
- (prop.cascade_backrefs or key == initiator.key) and \
- not sess._contains_state(newvalue_state):
+ if (
+ prop._cascade.save_update
+ and (prop.cascade_backrefs or key == initiator.key)
+ and not sess._contains_state(newvalue_state)
+ ):
sess._save_or_update_state(newvalue_state)
- if oldvalue is not None and \
- oldvalue is not attributes.NEVER_SET and \
- oldvalue is not attributes.PASSIVE_NO_RESULT and \
- prop._cascade.delete_orphan:
+ if (
+ oldvalue is not None
+ and oldvalue is not attributes.NEVER_SET
+ and oldvalue is not attributes.PASSIVE_NO_RESULT
+ and prop._cascade.delete_orphan
+ ):
# possible to reach here with attributes.NEVER_SET ?
oldvalue_state = attributes.instance_state(oldvalue)
- if oldvalue_state in sess._new and \
- prop.mapper._is_orphan(oldvalue_state):
+ if oldvalue_state in sess._new and prop.mapper._is_orphan(
+ oldvalue_state
+ ):
sess.expunge(oldvalue)
return newvalue
- event.listen(descriptor, 'append', append, raw=True, retval=True)
- event.listen(descriptor, 'remove', remove, raw=True, retval=True)
- event.listen(descriptor, 'set', set_, raw=True, retval=True)
+ event.listen(descriptor, "append", append, raw=True, retval=True)
+ event.listen(descriptor, "remove", remove, raw=True, retval=True)
+ event.listen(descriptor, "set", set_, raw=True, retval=True)
class UOWTransaction(object):
@@ -197,8 +207,9 @@ class UOWTransaction(object):
self.states[state] = (isdelete, True)
- def get_attribute_history(self, state, key,
- passive=attributes.PASSIVE_NO_INITIALIZE):
+ def get_attribute_history(
+ self, state, key, passive=attributes.PASSIVE_NO_INITIALIZE
+ ):
"""facade to attributes.get_state_history(), including
caching of results."""
@@ -213,12 +224,16 @@ class UOWTransaction(object):
# if the cached lookup was "passive" and now
# we want non-passive, do a non-passive lookup and re-cache
- if not cached_passive & attributes.SQL_OK \
- and passive & attributes.SQL_OK:
+ if (
+ not cached_passive & attributes.SQL_OK
+ and passive & attributes.SQL_OK
+ ):
impl = state.manager[key].impl
- history = impl.get_history(state, state.dict,
- attributes.PASSIVE_OFF |
- attributes.LOAD_AGAINST_COMMITTED)
+ history = impl.get_history(
+ state,
+ state.dict,
+ attributes.PASSIVE_OFF | attributes.LOAD_AGAINST_COMMITTED,
+ )
if history and impl.uses_objects:
state_history = history.as_state()
else:
@@ -228,14 +243,14 @@ class UOWTransaction(object):
impl = state.manager[key].impl
# TODO: store the history as (state, object) tuples
# so we don't have to keep converting here
- history = impl.get_history(state, state.dict, passive |
- attributes.LOAD_AGAINST_COMMITTED)
+ history = impl.get_history(
+ state, state.dict, passive | attributes.LOAD_AGAINST_COMMITTED
+ )
if history and impl.uses_objects:
state_history = history.as_state()
else:
state_history = history
- self.attributes[hashkey] = (history, state_history,
- passive)
+ self.attributes[hashkey] = (history, state_history, passive)
return state_history
@@ -247,17 +262,25 @@ class UOWTransaction(object):
if key not in self.presort_actions:
self.presort_actions[key] = Preprocess(processor, fromparent)
- def register_object(self, state, isdelete=False,
- listonly=False, cancel_delete=False,
- operation=None, prop=None):
+ def register_object(
+ self,
+ state,
+ isdelete=False,
+ listonly=False,
+ cancel_delete=False,
+ operation=None,
+ prop=None,
+ ):
if not self.session._contains_state(state):
# this condition is normal when objects are registered
# as part of a relationship cascade operation. it should
# not occur for the top-level register from Session.flush().
if not state.deleted and operation is not None:
- util.warn("Object of type %s not in session, %s operation "
- "along '%s' will not proceed" %
- (orm_util.state_class_str(state), operation, prop))
+ util.warn(
+ "Object of type %s not in session, %s operation "
+ "along '%s' will not proceed"
+ % (orm_util.state_class_str(state), operation, prop)
+ )
return False
if state not in self.states:
@@ -340,24 +363,26 @@ class UOWTransaction(object):
# see if the graph of mapper dependencies has cycles.
self.cycles = cycles = topological.find_cycles(
- self.dependencies,
- list(self.postsort_actions.values()))
+ self.dependencies, list(self.postsort_actions.values())
+ )
if cycles:
# if yes, break the per-mapper actions into
# per-state actions
convert = dict(
- (rec, set(rec.per_state_flush_actions(self)))
- for rec in cycles
+ (rec, set(rec.per_state_flush_actions(self))) for rec in cycles
)
# rewrite the existing dependencies to point to
# the per-state actions for those per-mapper actions
# that were broken up.
for edge in list(self.dependencies):
- if None in edge or \
- edge[0].disabled or edge[1].disabled or \
- cycles.issuperset(edge):
+ if (
+ None in edge
+ or edge[0].disabled
+ or edge[1].disabled
+ or cycles.issuperset(edge)
+ ):
self.dependencies.remove(edge)
elif edge[0] in cycles:
self.dependencies.remove(edge)
@@ -368,10 +393,9 @@ class UOWTransaction(object):
for dep in convert[edge[1]]:
self.dependencies.add((edge[0], dep))
- return set([a for a in self.postsort_actions.values()
- if not a.disabled
- ]
- ).difference(cycles)
+ return set(
+ [a for a in self.postsort_actions.values() if not a.disabled]
+ ).difference(cycles)
def execute(self):
postsort_actions = self._generate_actions()
@@ -386,15 +410,13 @@ class UOWTransaction(object):
# execute
if self.cycles:
for set_ in topological.sort_as_subsets(
- self.dependencies,
- postsort_actions):
+ self.dependencies, postsort_actions
+ ):
while set_:
n = set_.pop()
n.execute_aggregate(self, set_)
else:
- for rec in topological.sort(
- self.dependencies,
- postsort_actions):
+ for rec in topological.sort(self.dependencies, postsort_actions):
rec.execute(self)
def finalize_flush_changes(self):
@@ -410,8 +432,7 @@ class UOWTransaction(object):
states = set(self.states)
isdel = set(
- s for (s, (isdelete, listonly)) in self.states.items()
- if isdelete
+ s for (s, (isdelete, listonly)) in self.states.items() if isdelete
)
other = states.difference(isdel)
if isdel:
@@ -424,8 +445,8 @@ class IterateMappersMixin(object):
def _mappers(self, uow):
if self.fromparent:
return iter(
- m for m in
- self.dependency_processor.parent.self_and_descendants
+ m
+ for m in self.dependency_processor.parent.self_and_descendants
if uow._mapper_for_dep[(m, self.dependency_processor)]
)
else:
@@ -434,8 +455,10 @@ class IterateMappersMixin(object):
class Preprocess(IterateMappersMixin):
__slots__ = (
- 'dependency_processor', 'fromparent', 'processed',
- 'setup_flush_actions'
+ "dependency_processor",
+ "fromparent",
+ "processed",
+ "setup_flush_actions",
)
def __init__(self, dependency_processor, fromparent):
@@ -464,12 +487,14 @@ class Preprocess(IterateMappersMixin):
self.dependency_processor.presort_saves(uow, save_states)
self.processed.update(save_states)
- if (delete_states or save_states):
+ if delete_states or save_states:
if not self.setup_flush_actions and (
- self.dependency_processor.
- prop_has_changes(uow, delete_states, True) or
- self.dependency_processor.
- prop_has_changes(uow, save_states, False)
+ self.dependency_processor.prop_has_changes(
+ uow, delete_states, True
+ )
+ or self.dependency_processor.prop_has_changes(
+ uow, save_states, False
+ )
):
self.dependency_processor.per_property_flush_actions(uow)
self.setup_flush_actions = True
@@ -479,16 +504,14 @@ class Preprocess(IterateMappersMixin):
class PostSortRec(object):
- __slots__ = 'disabled',
+ __slots__ = ("disabled",)
def __new__(cls, uow, *args):
- key = (cls, ) + args
+ key = (cls,) + args
if key in uow.postsort_actions:
return uow.postsort_actions[key]
else:
- uow.postsort_actions[key] = \
- ret = \
- object.__new__(cls)
+ uow.postsort_actions[key] = ret = object.__new__(cls)
ret.disabled = False
return ret
@@ -497,14 +520,15 @@ class PostSortRec(object):
class ProcessAll(IterateMappersMixin, PostSortRec):
- __slots__ = 'dependency_processor', 'isdelete', 'fromparent'
+ __slots__ = "dependency_processor", "isdelete", "fromparent"
def __init__(self, uow, dependency_processor, isdelete, fromparent):
self.dependency_processor = dependency_processor
self.isdelete = isdelete
self.fromparent = fromparent
- uow.deps[dependency_processor.parent.base_mapper].\
- add(dependency_processor)
+ uow.deps[dependency_processor.parent.base_mapper].add(
+ dependency_processor
+ )
def execute(self, uow):
states = self._elements(uow)
@@ -524,7 +548,7 @@ class ProcessAll(IterateMappersMixin, PostSortRec):
return "%s(%s, isdelete=%s)" % (
self.__class__.__name__,
self.dependency_processor,
- self.isdelete
+ self.isdelete,
)
def _elements(self, uow):
@@ -536,7 +560,7 @@ class ProcessAll(IterateMappersMixin, PostSortRec):
class PostUpdateAll(PostSortRec):
- __slots__ = 'mapper', 'isdelete'
+ __slots__ = "mapper", "isdelete"
def __init__(self, uow, mapper, isdelete):
self.mapper = mapper
@@ -550,22 +574,23 @@ class PostUpdateAll(PostSortRec):
class SaveUpdateAll(PostSortRec):
- __slots__ = 'mapper',
+ __slots__ = ("mapper",)
def __init__(self, uow, mapper):
self.mapper = mapper
assert mapper is mapper.base_mapper
def execute(self, uow):
- persistence.save_obj(self.mapper,
- uow.states_for_mapper_hierarchy(
- self.mapper, False, False),
- uow
- )
+ persistence.save_obj(
+ self.mapper,
+ uow.states_for_mapper_hierarchy(self.mapper, False, False),
+ uow,
+ )
def per_state_flush_actions(self, uow):
- states = list(uow.states_for_mapper_hierarchy(
- self.mapper, False, False))
+ states = list(
+ uow.states_for_mapper_hierarchy(self.mapper, False, False)
+ )
base_mapper = self.mapper.base_mapper
delete_all = DeleteAll(uow, base_mapper)
for state in states:
@@ -580,29 +605,27 @@ class SaveUpdateAll(PostSortRec):
dep.per_state_flush_actions(uow, states_for_prop, False)
def __repr__(self):
- return "%s(%s)" % (
- self.__class__.__name__,
- self.mapper
- )
+ return "%s(%s)" % (self.__class__.__name__, self.mapper)
class DeleteAll(PostSortRec):
- __slots__ = 'mapper',
+ __slots__ = ("mapper",)
def __init__(self, uow, mapper):
self.mapper = mapper
assert mapper is mapper.base_mapper
def execute(self, uow):
- persistence.delete_obj(self.mapper,
- uow.states_for_mapper_hierarchy(
- self.mapper, True, False),
- uow
- )
+ persistence.delete_obj(
+ self.mapper,
+ uow.states_for_mapper_hierarchy(self.mapper, True, False),
+ uow,
+ )
def per_state_flush_actions(self, uow):
- states = list(uow.states_for_mapper_hierarchy(
- self.mapper, True, False))
+ states = list(
+ uow.states_for_mapper_hierarchy(self.mapper, True, False)
+ )
base_mapper = self.mapper.base_mapper
save_all = SaveUpdateAll(uow, base_mapper)
for state in states:
@@ -617,14 +640,11 @@ class DeleteAll(PostSortRec):
dep.per_state_flush_actions(uow, states_for_prop, True)
def __repr__(self):
- return "%s(%s)" % (
- self.__class__.__name__,
- self.mapper
- )
+ return "%s(%s)" % (self.__class__.__name__, self.mapper)
class ProcessState(PostSortRec):
- __slots__ = 'dependency_processor', 'isdelete', 'state'
+ __slots__ = "dependency_processor", "isdelete", "state"
def __init__(self, uow, dependency_processor, isdelete, state):
self.dependency_processor = dependency_processor
@@ -635,10 +655,13 @@ class ProcessState(PostSortRec):
cls_ = self.__class__
dependency_processor = self.dependency_processor
isdelete = self.isdelete
- our_recs = [r for r in recs
- if r.__class__ is cls_ and
- r.dependency_processor is dependency_processor and
- r.isdelete is isdelete]
+ our_recs = [
+ r
+ for r in recs
+ if r.__class__ is cls_
+ and r.dependency_processor is dependency_processor
+ and r.isdelete is isdelete
+ ]
recs.difference_update(our_recs)
states = [self.state] + [r.state for r in our_recs]
if isdelete:
@@ -651,12 +674,12 @@ class ProcessState(PostSortRec):
self.__class__.__name__,
self.dependency_processor,
orm_util.state_str(self.state),
- self.isdelete
+ self.isdelete,
)
class SaveUpdateState(PostSortRec):
- __slots__ = 'state', 'mapper'
+ __slots__ = "state", "mapper"
def __init__(self, uow, state):
self.state = state
@@ -665,24 +688,23 @@ class SaveUpdateState(PostSortRec):
def execute_aggregate(self, uow, recs):
cls_ = self.__class__
mapper = self.mapper
- our_recs = [r for r in recs
- if r.__class__ is cls_ and
- r.mapper is mapper]
+ our_recs = [
+ r for r in recs if r.__class__ is cls_ and r.mapper is mapper
+ ]
recs.difference_update(our_recs)
- persistence.save_obj(mapper,
- [self.state] +
- [r.state for r in our_recs],
- uow)
+ persistence.save_obj(
+ mapper, [self.state] + [r.state for r in our_recs], uow
+ )
def __repr__(self):
return "%s(%s)" % (
self.__class__.__name__,
- orm_util.state_str(self.state)
+ orm_util.state_str(self.state),
)
class DeleteState(PostSortRec):
- __slots__ = 'state', 'mapper'
+ __slots__ = "state", "mapper"
def __init__(self, uow, state):
self.state = state
@@ -691,17 +713,17 @@ class DeleteState(PostSortRec):
def execute_aggregate(self, uow, recs):
cls_ = self.__class__
mapper = self.mapper
- our_recs = [r for r in recs
- if r.__class__ is cls_ and
- r.mapper is mapper]
+ our_recs = [
+ r for r in recs if r.__class__ is cls_ and r.mapper is mapper
+ ]
recs.difference_update(our_recs)
states = [self.state] + [r.state for r in our_recs]
- persistence.delete_obj(mapper,
- [s for s in states if uow.states[s][0]],
- uow)
+ persistence.delete_obj(
+ mapper, [s for s in states if uow.states[s][0]], uow
+ )
def __repr__(self):
return "%s(%s)" % (
self.__class__.__name__,
- orm_util.state_str(self.state)
+ orm_util.state_str(self.state),
)
diff --git a/lib/sqlalchemy/orm/util.py b/lib/sqlalchemy/orm/util.py
index 43709a58c..a1b0cd5da 100644
--- a/lib/sqlalchemy/orm/util.py
+++ b/lib/sqlalchemy/orm/util.py
@@ -12,27 +12,51 @@ from .interfaces import PropComparator, MapperProperty
from . import attributes
import re
-from .base import instance_str, state_str, state_class_str, attribute_str, \
- state_attribute_str, object_mapper, object_state, _none_set, _never_set
+from .base import (
+ instance_str,
+ state_str,
+ state_class_str,
+ attribute_str,
+ state_attribute_str,
+ object_mapper,
+ object_state,
+ _none_set,
+ _never_set,
+)
from .base import class_mapper, _class_to_mapper
from .base import InspectionAttr
from .path_registry import PathRegistry
-all_cascades = frozenset(("delete", "delete-orphan", "all", "merge",
- "expunge", "save-update", "refresh-expire",
- "none"))
+all_cascades = frozenset(
+ (
+ "delete",
+ "delete-orphan",
+ "all",
+ "merge",
+ "expunge",
+ "save-update",
+ "refresh-expire",
+ "none",
+ )
+)
class CascadeOptions(frozenset):
"""Keeps track of the options sent to relationship().cascade"""
- _add_w_all_cascades = all_cascades.difference([
- 'all', 'none', 'delete-orphan'])
+ _add_w_all_cascades = all_cascades.difference(
+ ["all", "none", "delete-orphan"]
+ )
_allowed_cascades = all_cascades
__slots__ = (
- 'save_update', 'delete', 'refresh_expire', 'merge',
- 'expunge', 'delete_orphan')
+ "save_update",
+ "delete",
+ "refresh_expire",
+ "merge",
+ "expunge",
+ "delete_orphan",
+ )
def __new__(cls, value_list):
if isinstance(value_list, util.string_types) or value_list is None:
@@ -40,60 +64,62 @@ class CascadeOptions(frozenset):
values = set(value_list)
if values.difference(cls._allowed_cascades):
raise sa_exc.ArgumentError(
- "Invalid cascade option(s): %s" %
- ", ".join([repr(x) for x in
- sorted(values.difference(cls._allowed_cascades))]))
+ "Invalid cascade option(s): %s"
+ % ", ".join(
+ [
+ repr(x)
+ for x in sorted(
+ values.difference(cls._allowed_cascades)
+ )
+ ]
+ )
+ )
if "all" in values:
values.update(cls._add_w_all_cascades)
if "none" in values:
values.clear()
- values.discard('all')
+ values.discard("all")
self = frozenset.__new__(CascadeOptions, values)
- self.save_update = 'save-update' in values
- self.delete = 'delete' in values
- self.refresh_expire = 'refresh-expire' in values
- self.merge = 'merge' in values
- self.expunge = 'expunge' in values
+ self.save_update = "save-update" in values
+ self.delete = "delete" in values
+ self.refresh_expire = "refresh-expire" in values
+ self.merge = "merge" in values
+ self.expunge = "expunge" in values
self.delete_orphan = "delete-orphan" in values
if self.delete_orphan and not self.delete:
- util.warn("The 'delete-orphan' cascade "
- "option requires 'delete'.")
+ util.warn(
+ "The 'delete-orphan' cascade " "option requires 'delete'."
+ )
return self
def __repr__(self):
- return "CascadeOptions(%r)" % (
- ",".join([x for x in sorted(self)])
- )
+ return "CascadeOptions(%r)" % (",".join([x for x in sorted(self)]))
@classmethod
def from_string(cls, arg):
- values = [
- c for c
- in re.split(r'\s*,\s*', arg or "")
- if c
- ]
+ values = [c for c in re.split(r"\s*,\s*", arg or "") if c]
return cls(values)
-def _validator_events(
- desc, key, validator, include_removes, include_backrefs):
+def _validator_events(desc, key, validator, include_removes, include_backrefs):
"""Runs a validation method on an attribute value to be set or
appended.
"""
if not include_backrefs:
+
def detect_is_backref(state, initiator):
impl = state.manager[key].impl
return initiator.impl is not impl
if include_removes:
+
def append(state, value, initiator):
- if (
- initiator.op is not attributes.OP_BULK_REPLACE and
- (include_backrefs or not detect_is_backref(state, initiator))
+ if initiator.op is not attributes.OP_BULK_REPLACE and (
+ include_backrefs or not detect_is_backref(state, initiator)
):
return validator(state.obj(), key, value, False)
else:
@@ -103,7 +129,8 @@ def _validator_events(
if include_backrefs or not detect_is_backref(state, initiator):
obj = state.obj()
values[:] = [
- validator(obj, key, value, False) for value in values]
+ validator(obj, key, value, False) for value in values
+ ]
def set_(state, value, oldvalue, initiator):
if include_backrefs or not detect_is_backref(state, initiator):
@@ -116,10 +143,10 @@ def _validator_events(
validator(state.obj(), key, value, True)
else:
+
def append(state, value, initiator):
- if (
- initiator.op is not attributes.OP_BULK_REPLACE and
- (include_backrefs or not detect_is_backref(state, initiator))
+ if initiator.op is not attributes.OP_BULK_REPLACE and (
+ include_backrefs or not detect_is_backref(state, initiator)
):
return validator(state.obj(), key, value)
else:
@@ -128,8 +155,7 @@ def _validator_events(
def bulk_set(state, values, initiator):
if include_backrefs or not detect_is_backref(state, initiator):
obj = state.obj()
- values[:] = [
- validator(obj, key, value) for value in values]
+ values[:] = [validator(obj, key, value) for value in values]
def set_(state, value, oldvalue, initiator):
if include_backrefs or not detect_is_backref(state, initiator):
@@ -137,15 +163,16 @@ def _validator_events(
else:
return value
- event.listen(desc, 'append', append, raw=True, retval=True)
- event.listen(desc, 'bulk_replace', bulk_set, raw=True)
- event.listen(desc, 'set', set_, raw=True, retval=True)
+ event.listen(desc, "append", append, raw=True, retval=True)
+ event.listen(desc, "bulk_replace", bulk_set, raw=True)
+ event.listen(desc, "set", set_, raw=True, retval=True)
if include_removes:
event.listen(desc, "remove", remove, raw=True, retval=True)
-def polymorphic_union(table_map, typecolname,
- aliasname='p_union', cast_nulls=True):
+def polymorphic_union(
+ table_map, typecolname, aliasname="p_union", cast_nulls=True
+):
"""Create a ``UNION`` statement used by a polymorphic mapper.
See :ref:`concrete_inheritance` for an example of how
@@ -197,14 +224,22 @@ def polymorphic_union(table_map, typecolname,
for type, table in table_map.items():
if typecolname is not None:
result.append(
- sql.select([col(name, table) for name in colnames] +
- [sql.literal_column(
- sql_util._quote_ddl_expr(type)).
- label(typecolname)],
- from_obj=[table]))
+ sql.select(
+ [col(name, table) for name in colnames]
+ + [
+ sql.literal_column(
+ sql_util._quote_ddl_expr(type)
+ ).label(typecolname)
+ ],
+ from_obj=[table],
+ )
+ )
else:
- result.append(sql.select([col(name, table) for name in colnames],
- from_obj=[table]))
+ result.append(
+ sql.select(
+ [col(name, table) for name in colnames], from_obj=[table]
+ )
+ )
return sql.union_all(*result).alias(aliasname)
@@ -284,25 +319,29 @@ first()
class_, ident = args
else:
raise sa_exc.ArgumentError(
- "expected up to three positional arguments, "
- "got %s" % largs)
+ "expected up to three positional arguments, " "got %s" % largs
+ )
identity_token = kwargs.pop("identity_token", None)
if kwargs:
- raise sa_exc.ArgumentError("unknown keyword arguments: %s"
- % ", ".join(kwargs))
+ raise sa_exc.ArgumentError(
+ "unknown keyword arguments: %s" % ", ".join(kwargs)
+ )
mapper = class_mapper(class_)
if row is None:
return mapper.identity_key_from_primary_key(
- util.to_list(ident), identity_token=identity_token)
+ util.to_list(ident), identity_token=identity_token
+ )
else:
return mapper.identity_key_from_row(
- row, identity_token=identity_token)
+ row, identity_token=identity_token
+ )
else:
instance = kwargs.pop("instance")
if kwargs:
- raise sa_exc.ArgumentError("unknown keyword arguments: %s"
- % ", ".join(kwargs.keys))
+ raise sa_exc.ArgumentError(
+ "unknown keyword arguments: %s" % ", ".join(kwargs.keys)
+ )
mapper = object_mapper(instance)
return mapper.identity_key_from_instance(instance)
@@ -313,9 +352,15 @@ class ORMAdapter(sql_util.ColumnAdapter):
"""
- def __init__(self, entity, equivalents=None, adapt_required=False,
- chain_to=None, allow_label_resolve=True,
- anonymize_labels=False):
+ def __init__(
+ self,
+ entity,
+ equivalents=None,
+ adapt_required=False,
+ chain_to=None,
+ allow_label_resolve=True,
+ anonymize_labels=False,
+ ):
info = inspection.inspect(entity)
self.mapper = info.mapper
@@ -327,15 +372,18 @@ class ORMAdapter(sql_util.ColumnAdapter):
self.aliased_class = None
sql_util.ColumnAdapter.__init__(
- self, selectable, equivalents, chain_to,
+ self,
+ selectable,
+ equivalents,
+ chain_to,
adapt_required=adapt_required,
allow_label_resolve=allow_label_resolve,
anonymize_labels=anonymize_labels,
- include_fn=self._include_fn
+ include_fn=self._include_fn,
)
def _include_fn(self, elem):
- entity = elem._annotations.get('parentmapper', None)
+ entity = elem._annotations.get("parentmapper", None)
return not entity or entity.isa(self.mapper)
@@ -380,20 +428,25 @@ class AliasedClass(object):
"""
- def __init__(self, cls, alias=None,
- name=None,
- flat=False,
- adapt_on_names=False,
- # TODO: None for default here?
- with_polymorphic_mappers=(),
- with_polymorphic_discriminator=None,
- base_alias=None,
- use_mapper_path=False,
- represents_outer_join=False):
+ def __init__(
+ self,
+ cls,
+ alias=None,
+ name=None,
+ flat=False,
+ adapt_on_names=False,
+ # TODO: None for default here?
+ with_polymorphic_mappers=(),
+ with_polymorphic_discriminator=None,
+ base_alias=None,
+ use_mapper_path=False,
+ represents_outer_join=False,
+ ):
mapper = _class_to_mapper(cls)
if alias is None:
alias = mapper._with_polymorphic_selectable.alias(
- name=name, flat=flat)
+ name=name, flat=flat
+ )
self._aliased_insp = AliasedInsp(
self,
@@ -409,14 +462,14 @@ class AliasedClass(object):
base_alias,
use_mapper_path,
adapt_on_names,
- represents_outer_join
+ represents_outer_join,
)
- self.__name__ = 'AliasedClass_%s' % mapper.class_.__name__
+ self.__name__ = "AliasedClass_%s" % mapper.class_.__name__
def __getattr__(self, key):
try:
- _aliased_insp = self.__dict__['_aliased_insp']
+ _aliased_insp = self.__dict__["_aliased_insp"]
except KeyError:
raise AttributeError()
else:
@@ -434,13 +487,13 @@ class AliasedClass(object):
ret = attr.adapt_to_entity(_aliased_insp)
setattr(self, key, ret)
return ret
- elif hasattr(attr, 'func_code'):
+ elif hasattr(attr, "func_code"):
is_method = getattr(_aliased_insp._target, key, None)
if is_method and is_method.__self__ is not None:
return util.types.MethodType(attr.__func__, self, self)
else:
return None
- elif hasattr(attr, '__get__'):
+ elif hasattr(attr, "__get__"):
ret = attr.__get__(None, self)
if isinstance(ret, PropComparator):
return ret.adapt_to_entity(_aliased_insp)
@@ -450,8 +503,10 @@ class AliasedClass(object):
return attr
def __repr__(self):
- return '<AliasedClass at 0x%x; %s>' % (
- id(self), self._aliased_insp._target.__name__)
+ return "<AliasedClass at 0x%x; %s>" % (
+ id(self),
+ self._aliased_insp._target.__name__,
+ )
class AliasedInsp(InspectionAttr):
@@ -490,10 +545,19 @@ class AliasedInsp(InspectionAttr):
"""
- def __init__(self, entity, mapper, selectable, name,
- with_polymorphic_mappers, polymorphic_on,
- _base_alias, _use_mapper_path, adapt_on_names,
- represents_outer_join):
+ def __init__(
+ self,
+ entity,
+ mapper,
+ selectable,
+ name,
+ with_polymorphic_mappers,
+ polymorphic_on,
+ _base_alias,
+ _use_mapper_path,
+ adapt_on_names,
+ represents_outer_join,
+ ):
self.entity = entity
self.mapper = mapper
self.selectable = selectable
@@ -505,18 +569,28 @@ class AliasedInsp(InspectionAttr):
self.represents_outer_join = represents_outer_join
self._adapter = sql_util.ColumnAdapter(
- selectable, equivalents=mapper._equivalent_columns,
- adapt_on_names=adapt_on_names, anonymize_labels=True)
+ selectable,
+ equivalents=mapper._equivalent_columns,
+ adapt_on_names=adapt_on_names,
+ anonymize_labels=True,
+ )
self._adapt_on_names = adapt_on_names
self._target = mapper.class_
for poly in self.with_polymorphic_mappers:
if poly is not mapper:
- setattr(self.entity, poly.class_.__name__,
- AliasedClass(poly.class_, selectable, base_alias=self,
- adapt_on_names=adapt_on_names,
- use_mapper_path=_use_mapper_path))
+ setattr(
+ self.entity,
+ poly.class_.__name__,
+ AliasedClass(
+ poly.class_,
+ selectable,
+ base_alias=self,
+ adapt_on_names=adapt_on_names,
+ use_mapper_path=_use_mapper_path,
+ ),
+ )
is_aliased_class = True
"always returns True"
@@ -536,39 +610,35 @@ class AliasedInsp(InspectionAttr):
def __getstate__(self):
return {
- 'entity': self.entity,
- 'mapper': self.mapper,
- 'alias': self.selectable,
- 'name': self.name,
- 'adapt_on_names': self._adapt_on_names,
- 'with_polymorphic_mappers':
- self.with_polymorphic_mappers,
- 'with_polymorphic_discriminator':
- self.polymorphic_on,
- 'base_alias': self._base_alias,
- 'use_mapper_path': self._use_mapper_path,
- 'represents_outer_join': self.represents_outer_join
+ "entity": self.entity,
+ "mapper": self.mapper,
+ "alias": self.selectable,
+ "name": self.name,
+ "adapt_on_names": self._adapt_on_names,
+ "with_polymorphic_mappers": self.with_polymorphic_mappers,
+ "with_polymorphic_discriminator": self.polymorphic_on,
+ "base_alias": self._base_alias,
+ "use_mapper_path": self._use_mapper_path,
+ "represents_outer_join": self.represents_outer_join,
}
def __setstate__(self, state):
self.__init__(
- state['entity'],
- state['mapper'],
- state['alias'],
- state['name'],
- state['with_polymorphic_mappers'],
- state['with_polymorphic_discriminator'],
- state['base_alias'],
- state['use_mapper_path'],
- state['adapt_on_names'],
- state['represents_outer_join']
+ state["entity"],
+ state["mapper"],
+ state["alias"],
+ state["name"],
+ state["with_polymorphic_mappers"],
+ state["with_polymorphic_discriminator"],
+ state["base_alias"],
+ state["use_mapper_path"],
+ state["adapt_on_names"],
+ state["represents_outer_join"],
)
def _adapt_element(self, elem):
- return self._adapter.traverse(elem).\
- _annotate({
- 'parententity': self,
- 'parentmapper': self.mapper}
+ return self._adapter.traverse(elem)._annotate(
+ {"parententity": self, "parentmapper": self.mapper}
)
def _entity_for_mapper(self, mapper):
@@ -578,12 +648,12 @@ class AliasedInsp(InspectionAttr):
return self
else:
return getattr(
- self.entity, mapper.class_.__name__)._aliased_insp
+ self.entity, mapper.class_.__name__
+ )._aliased_insp
elif mapper.isa(self.mapper):
return self
else:
- assert False, "mapper %s doesn't correspond to %s" % (
- mapper, self)
+ assert False, "mapper %s doesn't correspond to %s" % (mapper, self)
@util.memoized_property
def _memoized_values(self):
@@ -599,11 +669,15 @@ class AliasedInsp(InspectionAttr):
def __repr__(self):
if self.with_polymorphic_mappers:
with_poly = "(%s)" % ", ".join(
- mp.class_.__name__ for mp in self.with_polymorphic_mappers)
+ mp.class_.__name__ for mp in self.with_polymorphic_mappers
+ )
else:
with_poly = ""
- return '<AliasedInsp at 0x%x; %s%s>' % (
- id(self), self.class_.__name__, with_poly)
+ return "<AliasedInsp at 0x%x; %s%s>" % (
+ id(self),
+ self.class_.__name__,
+ with_poly,
+ )
inspection._inspects(AliasedClass)(lambda target: target._aliased_insp)
@@ -700,15 +774,26 @@ def aliased(element, alias=None, name=None, flat=False, adapt_on_names=False):
)
return element.alias(name, flat=flat)
else:
- return AliasedClass(element, alias=alias, flat=flat,
- name=name, adapt_on_names=adapt_on_names)
+ return AliasedClass(
+ element,
+ alias=alias,
+ flat=flat,
+ name=name,
+ adapt_on_names=adapt_on_names,
+ )
-def with_polymorphic(base, classes, selectable=False,
- flat=False,
- polymorphic_on=None, aliased=False,
- innerjoin=False, _use_mapper_path=False,
- _existing_alias=None):
+def with_polymorphic(
+ base,
+ classes,
+ selectable=False,
+ flat=False,
+ polymorphic_on=None,
+ aliased=False,
+ innerjoin=False,
+ _use_mapper_path=False,
+ _existing_alias=None,
+):
"""Produce an :class:`.AliasedClass` construct which specifies
columns for descendant mappers of the given base.
@@ -777,24 +862,26 @@ def with_polymorphic(base, classes, selectable=False,
if _existing_alias:
assert _existing_alias.mapper is primary_mapper
classes = util.to_set(classes)
- new_classes = set([
- mp.class_ for mp in
- _existing_alias.with_polymorphic_mappers])
+ new_classes = set(
+ [mp.class_ for mp in _existing_alias.with_polymorphic_mappers]
+ )
if classes == new_classes:
return _existing_alias
else:
classes = classes.union(new_classes)
- mappers, selectable = primary_mapper.\
- _with_polymorphic_args(classes, selectable,
- innerjoin=innerjoin)
+ mappers, selectable = primary_mapper._with_polymorphic_args(
+ classes, selectable, innerjoin=innerjoin
+ )
if aliased or flat:
selectable = selectable.alias(flat=flat)
- return AliasedClass(base,
- selectable,
- with_polymorphic_mappers=mappers,
- with_polymorphic_discriminator=polymorphic_on,
- use_mapper_path=_use_mapper_path,
- represents_outer_join=not innerjoin)
+ return AliasedClass(
+ base,
+ selectable,
+ with_polymorphic_mappers=mappers,
+ with_polymorphic_discriminator=polymorphic_on,
+ use_mapper_path=_use_mapper_path,
+ represents_outer_join=not innerjoin,
+ )
def _orm_annotate(element, exclude=None):
@@ -804,7 +891,7 @@ def _orm_annotate(element, exclude=None):
Elements within the exclude collection will be cloned but not annotated.
"""
- return sql_util._deep_annotate(element, {'_orm_adapt': True}, exclude)
+ return sql_util._deep_annotate(element, {"_orm_adapt": True}, exclude)
def _orm_deannotate(element):
@@ -816,9 +903,9 @@ def _orm_deannotate(element):
"""
- return sql_util._deep_deannotate(element,
- values=("_orm_adapt", "parententity")
- )
+ return sql_util._deep_deannotate(
+ element, values=("_orm_adapt", "parententity")
+ )
def _orm_full_deannotate(element):
@@ -831,12 +918,18 @@ class _ORMJoin(expression.Join):
__visit_name__ = expression.Join.__visit_name__
def __init__(
- self,
- left, right, onclause=None, isouter=False,
- full=False, _left_memo=None, _right_memo=None):
+ self,
+ left,
+ right,
+ onclause=None,
+ isouter=False,
+ full=False,
+ _left_memo=None,
+ _right_memo=None,
+ ):
left_info = inspection.inspect(left)
- left_orm_info = getattr(left, '_joined_from_info', left_info)
+ left_orm_info = getattr(left, "_joined_from_info", left_info)
right_info = inspection.inspect(right)
adapt_to = right_info.selectable
@@ -859,19 +952,18 @@ class _ORMJoin(expression.Join):
prop = None
if prop:
- if sql_util.clause_is_present(
- on_selectable, left_info.selectable):
+ if sql_util.clause_is_present(on_selectable, left_info.selectable):
adapt_from = on_selectable
else:
adapt_from = left_info.selectable
- pj, sj, source, dest, \
- secondary, target_adapter = prop._create_joins(
- source_selectable=adapt_from,
- dest_selectable=adapt_to,
- source_polymorphic=True,
- dest_polymorphic=True,
- of_type=right_info.mapper)
+ pj, sj, source, dest, secondary, target_adapter = prop._create_joins(
+ source_selectable=adapt_from,
+ dest_selectable=adapt_to,
+ source_polymorphic=True,
+ dest_polymorphic=True,
+ of_type=right_info.mapper,
+ )
if sj is not None:
if isouter:
@@ -887,8 +979,11 @@ class _ORMJoin(expression.Join):
expression.Join.__init__(self, left, right, onclause, isouter, full)
- if not prop and getattr(right_info, 'mapper', None) \
- and right_info.mapper.single:
+ if (
+ not prop
+ and getattr(right_info, "mapper", None)
+ and right_info.mapper.single
+ ):
# if single inheritance target and we are using a manual
# or implicit ON clause, augment it the same way we'd augment the
# WHERE.
@@ -911,33 +1006,39 @@ class _ORMJoin(expression.Join):
assert self.right is leftmost
left = _ORMJoin(
- self.left, other.left,
- self.onclause, isouter=self.isouter,
+ self.left,
+ other.left,
+ self.onclause,
+ isouter=self.isouter,
_left_memo=self._left_memo,
- _right_memo=other._left_memo
+ _right_memo=other._left_memo,
)
return _ORMJoin(
left,
other.right,
- other.onclause, isouter=other.isouter,
- _right_memo=other._right_memo
+ other.onclause,
+ isouter=other.isouter,
+ _right_memo=other._right_memo,
)
def join(
- self, right, onclause=None,
- isouter=False, full=False, join_to_left=None):
+ self,
+ right,
+ onclause=None,
+ isouter=False,
+ full=False,
+ join_to_left=None,
+ ):
return _ORMJoin(self, right, onclause, full, isouter)
- def outerjoin(
- self, right, onclause=None,
- full=False, join_to_left=None):
+ def outerjoin(self, right, onclause=None, full=False, join_to_left=None):
return _ORMJoin(self, right, onclause, True, full=full)
def join(
- left, right, onclause=None, isouter=False,
- full=False, join_to_left=None):
+ left, right, onclause=None, isouter=False, full=False, join_to_left=None
+):
r"""Produce an inner join between left and right clauses.
:func:`.orm.join` is an extension to the core join interface
@@ -1085,8 +1186,9 @@ def _entity_isa(given, mapper):
"""
if given.is_aliased_class:
- return mapper in given.with_polymorphic_mappers or \
- given.mapper.isa(mapper)
+ return mapper in given.with_polymorphic_mappers or given.mapper.isa(
+ mapper
+ )
elif given.with_polymorphic_mappers:
return mapper in given.with_polymorphic_mappers
else:
@@ -1126,5 +1228,7 @@ def randomize_unitofwork():
from sqlalchemy.orm import unitofwork, session, mapper, dependency
from sqlalchemy.util import topological
from sqlalchemy.testing.util import RandomSet
- topological.set = unitofwork.set = session.set = mapper.set = \
- dependency.set = RandomSet
+
+ topological.set = (
+ unitofwork.set
+ ) = session.set = mapper.set = dependency.set = RandomSet