summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/mapper.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/orm/mapper.py')
-rw-r--r--lib/sqlalchemy/orm/mapper.py234
1 files changed, 128 insertions, 106 deletions
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 761e1af56..dceccf70f 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -206,16 +206,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`.
@@ -225,11 +225,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
@@ -241,7 +241,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.
@@ -260,7 +260,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.
@@ -283,7 +283,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
@@ -293,7 +293,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.
@@ -320,7 +320,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.
@@ -331,8 +331,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.
@@ -356,10 +356,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.
@@ -394,10 +394,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
@@ -411,11 +411,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
@@ -439,13 +439,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:
@@ -468,7 +468,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)
@@ -495,7 +495,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)
)
@@ -524,7 +524,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):
@@ -586,7 +586,7 @@ class Mapper(object):
if self.inherits:
self.dispatch._update(self.inherits.dispatch)
super_extensions = set(
- chain(*[m._deprecated_extensions
+ chain(*[m._deprecated_extensions
for m in self.inherits.iterate_to_root()]))
else:
super_extensions = set()
@@ -598,7 +598,7 @@ class Mapper(object):
def _configure_listeners(self):
if self.inherits:
super_extensions = set(
- chain(*[m._deprecated_extensions
+ chain(*[m._deprecated_extensions
for m in self.inherits.iterate_to_root()]))
else:
super_extensions = set()
@@ -645,8 +645,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
@@ -660,8 +660,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
@@ -745,10 +745,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:
@@ -761,23 +761,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 = sql_util.reduce_columns(
@@ -792,7 +792,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)
@@ -844,19 +844,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.
"""
@@ -905,15 +905,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
@@ -931,11 +931,11 @@ 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
@@ -951,7 +951,7 @@ class Mapper(object):
key = col.key
self._configure_property(
- key,
+ key,
properties.ColumnProperty(col, _instrument=instrument),
init=init, setparent=True)
polymorphic_key = key
@@ -997,15 +997,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]
@@ -1025,7 +1025,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)
@@ -1064,14 +1064,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]
@@ -1085,20 +1085,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 \
@@ -1198,10 +1198,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):
@@ -1222,7 +1222,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 ""
)
@@ -1281,7 +1281,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 = []
@@ -1347,7 +1347,7 @@ class Mapper(object):
self._mappers_from_spec(spec, selectable),
False)
- def _with_polymorphic_args(self, spec=None, selectable=False,
+ def _with_polymorphic_args(self, spec=None, selectable=False,
innerjoin=False):
if self.with_polymorphic:
if not spec:
@@ -1360,7 +1360,7 @@ class Mapper(object):
if selectable is not None:
return mappers, selectable
else:
- return mappers, self._selectable_from_mappers(mappers,
+ return mappers, self._selectable_from_mappers(mappers,
innerjoin)
@_memoized_configured_property
@@ -1387,7 +1387,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
@@ -1475,7 +1475,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__'):
@@ -1528,7 +1528,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
@@ -1657,7 +1657,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)
@@ -1671,7 +1671,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]
@@ -1698,8 +1698,8 @@ class Mapper(object):
if statement is not None:
result = loading.load_on_ident(
session.query(self).from_statement(statement),
- None,
- only_load_props=attribute_names,
+ None,
+ only_load_props=attribute_names,
refresh_state=state
)
@@ -1723,17 +1723,17 @@ 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 = loading.load_on_ident(
session.query(self),
- 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)
@@ -1742,16 +1742,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(
- *[sql_util.find_tables(c, check_columns=True)
+ *[sql_util.find_tables(c, check_columns=True)
for key in attribute_names
for c in props[key].columns]
))
@@ -1770,8 +1770,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()
@@ -1779,8 +1779,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()
@@ -1796,8 +1796,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}
)
)
@@ -1830,7 +1830,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:
@@ -1843,7 +1843,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))
@@ -1852,8 +1852,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
@@ -1865,9 +1865,31 @@ class Mapper(object):
table_to_mapper = {}
for mapper in self.base_mapper.self_and_descendants:
for t in mapper.tables:
- table_to_mapper[t] = mapper
+ table_to_mapper.setdefault(t, mapper)
+
+ def skip(fk):
+ # attempt to skip dependencies that are not
+ # significant to the inheritance chain
+ # for two tables that are related by inheritance.
+ # while that dependency may be important, it's techinically
+ # 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:
+ 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))
+ 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.iterkeys())
+ sorted_ = sql_util.sort_tables(table_to_mapper.iterkeys(),
+ skip_fn=skip)
ret = util.OrderedDict()
for t in sorted_:
ret[t] = table_to_mapper[t]
@@ -1910,7 +1932,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)
@@ -1931,14 +1953,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()
@@ -1954,8 +1976,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):
@@ -2022,7 +2044,7 @@ def validates(*names, **kw):
condition which is not supported.
:param \*names: list of attribute names to be validated.
- :param include_removes: if True, "remove" events will be
+ :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.
@@ -2043,7 +2065,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.
@@ -2056,11 +2078,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)