_already_compiling = False
_none_set = frozenset([None])
- _memoized_compiled_property = util.group_expirable_memoized_property()
+ _memoized_configured_property = util.group_expirable_memoized_property()
-# a list of MapperExtensions that will be installed in all mappers by default
-global_extensions = []
-
# a constant returned by _get_attr_by_column to indicate
# this mapper is not handling an attribute for a particular
# column
for name in method.__sa_validators__:
self._validators[name] = method
- if 'reconstruct_instance' in self.extension:
- def reconstruct(instance):
- self.extension.reconstruct_instance(self, instance)
- event_registry.add_listener('on_load', reconstruct)
-
manager.info[_INSTRUMENTOR] = self
-
+
+ @util.deprecated("0.7", message=":meth:`.Mapper.compile` "
+ "is replaced by :func:`.configure_mappers`")
+ def compile(self):
+ """Initialize the inter-mapper relationships of all mappers that
+ have been constructed thus far.
+
+ """
+ configure_mappers()
+ return self
+
+
+ @property
+ @util.deprecated("0.7", message=":attr:`.Mapper.compiled` "
+ "is replaced by :attr:`.Mapper.configured`")
+ def compiled(self):
+ return self.configured
+
def dispose(self):
# Disable any attribute-based compilation.
- self.compiled = True
+ self.configured = True
- if hasattr(self, '_compile_failed'):
- del self._compile_failed
+ if hasattr(self, '_configure_failed'):
+ del self._configure_failed
if not self.non_primary and \
self.class_manager.is_mapped and \
def has_property(self, key):
return key in self._props
- def get_property(self, key,
- resolve_synonyms=False,
- raiseerr=True, _compile_mappers=True):
-
- """return a :class:`.MapperProperty` associated with the given key.
+ def get_property(self, key, _compile_mappers=True):
+ """return a MapperProperty associated with the given key.
- resolve_synonyms=False and raiseerr=False are deprecated.
+ Calls getattr() against the mapped class itself, so that class-level
+ proxies will be resolved to the underlying property, if any.
"""
-
+
- if _compile_mappers and not self.compiled:
- self.compile()
+ if _compile_mappers and _new_mappers:
+ configure_mappers()
-
- if not resolve_synonyms:
- prop = self._props.get(key, None)
- if prop is None and raiseerr:
- raise sa_exc.InvalidRequestError(
- "Mapper '%s' has no property '%s'" %
- (self, key))
- return prop
- else:
- try:
- return getattr(self.class_, key).property
- except AttributeError:
- if raiseerr:
- raise sa_exc.InvalidRequestError(
- "Mapper '%s' has no property '%s'" % (self, key))
- else:
- return None
-
++
+ try:
+ return getattr(self.class_, key).property
+ except AttributeError:
+ raise sa_exc.InvalidRequestError(
+ "Mapper '%s' has no property '%s'" % (self, key))
+
@util.deprecated('0.6.4',
'Call to deprecated function mapper._get_col_to_pr'
'op(). Use mapper.get_property_by_column()')
return fn
return wrap
-def _event_on_init(state, instance, args, kwargs):
- """Trigger mapper compilation and run init_instance hooks."""
-
+def _event_on_load(state):
instrumenting_mapper = state.manager.info[_INSTRUMENTOR]
- if _new_mappers:
- configure_mappers()
- if 'init_instance' in instrumenting_mapper.extension:
- instrumenting_mapper.extension.init_instance(
- instrumenting_mapper, instrumenting_mapper.class_,
- state.manager.events.original_init,
- instance, args, kwargs)
-
-def _event_on_init_failure(state, instance, args, kwargs):
- """Run init_failed hooks."""
+ if instrumenting_mapper._reconstructor:
+ instrumenting_mapper._reconstructor(state.obj())
+
+def _event_on_init(state, args, kwargs):
+ """Trigger mapper compilation and run init_instance hooks."""
- instrumenting_mapper = state.manager.info[_INSTRUMENTOR]
- if 'init_failed' in instrumenting_mapper.extension:
- util.warn_exception(
- instrumenting_mapper.extension.init_failed,
- instrumenting_mapper, instrumenting_mapper.class_,
- state.manager.events.original_init, instance, args, kwargs)
+ instrumenting_mapper = state.manager.info.get(_INSTRUMENTOR)
+ if instrumenting_mapper:
- # compile() always compiles all mappers
- instrumenting_mapper.compile()
++ if _new_mappers:
++ configure_mappers()
+
+ if instrumenting_mapper._set_polymorphic_identity:
+ instrumenting_mapper._set_polymorphic_identity(state)
-def _event_on_resurrect(state, instance):
+def _event_on_resurrect(state):
# re-populate the primary key elements
# of the dict based on the mapping.
- instrumenting_mapper = state.manager.info[_INSTRUMENTOR]
- for col, val in zip(instrumenting_mapper.primary_key, state.key[1]):
- instrumenting_mapper._set_state_attr_by_column(
- state, state.dict, col, val)
+ instrumenting_mapper = state.manager.info.get(_INSTRUMENTOR)
+ if instrumenting_mapper:
+ for col, val in zip(instrumenting_mapper.primary_key, state.key[1]):
+ instrumenting_mapper._set_state_attr_by_column(
+ state, state.dict, col, val)
def _sort_states(states):
from sqlalchemy.util import EMPTY_SET
import weakref
from sqlalchemy import util
-
-from sqlalchemy.orm.attributes import PASSIVE_NO_RESULT, PASSIVE_OFF, \
- NEVER_SET, NO_VALUE, manager_of_class, \
- ATTR_WAS_SET
-from sqlalchemy.orm import attributes, exc as orm_exc, interfaces, configure_mappers
++
+from sqlalchemy.orm import exc as orm_exc, attributes, interfaces
+from sqlalchemy.orm.attributes import PASSIVE_OFF, PASSIVE_NO_RESULT, \
+ PASSIVE_NO_FETCH, NEVER_SET, ATTR_WAS_SET, NO_VALUE
+
++mapperlib = util.importlater("sqlalchemy.orm", "mapperlib")
+
import sys
-attributes.state = sys.modules['sqlalchemy.orm.state']
class InstanceState(object):
"""tracks state information at the instance level."""
"Cannot deserialize object of type %r - no mapper() has"
" been configured for this class within the current Python process!" %
self.class_)
- elif manager.is_mapped and not manager.mapper.compiled:
- manager.mapper.compile()
+ elif manager.is_mapped and not manager.mapper.configured:
- configure_mappers()
++ mapperlib.configure_mappers()
self.committed_state = state.get('committed_state', {})
self.pending = state.get('pending', {})
assert class_mapper(User).get_property('props').secondary \
is user_to_prop
- compile_mappers()
+ def test_string_dependency_resolution_schemas(self):
+ Base = decl.declarative_base()
+
+ class User(Base):
+
+ __tablename__ = 'users'
+ __table_args__ = {'schema':'fooschema'}
+
+ id = Column(Integer, primary_key=True)
+ name = Column(String(50))
+ props = relationship('Prop', secondary='fooschema.user_to_prop',
+ primaryjoin='User.id==fooschema.user_to_prop.c.user_id',
+ secondaryjoin='fooschema.user_to_prop.c.prop_id==Prop.id',
+ backref='users')
+
+ class Prop(Base):
+
+ __tablename__ = 'props'
+ __table_args__ = {'schema':'fooschema'}
+
+ id = Column(Integer, primary_key=True)
+ name = Column(String(50))
+
+ user_to_prop = Table('user_to_prop', Base.metadata,
+ Column('user_id', Integer, ForeignKey('fooschema.users.id')),
+ Column('prop_id',Integer, ForeignKey('fooschema.props.id')),
+ schema='fooschema')
++ configure_mappers()
+
+ assert class_mapper(User).get_property('props').secondary \
+ is user_to_prop
+
def test_uncompiled_attributes_in_relationship(self):
class Address(Base, ComparableEntity):
related_child1 = Column('c1', Integer)
__mapper_args__ = dict(polymorphic_identity='child2')
- sa.orm.compile_mappers() # no exceptions here
+ sa.orm.configure_mappers() # no exceptions here
+ def test_foreign_keys_with_col(self):
+ """Test that foreign keys that reference a literal 'id' subclass
+ 'id' attribute behave intuitively.
+
+ See [ticket:1892].
+
+ """
+ class Booking(Base):
+ __tablename__ = 'booking'
+ id = Column(Integer, primary_key=True)
+
+ class PlanBooking(Booking):
+ __tablename__ = 'plan_booking'
+ id = Column(Integer, ForeignKey(Booking.id),
+ primary_key=True)
+
+ # referencing PlanBooking.id gives us the column
+ # on plan_booking, not booking
+ class FeatureBooking(Booking):
+ __tablename__ = 'feature_booking'
+ id = Column(Integer, ForeignKey(Booking.id),
+ primary_key=True)
+ plan_booking_id = Column(Integer,
+ ForeignKey(PlanBooking.id))
+
+ plan_booking = relationship(PlanBooking,
+ backref='feature_bookings')
+
+ assert FeatureBooking.__table__.c.plan_booking_id.\
+ references(PlanBooking.__table__.c.id)
+
+ assert FeatureBooking.__table__.c.id.\
+ references(Booking.__table__.c.id)
+
+
def test_single_colsonbase(self):
"""test single inheritance where all the columns are on the base
class."""
from sqlalchemy import MetaData, Integer, String, ForeignKey, func, util
from sqlalchemy.test.schema import Table, Column
from sqlalchemy.engine import default
-from sqlalchemy.orm import mapper, relationship, backref, create_session, class_mapper, configure_mappers, reconstructor, validates, aliased
-from sqlalchemy.orm import defer, deferred, synonym, attributes, column_property, composite, relationship, dynamic_loader, comparable_property,AttributeExtension
+from sqlalchemy.orm import mapper, relationship, backref, \
- create_session, class_mapper, compile_mappers, reconstructor, \
++ create_session, class_mapper, configure_mappers, reconstructor, \
+ validates, aliased, Mapper
+from sqlalchemy.orm import defer, deferred, synonym, attributes, \
+ column_property, composite, relationship, dynamic_loader, \
+ comparable_property, AttributeExtension
+from sqlalchemy.orm.instrumentation import ClassManager
from sqlalchemy.test.testing import eq_, AssertsCompiledSQL
from test.orm import _base, _fixtures
from sqlalchemy.test.assertsql import AllOf, CompiledSQL
mapper(Foo, addresses, inherits=User)
assert getattr(Foo().__class__, 'name').impl is not None
- @testing.resolve_artifact_names
- def test_extension_collection_frozen(self):
- class Foo(User):pass
- m = mapper(User, users)
- mapper(Order, orders)
- configure_mappers()
- mapper(Foo, addresses, inherits=User)
- ext_list = [AttributeExtension()]
- m.add_property('somename', column_property(users.c.name, extension=ext_list))
- m.add_property('orders', relationship(Order, extension=ext_list, backref='user'))
- assert len(ext_list) == 1
-
- assert Foo.orders.impl.extensions is User.orders.impl.extensions
- assert Foo.orders.impl.extensions is not ext_list
-
- configure_mappers()
- assert len(User.somename.impl.extensions) == 1
- assert len(Foo.somename.impl.extensions) == 1
- assert len(Foo.orders.impl.extensions) == 3
- assert len(User.orders.impl.extensions) == 3
-
@testing.resolve_artifact_names
- def test_compile_on_get_props_1(self):
+ def test_configure_on_get_props_1(self):
m =mapper(User, users)
- assert not m.compiled
+ assert not m.configured
assert list(m.iterate_properties)
- assert m.compiled
+ assert m.configured
@testing.resolve_artifact_names
- def test_compile_on_get_props_2(self):
+ def test_configure_on_get_props_2(self):
m= mapper(User, users)
- assert not m.compiled
+ assert not m.configured
assert m.get_property('name')
- assert m.compiled
+ assert m.configured
+
+ @testing.resolve_artifact_names
+ def test_configure_on_get_props_3(self):
+ m= mapper(User, users)
+ assert not m.configured
+ configure_mappers()
+
+ m2 = mapper(Address, addresses, properties={
+ 'user':relationship(User, backref='addresses')
+ })
+ assert m.get_property('addresses')
@testing.resolve_artifact_names
def test_add_property(self):
backref=backref('foo',doc='foo relationship')
),
'foober':column_property(t1.c.col3, doc='alternate data col'),
- 'hoho':synonym(t1.c.col4, doc="syn of col4")
+ 'hoho':synonym("col4", doc="syn of col4")
})
mapper(Bar, t2)
- compile_mappers()
+ configure_mappers()
eq_(Foo.col1.__doc__, "primary key column")
eq_(Foo.col2.__doc__, "data col")
eq_(Foo.col5.__doc__, None)