"""MySQL Connector. Manages interactions with MySQL for podcast RDS databse. """ from contextlib import contextmanager from sqlalchemy import create_engine from sqlalchemy import pool from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import scoped_session from sqlalchemy.orm import sessionmaker from podcast import config from podcast.api import app def _create_engine(db_url): """Create engine based on config settings.""" if config.POOL_CLASS == pool.QueuePool and config.ENVIRONMENT: return create_engine( db_url, pool_size=config.POOL_SIZE, max_overflow=config.POOL_MAX_OVERFLOW, pool_recycle=config.POOL_RECYCLE_MS) return create_engine(db_url, poolclass=config.POOL_CLASS) podcast_db_engine = _create_engine(config.PODCAST_DB_URL) podcast_session_factory = sessionmaker(bind=podcast_db_engine) podcast_db_session = scoped_session(podcast_session_factory) sessions = (podcast_db_session, ) BaseModel = declarative_base() @app.teardown_request def remove_session(exception): """For scoped_session, explicitly close session at end of each request. Args: exception (object): When a teardown function was called because of an exception it will be passed an error object. """ for session in sessions: session.remove() @contextmanager def pod_db_session(read_only=False): """Provide transactional scope around series of operations for ows_podcast. Taken from http://docs.sqlalchemy.org/en/latest/orm/session_basics.html. This handles rollback and closing of session, so there is no need to do that throughout the code. Usage: with podcast_database_session() as session: session.execute(query) """ session = podcast_db_session() try: yield session if not read_only: session.commit() except Exception: session.rollback() raise