# Buggy code
def new_session_factory(
    url="sqlite:///:memory:", reset=False, expire_on_commit=False, **kwargs
):
    """Create a new session at url"""
    if url.startswith("sqlite"):
        kwargs.setdefault("connect_args", {"check_same_thread": False})
        listeners = kwargs.setdefault("listeners", [])
        listeners.append(ForeignKeysListener())

    elif url.startswith("mysql"):
        kwargs.setdefault("pool_recycle", 60)

    if url.endswith(":memory:"):
        # If we're using an in-memory database, ensure that only one connection
        # is ever created.
        kwargs.setdefault("poolclass", StaticPool)

    engine = create_engine(url, **kwargs)
    if reset:
        Base.metadata.drop_all(engine)

    if mysql_large_prefix_check(engine):  # if mysql is allows large indexes
        add_row_format(Base)  # set format on the tables
    # check the db revision (will raise, pointing to `upgrade-db` if version doesn't match)
    check_db_revision(engine)

    Base.metadata.create_all(engine)

    # We set expire_on_commit=False, since we don't actually need
    # SQLAlchemy to expire objects after commiting - we don't expect
    # concurrent runs of the hub talking to the same db. Turning
    # this off gives us a major performance boost
    session_factory = sessionmaker(
        bind=engine,
        expire_on_commit=expire_on_commit,
    )
    return session_factory


# Traceback (sqlalchemy.exc.StatementError)
[E 2018-01-19 04:14:19.920 JupyterHub web:1518] Exception in exception handler
Traceback (most recent call last):
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 1516, in _execute
self._handle_request_exception(e)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 1570, in _handle_request_exception
self.send_error(500, exc_info=sys.exc_info())
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 1040, in send_error
self.finish()
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/jupyterhub/handlers/base.py", line 105, in finish
super().finish(*args, **kwargs)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 993, in finish
self._log()
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 1540, in _log
self.application.log_request(self)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/tornado/web.py", line 2053, in log_request
self.settings["log_function"](handler)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/jupyterhub/log.py", line 90, in log_request
user = handler.get_current_user()
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/jupyterhub/handlers/base.py", line 229, in get_current_user
return self.get_current_user_cookie()
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/jupyterhub/handlers/base.py", line 222, in get_current_user_cookie
return self._user_for_cookie(self.hub.cookie_name)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/jupyterhub/handlers/base.py", line 206, in _user_for_cookie
u = self.db.query(orm.User).filter(orm.User.cookie_id==cookie_id).first()
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2755, in first
ret = list(self[0:1])
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2547, in __getitem__
return list(res)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2855, in __iter__
return self._execute_and_instances(context)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 2878, in _execute_and_instances
result = conn.execute(querycontext.statement, self._params)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 945, in execute
return meth(self, multiparams, params)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 263, in _execute_on_connection
return connection._execute_clauseelement(self, multiparams, params)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement
compiled_sql, distilled_params
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1121, in _execute_context
None, None)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1402, in _handle_dbapi_exception
exc_info
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 203, in raise_from_cause
reraise(type(exception), exception, tb=exc_tb, cause=cause)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 186, in reraise
raise value.with_traceback(tb)
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1114, in _execute_context
conn = self._revalidate_connection()
File "/Users/bhatt/anaconda3/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 424, in _revalidate_connection
"Can't reconnect until invalid "
sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) Can't reconnect until invalid transaction is rolled back [SQL: 'SELECT users.id AS users_id, users.name AS users_name, users.`admin` AS users_admin, users.last_activity AS users_last_activity, users.cookie_id AS users_cookie_id, users.state AS users_state, users.encrypted_auth_state AS users_encrypted_auth_state \nFROM users \nWHERE users.cookie_id = %(cookie_id_1)s \n LIMIT %(param_1)s'] [parameters: [{}]]

# Fixed code
def new_session_factory(
    url="sqlite:///:memory:", reset=False, expire_on_commit=False, **kwargs
):
    """Create a new session at url"""
    if url.startswith("sqlite"):
        kwargs.setdefault("connect_args", {"check_same_thread": False})
        listeners = kwargs.setdefault("listeners", [])
        listeners.append(ForeignKeysListener())

    elif url.startswith("mysql"):
        kwargs.setdefault("pool_recycle", 60)

    if url.endswith(":memory:"):
        # If we're using an in-memory database, ensure that only one connection
        # is ever created.
        kwargs.setdefault("poolclass", StaticPool)

    engine = create_engine(url, **kwargs)
    # enable pessimistic disconnect handling
    register_ping_connection(engine)

    if reset:
        Base.metadata.drop_all(engine)

    if mysql_large_prefix_check(engine):  # if mysql is allows large indexes
        add_row_format(Base)  # set format on the tables
    # check the db revision (will raise, pointing to `upgrade-db` if version doesn't match)
    check_db_revision(engine)

    Base.metadata.create_all(engine)

    # We set expire_on_commit=False, since we don't actually need
    # SQLAlchemy to expire objects after commiting - we don't expect
    # concurrent runs of the hub talking to the same db. Turning
    # this off gives us a major performance boost
    session_factory = sessionmaker(
        bind=engine,
        expire_on_commit=expire_on_commit,
    )
    return session_factory