]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- merge mapper simpler compile branch, [ticket:1966]
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 26 Nov 2010 21:28:41 +0000 (16:28 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 26 Nov 2010 21:28:41 +0000 (16:28 -0500)
12 files changed:
1  2 
lib/sqlalchemy/orm/__init__.py
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/properties.py
lib/sqlalchemy/orm/state.py
lib/sqlalchemy/orm/util.py
lib/sqlalchemy/util.py
test/ext/test_declarative.py
test/orm/inheritance/test_basic.py
test/orm/test_mapper.py
test/orm/test_query.py
test/orm/test_relationships.py
test/orm/test_unitofwork.py

Simple merge
index 32eb8f64333eac9b26072519970bd5c47dcdee9d,ee41be00b0d774a82a73008bb17805837e8ab342..0721f7376ed56c0be5e476d72be320f011bbcdf8
@@@ -46,8 -46,11 +46,8 @@@ _new_mappers = Fals
  _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
@@@ -412,14 -412,36 +412,31 @@@ class Mapper(object)
                      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()')
@@@ -2395,30 -2411,35 +2413,30 @@@ def validates(*names)
          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):
Simple merge
index 3e977a4c9cf360d59acc682fa18f8c85f3c41660,4e67f934c70827b83d36ef1fd493341be5bed945..059788bac1ad02a99d30a3d04f2e214ec4eb9a83
@@@ -8,12 -1,13 +8,14 @@@ defines a large part of the ORM's inter
  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', {})
Simple merge
Simple merge
index 88fd5b976365d7e9b8359d0c71b1a0f89bf53e0b,45d01ba7403147b7036890eb8013801ed7e4586c..32173cdc1c2a609e832087328222161ca6e07efc
@@@ -299,38 -299,6 +299,38 @@@ class DeclarativeTest(DeclarativeTestBa
          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):
@@@ -1469,43 -1430,8 +1469,43 @@@ class DeclarativeInheritanceTest(Declar
              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."""
Simple merge
index 8360d54bfab9e8dd4d15fd5a0f4055f2e28f68dc,eabb710ff9297a66f5637a9a23cd30bbc91868fe..7d12a8bab51af5ee9cd63a1b107c2fc02e587c17
@@@ -6,13 -6,8 +6,13 @@@ from sqlalchemy.test import testing, pi
  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
@@@ -230,20 -269,52 +231,31 @@@ class MapperTest(_fixtures.FixtureTest)
          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):
@@@ -1183,10 -1249,10 +1196,10 @@@ class DocumentTest(testing.TestBase)
                                      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)
Simple merge
Simple merge
Simple merge