Using "configure" on scoped_session does not bind engine properly
See original GitHub issueMigrated issue, originally created by Adam Olsen (@synic)
Using SQLAlchemy 1.1.9 (though it happened with 1.1.8 too) with Python 2.7.13 on OS X
Using scoped_session.configure
to change the engine doesn’t bind the engine properly. For instance, if you do something like this:
session = orm.scoped_session(orm.sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
session.close_all()
engine = create_engine('postgresql://someuser:somepass@localhost:5432/db',
json_serializer=serialize, json_deserializer=deserialize)
session.configure(bind=engine)
print session.bind # will output `Engine(sqlite://)`
It results in errors such as the one you see below (if you start with sqlite, but then switch to postgres and try to query tables).
If you’re wondering WHY we would want to do this, it is for testing. Our test suite tries to make sure that everything works ok with both sqlite and postgresql. We can’t just create a new instance of the scoped_session, as it will break the factories and various other places that call for a session at load time (we could probably find some way to make it work with two different sessions, but I don’t want to do that unless I have to).
Traceback (most recent call last):
File "/vagrant/apps/skedup/tests/base.py", line 28, in setUp
db.session.commit()
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/scoping.py", line 157, in do
return getattr(self.registry(), name)(*args, **kwargs)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 874, in commit
self.transaction.commit()
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 459, in commit
self._assert_active(prepared_ok=True)
File "/usr/local/lib/python2.7/site-packages/sqlalchemy/orm/session.py", line 276, in _assert_active
% self._rollback_exception
InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction with this Session, first issue Session.rollback(). Original exception was: (exceptions.AttributeError) 'SQLiteDialect_pysqlite' object has no attribute '_json_serializer'
Doing something like this totally fixes it (manually assigning the engine to session.bind
), but it seems like it shouldn’t be required:
session = orm.scoped_session(orm.sessionmaker())
engine = create_engine('sqlite://')
session.configure(bind=engine)
session.close_all()
engine = create_engine('postgresql://someuser:somepass@localhost:5432/db',
json_serializer=serialize, json_deserializer=deserialize)
session.configure(bind=engine)
session.bind = engine # <---- this is the key to making it work
print session.bind # will output `Engine(postgresql://someuser:somepass@localhost:5432/db)`
Issue Analytics
- State:
- Created 6 years ago
- Comments:6
Michael Bayer (@zzzeek) wrote:
Your test as written does produce the correct output, because you are not actually instantiating the session:
output:
the issue you’re having is that you are instantiating a session first, then changing the “bind” on the
sessionmaker
that produces a new session:in the output, there is in fact a handy warning as well telling you as much:
the solution is to remove the session that’s instantiated:
assuming things are the same on your end, there’s no bug here, please confirm thanks!
Changes by Adam Olsen (@synic):