# Path: pypi_portal/core/email.py
# def send_exception(subject):
#     """Send Python exception tracebacks via email to the ADMINS list.
# 
#     Use the same HTML styling as Flask tracebacks in debug web servers.
# 
#     This function must be called while the exception is happening. It picks up the raised exception with sys.exc_info().
# 
#     Positional arguments:
#     subject -- subject line of the email (to be prepended by 'Application Error: ').
#     """
#     # Generate and modify html.
#     tb = tbtools.get_current_traceback()  # Get exception information.
#     with _override_html():
#         html = tb.render_full().encode('utf-8', 'replace')
#     html = html.replace('<blockquote>', '<blockquote style="margin: 1em 0 0; padding: 0;">')
#     subject = 'Application Error: {}'.format(subject)
# 
#     # Apply throttle.
#     md5 = hashlib.md5('{}{}'.format(subject, html)).hexdigest()
#     seconds = int(current_app.config['MAIL_EXCEPTION_THROTTLE'])
#     lock = redis.lock(EMAIL_THROTTLE.format(md5=md5), timeout=seconds)
#     have_lock = lock.acquire(blocking=False)
#     if not have_lock:
#         LOG.debug('Suppressing email: {}'.format(subject))
#         return
# 
#     # Send email.
#     msg = Message(subject=subject, recipients=current_app.config['ADMINS'], html=html)
#     mail.send(msg)
# 
# Path: pypi_portal/extensions.py
# LOG = getLogger(__name__)
# def _on_connect(dbapi_connection, **_):


import locale
import os
from logging import getLogger
from celery.signals import task_failure, worker_process_init
from flask import current_app, render_template, request
from markupsafe import Markup
from pypi_portal.core.email import send_exception
from pypi_portal.extensions import db
"""Flask middleware definitions. This is also where template filters are defined.

To be imported by the application.current_app() factory.
"""




LOG = getLogger(__name__)


# Fix Flask-SQLAlchemy and Celery incompatibilities.
@worker_process_init.connect
def celery_worker_init_db(**_):
    """Initialize SQLAlchemy right after the Celery worker process forks.

    This ensures each Celery worker has its own dedicated connection to the MySQL database. Otherwise
    one worker may close the connection while another worker is using it, raising exceptions.

    Without this, the existing session to the MySQL server is cloned to all Celery workers, so they
    all share a single session. A SQLAlchemy session is not thread/concurrency-safe, causing weird
    exceptions to be raised by workers.

    Based on http://stackoverflow.com/a/14146403/1198943
    """
    LOG.debug('Initializing SQLAlchemy for PID {}.'.format(os.getpid()))

# Path: pypi_portal/core/email.py
# def send_exception(subject):
#     """Send Python exception tracebacks via email to the ADMINS list.
# 
#     Use the same HTML styling as Flask tracebacks in debug web servers.
# 
#     This function must be called while the exception is happening. It picks up the raised exception with sys.exc_info().
# 
#     Positional arguments:
#     subject -- subject line of the email (to be prepended by 'Application Error: ').
#     """
#     # Generate and modify html.
#     tb = tbtools.get_current_traceback()  # Get exception information.
#     with _override_html():
#         html = tb.render_full().encode('utf-8', 'replace')
#     html = html.replace('<blockquote>', '<blockquote style="margin: 1em 0 0; padding: 0;">')
#     subject = 'Application Error: {}'.format(subject)
# 
#     # Apply throttle.
#     md5 = hashlib.md5('{}{}'.format(subject, html)).hexdigest()
#     seconds = int(current_app.config['MAIL_EXCEPTION_THROTTLE'])
#     lock = redis.lock(EMAIL_THROTTLE.format(md5=md5), timeout=seconds)
#     have_lock = lock.acquire(blocking=False)
#     if not have_lock:
#         LOG.debug('Suppressing email: {}'.format(subject))
#         return
# 
#     # Send email.
#     msg = Message(subject=subject, recipients=current_app.config['ADMINS'], html=html)
#     mail.send(msg)
# 
# Path: pypi_portal/extensions.py
# LOG = getLogger(__name__)
# def _on_connect(dbapi_connection, **_):


# Path: pypi_portal/middleware.py
import locale
import os
from logging import getLogger
from celery.signals import task_failure, worker_process_init
from flask import current_app, render_template, request
from markupsafe import Markup
from pypi_portal.core.email import send_exception
from pypi_portal.extensions import db

"""Flask middleware definitions. This is also where template filters are defined.

To be imported by the application.current_app() factory.
"""




LOG = getLogger(__name__)


# Fix Flask-SQLAlchemy and Celery incompatibilities.
@worker_process_init.connect
def celery_worker_init_db(**_):
    """Initialize SQLAlchemy right after the Celery worker process forks.

    This ensures each Celery worker has its own dedicated connection to the MySQL database. Otherwise
    one worker may close the connection while another worker is using it, raising exceptions.

    Without this, the existing session to the MySQL server is cloned to all Celery workers, so they
    all share a single session. A SQLAlchemy session is not thread/concurrency-safe, causing weird
    exceptions to be raised by workers.

    Based on http://stackoverflow.com/a/14146403/1198943
    """
    LOG.debug('Initializing SQLAlchemy for PID {}.'.format(os.getpid()))

    db.init_app(current_app)