Update SQLAlchemy

This commit is contained in:
Ruud
2013-06-14 11:00:06 +02:00
parent 267ecfacab
commit 4aa6700ceb
124 changed files with 6500 additions and 5207 deletions
+140 -125
View File
@@ -1,5 +1,5 @@
# orm/mapper.py
# Copyright (C) 2005-2012 the SQLAlchemy authors and contributors <see AUTHORS file>
# Copyright (C) 2005-2013 the SQLAlchemy authors and contributors <see AUTHORS file>
#
# This module is part of SQLAlchemy and is released under
# the MIT License: http://www.opensource.org/licenses/mit-license.php
@@ -214,16 +214,16 @@ class Mapper(object):
local_table = None
"""The :class:`.Selectable` which this :class:`.Mapper` manages.
Typically is an instance of :class:`.Table` or :class:`.Alias`.
May also be ``None``.
Typically is an instance of :class:`.Table` or :class:`.Alias`.
May also be ``None``.
The "local" table is the
selectable that the :class:`.Mapper` is directly responsible for
selectable that the :class:`.Mapper` is directly responsible for
managing from an attribute access and flush perspective. For
non-inheriting mappers, the local table is the same as the
"mapped" table. For joined-table inheritance mappers, local_table
will be the particular sub-table of the overall "join" which
this :class:`.Mapper` represents. If this mapper is a
this :class:`.Mapper` represents. If this mapper is a
single-table inheriting mapper, local_table will be ``None``.
See also :attr:`~.Mapper.mapped_table`.
@@ -233,11 +233,11 @@ class Mapper(object):
mapped_table = None
"""The :class:`.Selectable` to which this :class:`.Mapper` is mapped.
Typically an instance of :class:`.Table`, :class:`.Join`, or
Typically an instance of :class:`.Table`, :class:`.Join`, or
:class:`.Alias`.
The "mapped" table is the selectable that
the mapper selects from during queries. For non-inheriting
The "mapped" table is the selectable that
the mapper selects from during queries. For non-inheriting
mappers, the mapped table is the same as the "local" table.
For joined-table inheritance mappers, mapped_table references the
full :class:`.Join` representing full rows for this particular
@@ -249,7 +249,7 @@ class Mapper(object):
"""
inherits = None
"""References the :class:`.Mapper` which this :class:`.Mapper`
"""References the :class:`.Mapper` which this :class:`.Mapper`
inherits from, if any.
This is a *read only* attribute determined during mapper construction.
@@ -268,7 +268,7 @@ class Mapper(object):
"""
concrete = None
"""Represent ``True`` if this :class:`.Mapper` is a concrete
"""Represent ``True`` if this :class:`.Mapper` is a concrete
inheritance mapper.
This is a *read only* attribute determined during mapper construction.
@@ -291,7 +291,7 @@ class Mapper(object):
primary_key = None
"""An iterable containing the collection of :class:`.Column` objects
which comprise the 'primary key' of the mapped table, from the
which comprise the 'primary key' of the mapped table, from the
perspective of this :class:`.Mapper`.
This list is against the selectable in :attr:`~.Mapper.mapped_table`. In the
@@ -301,7 +301,7 @@ class Mapper(object):
referenced by the :class:`.Join`.
The list is also not necessarily the same as the primary key column
collection associated with the underlying tables; the :class:`.Mapper`
collection associated with the underlying tables; the :class:`.Mapper`
features a ``primary_key`` argument that can override what the
:class:`.Mapper` considers as primary key columns.
@@ -328,7 +328,7 @@ class Mapper(object):
"""
single = None
"""Represent ``True`` if this :class:`.Mapper` is a single table
"""Represent ``True`` if this :class:`.Mapper` is a single table
inheritance mapper.
:attr:`~.Mapper.local_table` will be ``None`` if this flag is set.
@@ -339,8 +339,8 @@ class Mapper(object):
"""
non_primary = None
"""Represent ``True`` if this :class:`.Mapper` is a "non-primary"
mapper, e.g. a mapper that is used only to selet rows but not for
"""Represent ``True`` if this :class:`.Mapper` is a "non-primary"
mapper, e.g. a mapper that is used only to selet rows but not for
persistence management.
This is a *read only* attribute determined during mapper construction.
@@ -364,10 +364,10 @@ class Mapper(object):
"""A mapping of "polymorphic identity" identifiers mapped to :class:`.Mapper`
instances, within an inheritance scenario.
The identifiers can be of any type which is comparable to the
The identifiers can be of any type which is comparable to the
type of column represented by :attr:`~.Mapper.polymorphic_on`.
An inheritance chain of mappers will all reference the same
An inheritance chain of mappers will all reference the same
polymorphic map object. The object is used to correlate incoming
result rows to target mappers.
@@ -402,10 +402,10 @@ class Mapper(object):
"""
columns = None
"""A collection of :class:`.Column` or other scalar expression
"""A collection of :class:`.Column` or other scalar expression
objects maintained by this :class:`.Mapper`.
The collection behaves the same as that of the ``c`` attribute on
The collection behaves the same as that of the ``c`` attribute on
any :class:`.Table` object, except that only those columns included in
this mapping are present, and are keyed based on the attribute name
defined in the mapping, not necessarily the ``key`` attribute of the
@@ -419,11 +419,11 @@ class Mapper(object):
validators = None
"""An immutable dictionary of attributes which have been decorated
using the :func:`~.orm.validates` decorator.
using the :func:`~.orm.validates` decorator.
The dictionary contains string attribute names as keys
mapped to the actual validation method.
"""
c = None
@@ -443,13 +443,13 @@ class Mapper(object):
self.inherits = class_mapper(self.inherits, compile=False)
if not issubclass(self.class_, self.inherits.class_):
raise sa_exc.ArgumentError(
"Class '%s' does not inherit from '%s'" %
"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" %
"only allowed from a %s mapper" %
(np, self.class_.__name__, np))
# inherit_condition is optional.
if self.local_table is None:
@@ -472,7 +472,7 @@ class Mapper(object):
self.inherits.local_table,
self.local_table)
self.mapped_table = sql.join(
self.inherits.mapped_table,
self.inherits.mapped_table,
self.local_table,
self.inherit_condition)
@@ -499,7 +499,7 @@ class Mapper(object):
"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.version_id_col.description,
self.inherits.version_id_col.description)
)
@@ -528,7 +528,7 @@ class Mapper(object):
if self.mapped_table is None:
raise sa_exc.ArgumentError(
"Mapper '%s' does not have a mapped_table specified."
"Mapper '%s' does not have a mapped_table specified."
% self)
def _set_with_polymorphic(self, with_polymorphic):
@@ -580,6 +580,12 @@ class Mapper(object):
self.inherits._inheriting_mappers.add(self)
self.passive_updates = self.inherits.passive_updates
self._all_tables = self.inherits._all_tables
for key, prop in mapper._props.iteritems():
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):
self.polymorphic_on = polymorphic_on
@@ -589,7 +595,7 @@ class Mapper(object):
if self.inherits:
self.dispatch._update(self.inherits.dispatch)
super_extensions = set(chain(*[m._deprecated_extensions
super_extensions = set(chain(*[m._deprecated_extensions
for m in self.inherits.iterate_to_root()]))
else:
super_extensions = set()
@@ -600,7 +606,7 @@ class Mapper(object):
def _configure_listeners(self):
if self.inherits:
super_extensions = set(chain(*[m._deprecated_extensions
super_extensions = set(chain(*[m._deprecated_extensions
for m in self.inherits.iterate_to_root()]))
else:
super_extensions = set()
@@ -647,8 +653,8 @@ class Mapper(object):
"remove *all* current mappers from all classes." %
self.class_)
#else:
# a ClassManager may already exist as
# ClassManager.instrument_attribute() creates
# 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
@@ -662,8 +668,8 @@ class Mapper(object):
manager.mapper = self
manager.deferred_scalar_loader = self._load_scalar_attributes
# The remaining members can be added by any mapper,
# The remaining members can be added by any mapper,
# e_name None or not.
if manager.info.get(_INSTRUMENTOR, False):
return
@@ -678,9 +684,10 @@ class Mapper(object):
self._reconstructor = method
event.listen(manager, 'load', _event_on_load, raw=True)
elif hasattr(method, '__sa_validators__'):
include_removes = getattr(method, "__sa_include_removes__", False)
for name in method.__sa_validators__:
self.validators = self.validators.union(
{name : method}
{name : (method, include_removes)}
)
manager.info[_INSTRUMENTOR] = self
@@ -746,10 +753,10 @@ class Mapper(object):
self._readonly_props = set(
self._columntoproperty[col]
for col in self._columntoproperty
if not hasattr(col, 'table') or
if not hasattr(col, 'table') or
col.table not in self._cols_by_table)
# if explicit PK argument sent, add those columns to the
# if explicit PK argument sent, add those columns to the
# primary key mappings
if self._primary_key_argument:
for k in self._primary_key_argument:
@@ -762,23 +769,23 @@ class Mapper(object):
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'" %
"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."
"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
# if inheriting, the "primary key" for this mapper is
# that of the inheriting (unless concrete or explicit)
self.primary_key = self.inherits.primary_key
else:
# determine primary key from argument or mapped_table pks -
# determine primary key from argument or mapped_table pks -
# reduce to the minimal set of columns
if self._primary_key_argument:
primary_key = sqlutil.reduce_columns(
@@ -793,7 +800,7 @@ class Mapper(object):
if len(primary_key) == 0:
raise sa_exc.ArgumentError(
"Mapper %s could not assemble any primary "
"key columns for mapped table '%s'" %
"key columns for mapped table '%s'" %
(self, self.mapped_table.description))
self.primary_key = tuple(primary_key)
@@ -845,19 +852,19 @@ class Mapper(object):
if column in mapper._columntoproperty:
column_key = mapper._columntoproperty[column].key
self._configure_property(column_key,
column,
init=False,
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
'polymorphic_on' column, if applicable, and not
"""Configure an attribute on the mapper representing the
'polymorphic_on' column, if applicable, and not
already generated by _configure_properties (which is typical).
Also create a setter function which will assign this
attribute to the value of the 'polymorphic_identity'
upon instance construction, also if applicable. This
upon instance construction, also if applicable. This
routine will run when an instance is created.
"""
@@ -906,15 +913,15 @@ class Mapper(object):
else:
# polymorphic_on is a Column or SQL expression and doesn't
# appear to be mapped.
# this means it can be 1. only present in the with_polymorphic
# this means it can be 1. only present in the with_polymorphic
# selectable or 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)
if col is None:
# polymorphic_on doesn't derive from any column/expression
# polymorphic_on doesn't derive from any column/expression
# isn't present in the mapped table.
# we will make a "hidden" ColumnProperty for it.
# Just check that if it's directly a schema.Column and we
# we will make a "hidden" ColumnProperty for it.
# Just check that if it's directly a schema.Column and we
# have with_polymorphic, it's likely a user error if the
# schema.Column isn't represented somehow in either mapped_table or
# with_polymorphic. Otherwise as of 0.7.4 we just go with it
@@ -932,15 +939,14 @@ class Mapper(object):
"loads will not function properly"
% col.description)
else:
# column/expression that polymorphic_on derives from
# column/expression that polymorphic_on derives from
# is present in our mapped table
# and is probably mapped, but polymorphic_on itself
# is not. This happens when
# the polymorphic_on is only directly present in the
# is not. This happens when
# the polymorphic_on is only directly present in the
# with_polymorphic selectable, as when use polymorphic_union.
# we'll make a separate ColumnProperty for it.
instrument = True
key = getattr(col, 'key', None)
if key:
if self._should_exclude(col.key, col.key, False, col):
@@ -952,7 +958,7 @@ class Mapper(object):
key = col.key
self._configure_property(
key,
key,
properties.ColumnProperty(col, _instrument=instrument),
init=init, setparent=True)
polymorphic_key = key
@@ -998,15 +1004,15 @@ class Mapper(object):
self._configure_property(key, prop, init=False, setparent=False)
elif key not in self._props:
self._configure_property(
key,
properties.ConcreteInheritedProperty(),
key,
properties.ConcreteInheritedProperty(),
init=init, setparent=True)
def _configure_property(self, key, prop, init=True, setparent=True):
self._log("_configure_property(%s, %s)", key, prop.__class__.__name__)
if not isinstance(prop, MapperProperty):
# we were passed a Column or a list of Columns;
# we were passed a Column or a list of Columns;
# generate a properties.ColumnProperty
columns = util.to_list(prop)
column = columns[0]
@@ -1026,7 +1032,7 @@ class Mapper(object):
"explicitly."
% (prop.columns[-1], column, key))
# existing properties.ColumnProperty from an inheriting
# existing properties.ColumnProperty from an inheriting
# mapper. make a copy and append our column to it
prop = prop.copy()
prop.columns.insert(0, column)
@@ -1065,14 +1071,14 @@ class Mapper(object):
"(including its availability as a foreign key), "
"use the 'include_properties' or 'exclude_properties' "
"mapper arguments to control specifically which table "
"columns get mapped." %
"columns get mapped." %
(key, self, column.key, prop))
if isinstance(prop, properties.ColumnProperty):
col = self.mapped_table.corresponding_column(prop.columns[0])
# if the column is not present in the mapped table,
# test if a column has been added after the fact to the
# if the column is not present in the mapped table,
# test if a column has been added after the fact to the
# parent table (or their parent, etc.) [ticket:1570]
if col is None and self.inherits:
path = [self]
@@ -1086,20 +1092,20 @@ class Mapper(object):
break
path.append(m)
# subquery expression, column not present in the mapped
# subquery expression, column not present in the mapped
# selectable.
if col is None:
col = prop.columns[0]
# column is coming in after _readonly_props was
# column is coming in after _readonly_props was
# initialized; check for 'readonly'
if hasattr(self, '_readonly_props') and \
(not hasattr(col, 'table') or
(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
# 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 \
@@ -1199,10 +1205,10 @@ class Mapper(object):
def _log_desc(self):
return "(" + self.class_.__name__ + \
"|" + \
(self.local_table is not None and
self.local_table.description or
(self.local_table is not None and
self.local_table.description or
str(self.local_table)) +\
(self.non_primary and
(self.non_primary and
"|non-primary" or "") + ")"
def _log(self, msg, *args):
@@ -1223,7 +1229,7 @@ class Mapper(object):
def __str__(self):
return "Mapper|%s|%s%s" % (
self.class_.__name__,
self.local_table is not None and
self.local_table is not None and
self.local_table.description or None,
self.non_primary and "|non-primary" or ""
)
@@ -1288,7 +1294,7 @@ class Mapper(object):
for m in mappers:
if not m.isa(self):
raise sa_exc.InvalidRequestError(
"%r does not inherit from %r" %
"%r does not inherit from %r" %
(m, self))
else:
mappers = []
@@ -1387,7 +1393,7 @@ class Mapper(object):
mappers])
):
if getattr(c, '_is_polymorphic_discriminator', False) and \
(self.polymorphic_on is None or
(self.polymorphic_on is None or
c.columns[0] is not self.polymorphic_on):
continue
yield c
@@ -1452,7 +1458,7 @@ class Mapper(object):
return result
def _is_userland_descriptor(self, obj):
if isinstance(obj, (MapperProperty,
if isinstance(obj, (MapperProperty,
attributes.QueryableAttribute)):
return False
elif not hasattr(obj, '__get__'):
@@ -1505,7 +1511,7 @@ class Mapper(object):
return False
def common_parent(self, other):
"""Return true if the given mapper shares a
"""Return true if the given mapper shares a
common inherited parent as this mapper."""
return self.base_mapper is other.base_mapper
@@ -1634,7 +1640,7 @@ class Mapper(object):
for col in self.primary_key
]
def _get_state_attr_by_column(self, state, dict_, column,
def _get_state_attr_by_column(self, state, dict_, column,
passive=attributes.PASSIVE_OFF):
prop = self._columntoproperty[column]
return state.manager[prop.key].impl.get(state, dict_, passive=passive)
@@ -1648,7 +1654,7 @@ class Mapper(object):
dict_ = attributes.instance_dict(obj)
return self._get_committed_state_attr_by_column(state, dict_, column)
def _get_committed_state_attr_by_column(self, state, dict_,
def _get_committed_state_attr_by_column(self, state, dict_,
column, passive=attributes.PASSIVE_OFF):
prop = self._columntoproperty[column]
@@ -1674,8 +1680,8 @@ class Mapper(object):
statement = self._optimized_get_statement(state, attribute_names)
if statement is not None:
result = session.query(self).from_statement(statement).\
_load_on_ident(None,
only_load_props=attribute_names,
_load_on_ident(None,
only_load_props=attribute_names,
refresh_state=state)
if result is False:
@@ -1698,16 +1704,16 @@ class Mapper(object):
_none_set.issuperset(identity_key):
util.warn("Instance %s to be refreshed doesn't "
"contain a full primary key - can't be refreshed "
"(and shouldn't be expired, either)."
"(and shouldn't be expired, either)."
% state_str(state))
return
result = session.query(self)._load_on_ident(
identity_key,
refresh_state=state,
identity_key,
refresh_state=state,
only_load_props=attribute_names)
# if instance is pending, a refresh operation
# if instance is pending, a refresh operation
# may not complete (even if PK attributes are assigned)
if has_key and result is None:
raise orm_exc.ObjectDeletedError(state)
@@ -1716,16 +1722,16 @@ class Mapper(object):
"""assemble a WHERE clause which retrieves a given state by primary
key, using a minimized set of tables.
Applies to a joined-table inheritance mapper where the
Applies to a joined-table inheritance mapper where the
requested attribute names are only present on joined tables,
not the base table. The WHERE clause attempts to include
not the base table. The WHERE clause attempts to include
only those tables to minimize joins.
"""
props = self._props
tables = set(chain(
*[sqlutil.find_tables(c, check_columns=True)
*[sqlutil.find_tables(c, check_columns=True)
for key in attribute_names
for c in props[key].columns]
))
@@ -1744,8 +1750,8 @@ class Mapper(object):
if leftcol.table not in tables:
leftval = self._get_committed_state_attr_by_column(
state, state.dict,
leftcol,
state, state.dict,
leftcol,
passive=attributes.PASSIVE_NO_INITIALIZE)
if leftval is attributes.PASSIVE_NO_RESULT or leftval is None:
raise ColumnsNotAvailable()
@@ -1753,8 +1759,8 @@ class Mapper(object):
type_=binary.right.type)
elif rightcol.table not in tables:
rightval = self._get_committed_state_attr_by_column(
state, state.dict,
rightcol,
state, state.dict,
rightcol,
passive=attributes.PASSIVE_NO_INITIALIZE)
if rightval is attributes.PASSIVE_NO_RESULT or rightval is None:
raise ColumnsNotAvailable()
@@ -1770,8 +1776,8 @@ class Mapper(object):
start = True
if start and not mapper.single:
allconds.append(visitors.cloned_traverse(
mapper.inherit_condition,
{},
mapper.inherit_condition,
{},
{'binary':visit_binary}
)
)
@@ -1804,7 +1810,7 @@ class Mapper(object):
visited_states = set()
prp, mpp = object(), object()
visitables = deque([(deque(self._props.values()), prp,
visitables = deque([(deque(self._props.values()), prp,
state, state.dict)])
while visitables:
@@ -1817,7 +1823,7 @@ class Mapper(object):
prop = iterator.popleft()
if type_ not in prop.cascade:
continue
queue = deque(prop.cascade_iterator(type_, parent_state,
queue = deque(prop.cascade_iterator(type_, parent_state,
parent_dict, visited_states, halt_on))
if queue:
visitables.append((queue,mpp, None, None))
@@ -1826,8 +1832,8 @@ class Mapper(object):
corresponding_dict = iterator.popleft()
yield instance, instance_mapper, \
corresponding_state, corresponding_dict
visitables.append((deque(instance_mapper._props.values()),
prp, corresponding_state,
visitables.append((deque(instance_mapper._props.values()),
prp, corresponding_state,
corresponding_dict))
@_memoized_configured_property
@@ -1884,7 +1890,7 @@ class Mapper(object):
@util.memoized_property
def _table_to_equated(self):
"""memoized map of tables to collections of columns to be
"""memoized map of tables to collections of columns to be
synchronized upwards to the base mapper."""
result = util.defaultdict(list)
@@ -1900,16 +1906,16 @@ class Mapper(object):
return result
def _instance_processor(self, context, path, reduced_path, adapter,
polymorphic_from=None,
def _instance_processor(self, context, path, reduced_path, adapter,
polymorphic_from=None,
only_load_props=None, refresh_state=None,
polymorphic_discriminator=None):
"""Produce a mapper level row processor callable
"""Produce a mapper level row processor callable
which processes rows into mapped instances."""
# note that this method, most of which exists in a closure
# called _instance(), resists being broken out, as
# called _instance(), resists being broken out, as
# attempts to do so tend to add significant function
# call overhead. _instance() is the most
# performance-critical section in the whole ORM.
@@ -2019,7 +2025,7 @@ class Mapper(object):
identitykey = self._identity_key_from_state(refresh_state)
else:
identitykey = (
identity_class,
identity_class,
tuple([row[column] for column in pk_cols])
)
@@ -2036,22 +2042,22 @@ class Mapper(object):
version_id_col is not None and \
context.version_check and \
self._get_state_attr_by_column(
state,
dict_,
state,
dict_,
self.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),
"does not match database-loaded version id '%s'."
% (state_str(state),
self._get_state_attr_by_column(
state, dict_,
self.version_id_col),
row[version_id_col]))
elif refresh_state:
# out of band refresh_state detected (i.e. its not in the
# session.identity_map) honor it anyway. this can happen
# session.identity_map) honor it anyway. this can happen
# if a _get() occurs within save_obj(), such as
# when eager_defaults is True.
state = refresh_state
@@ -2072,7 +2078,7 @@ class Mapper(object):
if create_instance:
for fn in create_instance:
instance = fn(self, context,
instance = fn(self, context,
row, self.class_)
if instance is not EXT_CONTINUE:
manager = attributes.manager_of_class(
@@ -2103,8 +2109,8 @@ class Mapper(object):
if populate_instance:
for fn in populate_instance:
ret = fn(self, context, row, state,
only_load_props=only_load_props,
ret = fn(self, context, row, state,
only_load_props=only_load_props,
instancekey=identitykey, isnew=isnew)
if ret is not EXT_CONTINUE:
break
@@ -2132,8 +2138,8 @@ class Mapper(object):
if populate_instance:
for fn in populate_instance:
ret = fn(self, context, row, state,
only_load_props=attrs,
ret = fn(self, context, row, state,
only_load_props=attrs,
instancekey=identitykey, isnew=isnew)
if ret is not EXT_CONTINUE:
break
@@ -2153,7 +2159,7 @@ class Mapper(object):
if result is not None:
if append_result:
for fn in append_result:
if fn(self, context, row, state,
if fn(self, context, row, state,
result, instancekey=identitykey,
isnew=isnew) is not EXT_CONTINUE:
break
@@ -2173,7 +2179,7 @@ class Mapper(object):
pops = (new_populators, existing_populators, delayed_populators, eager_populators)
for prop in self._props.itervalues():
for i, pop in enumerate(prop.create_row_processor(
context, path,
context, path,
reduced_path,
self, row, adapter)):
if pop is not None:
@@ -2196,8 +2202,8 @@ class Mapper(object):
if mapper is self:
return None
# replace the tip of the path info with the subclass mapper
# being used. that way accurate "load_path" info is available
# replace the tip of the path info with the subclass mapper
# being used. that way accurate "load_path" info is available
# for options invoked during deferred loads.
# we lose AliasedClass path elements this way, but currently,
# those are not needed at this stage.
@@ -2205,7 +2211,7 @@ class Mapper(object):
# this asserts to true
#assert mapper.isa(_class_to_mapper(path[-1]))
return mapper._instance_processor(context, path[0:-1] + (mapper,),
return mapper._instance_processor(context, path[0:-1] + (mapper,),
reduced_path[0:-1] + (mapper.base_mapper,),
adapter,
polymorphic_from=self)
@@ -2217,14 +2223,14 @@ def configure_mappers():
"""Initialize the inter-mapper relationships of all mappers that
have been constructed thus far.
This function can be called any number of times, but in
This function can be called any number of times, but in
most cases is handled internally.
"""
global _new_mappers
if not _new_mappers:
return
return
_call_configured = None
_COMPILE_MUTEX.acquire()
@@ -2240,8 +2246,8 @@ def configure_mappers():
return
# initialize properties on all mappers
# note that _mapper_registry is unordered, which
# may randomly conceal/reveal issues related to
# note that _mapper_registry is unordered, which
# may randomly conceal/reveal issues related to
# the order of mapper compilation
for mapper in list(_mapper_registry):
if getattr(mapper, '_configure_failed', False):
@@ -2291,7 +2297,7 @@ def reconstructor(fn):
fn.__sa_reconstructor__ = True
return fn
def validates(*names):
def validates(*names, **kw):
"""Decorate a method as a 'validator' for one or more named properties.
Designates a method as a validator, a method which receives the
@@ -2307,9 +2313,18 @@ def validates(*names):
an assertion to avoid recursion overflows. This is a reentrant
condition which is not supported.
:param \*names: list of attribute names to be validated.
:param include_removes: if True, "remove" events will be
sent as well - the validation function must accept an additional
argument "is_remove" which will be a boolean.
.. versionadded:: 0.7.7
"""
include_removes = kw.pop('include_removes', False)
def wrap(fn):
fn.__sa_validators__ = names
fn.__sa_include_removes__ = include_removes
return fn
return wrap
@@ -2320,7 +2335,7 @@ def _event_on_load(state, ctx):
def _event_on_first_init(manager, cls):
"""Initial mapper compilation trigger.
instrumentation calls this one when InstanceState
is first generated, and is needed for legacy mutable
attributes to work.
@@ -2333,11 +2348,11 @@ def _event_on_first_init(manager, cls):
def _event_on_init(state, args, kwargs):
"""Run init_instance hooks.
This also includes mapper compilation, normally not needed
here but helps with some piecemeal configuration
scenarios (such as in the ORM tutorial).
"""
instrumenting_mapper = state.manager.info.get(_INSTRUMENTOR)