- proper error message is raised when trying to access
expired instance attributes with no session present
+ - dynamic relations, when referenced, create a strong
+ reference to the parent object so that the query
+ still has a parent to call against even if the
+ parent is only created (and otherwise dereferenced)
+ within the scope of a single expression [ticket:938]
+
- added a mapper() flag "eager_defaults"; when set to
True, defaults that are generated during an INSERT or
UPDATE operation are post-fetched immediately, instead
class AppenderQuery(Query):
def __init__(self, attr, state):
super(AppenderQuery, self).__init__(attr.target_mapper, None)
- self.state = state
+ self.instance = state.obj()
self.attr = attr
def __session(self):
- instance = self.state.obj()
- sess = object_session(instance)
- if sess is not None and self.autoflush and sess.autoflush and instance in sess:
+ sess = object_session(self.instance)
+ if sess is not None and self.autoflush and sess.autoflush and self.instance in sess:
sess.flush()
- if not has_identity(instance):
+ if not has_identity(self.instance):
return None
else:
return sess
def __iter__(self):
sess = self.__session()
if sess is None:
- return iter(self.attr._get_collection(self.state, passive=True).added_items)
+ return iter(self.attr._get_collection(self.instance._state, passive=True).added_items)
else:
return iter(self._clone(sess))
def __getitem__(self, index):
sess = self.__session()
if sess is None:
- return self.attr._get_collection(self.state, passive=True).added_items.__getitem__(index)
+ return self.attr._get_collection(self.instance._state, passive=True).added_items.__getitem__(index)
else:
return self._clone(sess).__getitem__(index)
def count(self):
sess = self.__session()
if sess is None:
- return len(self.attr._get_collection(self.state, passive=True).added_items)
+ return len(self.attr._get_collection(self.instance._state, passive=True).added_items)
else:
return self._clone(sess).count()
# note we're returning an entirely new Query class instance here
# without any assignment capabilities;
# the class of this query is determined by the session.
- instance = self.state.obj()
+ instance = self.instance
if sess is None:
sess = object_session(instance)
if sess is None:
return sess.query(self.attr.target_mapper).with_parent(instance, self.attr.key)
def assign(self, collection):
- instance = self.state.obj()
+ instance = self.instance
if has_identity(instance):
oldlist = list(self)
else:
oldlist = []
- self.attr._get_collection(self.state, passive=True).replace(oldlist, collection)
+ self.attr._get_collection(self.instance._state, passive=True).replace(oldlist, collection)
return oldlist
def append(self, item):
- self.attr.append(self.state, item, None)
+ self.attr.append(self.instance._state, item, None)
def remove(self, item):
- self.attr.remove(self.state, item, None)
+ self.attr.remove(self.instance._state, item, None)
class CollectionHistory(object):
for saveuser in (False, True):
create_backref_test(autoflush, saveuser)
+class DontDereferenceTest(ORMTest):
+ def define_tables(self, metadata):
+ global users_table, addresses_table
+
+ users_table = Table('users', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('name', String(40)),
+ Column('fullname', String(100)),
+ Column('password', String(15)))
+
+ addresses_table = Table('addresses', metadata,
+ Column('id', Integer, primary_key=True),
+ Column('email_address', String(100), nullable=False),
+ Column('user_id', Integer, ForeignKey('users.id')))
+ def test_no_deref(self):
+ mapper(User, users_table, properties={
+ 'addresses': relation(Address, backref='user', lazy='dynamic')
+ })
+
+ mapper(Address, addresses_table)
+
+ session = create_session()
+ user = User()
+ user.name = 'joe'
+ user.fullname = 'Joe User'
+ user.password = 'Joe\'s secret'
+ address = Address()
+ address.email_address = 'joe@joesdomain.example'
+ address.user = user
+ session.save(user)
+ session.flush()
+ session.clear()
+
+ def query1():
+ session = create_session(metadata.bind)
+ user = session.query(User).first()
+ return user.addresses.all()
+
+ def query2():
+ session = create_session(metadata.bind)
+ return session.query(User).first().addresses.all()
+
+ def query3():
+ session = create_session(metadata.bind)
+ user = session.query(User).first()
+ return session.query(User).first().addresses.all()
+
+ self.assertEquals(query1(), [Address(email_address='joe@joesdomain.example')] )
+ self.assertEquals(query2(), [Address(email_address='joe@joesdomain.example')] )
+ self.assertEquals(query3(), [Address(email_address='joe@joesdomain.example')] )
+
+
if __name__ == '__main__':
testenv.main()