- Fixed session.transaction.commit() on a autocommit=False
session not starting a new transaction.
+
+ - Some adjustments to Session.identity_map's weak referencing
+ behavior to reduce asynchronous GC side effects.
+
- sql
- column.in_(someselect) can now be used as a columns-clause
expression without the subquery bleeding into the FROM clause
class IdentityMap(dict):
def __init__(self):
- self._mutable_attrs = weakref.WeakKeyDictionary()
+ self._mutable_attrs = {}
self.modified = False
def add(self, state):
"""return True if any InstanceStates present have been marked as 'modified'."""
if not self.modified:
- for state in self._mutable_attrs:
+ for state in list(self._mutable_attrs):
if state.check_modified():
return True
else:
import testenv; testenv.configure_for_tests()
import gc
-from sqlalchemy.orm import mapper, relation, create_session, clear_mappers
+from sqlalchemy.orm import mapper, relation, create_session, clear_mappers, sessionmaker
from sqlalchemy.orm.mapper import _mapper_registry
from sqlalchemy.orm.session import _sessions
-
+import operator
from testlib import testing
-from testlib.sa import MetaData, Table, Column, Integer, String, ForeignKey
+from testlib.sa import MetaData, Table, Column, Integer, String, ForeignKey, PickleType
from orm import _base
metadata.drop_all()
assert_no_mappers()
+ def test_mutable_identity(self):
+ metadata = MetaData(testing.db)
+ table1 = Table("mytable", metadata,
+ Column('col1', Integer, primary_key=True),
+ Column('col2', PickleType(comparator=operator.eq))
+ )
+
+ class Foo(object):
+ def __init__(self, col2):
+ self.col2 = col2
+
+ mapper(Foo, table1)
+ metadata.create_all()
+
+ session = sessionmaker()()
+
+ def go():
+ obj = [
+ Foo({'a':1}),
+ Foo({'b':1}),
+ Foo({'c':1}),
+ Foo({'d':1}),
+ Foo({'e':1}),
+ Foo({'f':1}),
+ Foo({'g':1}),
+ Foo({'h':1}),
+ Foo({'i':1}),
+ Foo({'j':1}),
+ Foo({'k':1}),
+ Foo({'l':1}),
+ ]
+
+ session.add_all(obj)
+ session.commit()
+
+ testing.eq_(len(session.identity_map._mutable_attrs), 12)
+ testing.eq_(len(session.identity_map), 12)
+ obj = None
+ gc.collect()
+ testing.eq_(len(session.identity_map._mutable_attrs), 0)
+ testing.eq_(len(session.identity_map), 0)
+
+ try:
+ go()
+ finally:
+ metadata.drop_all()
+
if __name__ == '__main__':
testenv.main()