I'm experiencing some problems with alembic's stamp command and using sqlite in-memory databases for testing. Tests that work perfectly with file-based sqlite dbs fail with OperationalError: (OperationalError) no such table
.
I'm stamping during initialisation to show the database is up-to-date:
def init_db(engine, version):
tables.Base.metadata.create_all(engine)
with engine.begin() as connection:
stamp_alembic(connection)
def stamp_alembic(connection):
from alembic import command
from alembic.config import Config
alembic_cfg = Config('alembic.ini')
alembic_cfg.attributes['connection'] = connection
command.stamp(alembic_cfg, 'head')
I'm passing the current connection to env.py
as per the cookbook:
def run_migrations_online():
connectable = config.attributes.get('connection', None)
if connectable is None:
# only create Engine if we don't have a Connection
# from the outside
connectable = engine_from_config(
config.get_section(config.config_ini_section),
prefix='sqlalchemy.',
poolclass=pool.NullPool
)
with connectable.connect() as connection:
context.configure(
connection=connection,
target_metadata=target_metadata
)
with context.begin_transaction():
context.run_migrations()
My test class:
SETTINGS = {'sqlalchemy.url': 'sqlite:///:memory:'}
class TestOperatorUserModel(unittest.TestCase):
def setUp(self):
engine = engine_from_config(SETTINGS, 'sqlalchemy.')
tables.DBSession.configure(bind=engine)
init_db(engine, SETTINGS['version.db'])
transaction.begin()
def tearDown(self):
engine = engine_from_config(SETTINGS, 'sqlalchemy.')
transaction.abort()
tables.Base.metadata.drop_all(engine)
tables.DBSession.remove()
If I remove the stamp call from initialisation, the tests also run fine. As a workaround, I'm only stamping the db if engine.url.database
isn't ':memory:'
, but I'd ideally like to know what is the real source of the issue.
Environment is Python 2.7.11, SQLAlchemy 0.9.10, alembic 0.8.6 and sqlite 2.8.17.