"""MySQL connector.""" from contextlib import contextmanager from sqlalchemy import create_engine from sqlalchemy.exc import SQLAlchemyError from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import NullPool from contracts import config if config.ENVIRONMENT == config.TEST_ENVIRONMENT: # For the test environment the database used is an in-memory sqlite db. # This db gets dropped immediately after the execution of the tests. _db_engine = create_engine('sqlite://') else: _db_engine = create_engine(config.DB_URL, poolclass=NullPool) BaseModel = declarative_base() # A session() instance establishes all conversations with the database # and represents a "staging zone" for all the objects loaded into the # database session object. Any change made against the objects in the # session won't be persisted into the database until you call # session.commit(). If you're not happy about the changes, you can # revert all of them back to the last commit by calling # session.rollback() # # Description taken from: # pythoncentral.io/introductory-tutorial-python-sqlalchemy/ _db_session = sessionmaker(bind=_db_engine) @contextmanager def db_session(expire_on_commit=True): """Provide transactional scope. Taken from http://docs.sqlalchemy.org/en/latest/orm/session_basics.html. Handles commit, rollback, and closing of sessions. Usage: with session_scope() as session: session.execute(query) """ session = _db_session(expire_on_commit=expire_on_commit) try: yield session session.commit() except SQLAlchemyError: session.rollback() raise finally: session.close()