# coding: utf-8

import logging
import re
from itertools import chain
from textwrap import TextWrapper

from django.core import mail
from django.test import TestCase as DjangoTestCase
from django.views import debug
from six import string_types
from six.moves.urllib.parse import urlparse, urlunparse
from threadlocals.threadlocals import set_thread_variable

from .celery import app as celery_app

# patch the default formatter to use a unicode format string
logging._defaultFormatter = logging.Formatter("%(message)s")
logger = logging.getLogger(__name__)
HIDDEN_SETTING = re.compile(r"URL|BACKEND")


class TestCase(DjangoTestCase):
    """
    Overrides the default Django TestCase to clear out the threadlocal request
    variable during class setUp and tearDown.
    """

    @classmethod
    def setUpClass(cls):
        super(TestCase, cls).setUpClass()
        set_thread_variable("request", None)

    @classmethod
    def tearDownClass(cls):
        set_thread_variable("request", None)
        super(TestCase, cls).tearDownClass()

    def setUp(self):
        super(TestCase, self).setUp()
        set_thread_variable("request", None)

    def tearDown(self):
        set_thread_variable("request", None)
        super(TestCase, self).tearDown()


def monkey_patch_cleanse_setting():
    # monkey-patch django.views.debug.cleanse_setting to check for CELERY_RESULT_BACKEND
    _cleanse_setting = debug.cleanse_setting

    def cleanse_setting(key, value):
        cleansed = _cleanse_setting(key, value)
        if HIDDEN_SETTING.search(key):
            try:
                parsed = None
                if isinstance(value, string_types):
                    parsed = urlparse(value)
                if parsed and parsed.password:
                    # urlparse returns a read-only tuple, use a list to rewrite parts
                    parsed_list = list(parsed)
                    parsed_list[1] = parsed.netloc.replace(
                        f":{parsed.password}", ":**********", 1
                    )
                    # put Humpty Dumpty back together again
                    cleansed = urlunparse(parsed_list)
            except Exception:
                logger.exception("Exception cleansing URLs for error reporting")
        return cleansed

    debug.cleanse_setting = cleanse_setting


def monkey_patch_mail_admins():
    # monkey-patch django.core.mail.mail_admins to properly wrap long lines
    _mail_admins = mail.mail_admins

    def mail_admins(subject, message, *args, **kwargs):
        """
        Wraps the mail_admins function from Django to wrap long lines in emails.
        The exim mail server used in EDD dis-allows lines longer than 998 bytes.
        """
        wrapper = TextWrapper(
            width=79,
            break_on_hyphens=False,
            replace_whitespace=False,
            subsequent_indent="  ",
        )
        message = "\n".join(
            chain(*(wrapper.wrap(line) for line in message.splitlines()))
        )
        _mail_admins(subject, message, *args, **kwargs)

    mail.mail_admins = mail_admins


monkey_patch_cleanse_setting()
monkey_patch_mail_admins()


__all__ = ("celery_app", "TestCase")

# coding: utf-8

import logging
import re
from itertools import chain
from textwrap import TextWrapper

from django.core import mail
from django.test import TestCase as DjangoTestCase
from django.views import debug
from six import string_types
from six.moves.urllib.parse import urlparse, urlunparse
from threadlocals.threadlocals import set_thread_variable

from .celery import app as celery_app

# patch the default formatter to use a unicode format string
logging._defaultFormatter = logging.Formatter("%(message)s")
logger = logging.getLogger(__name__)
HIDDEN_SETTING = re.compile(r"URL|BACKEND")


class TestCase(DjangoTestCase):
    """
    Overrides the default Django TestCase to clear out the threadlocal request
    variable during class setUp and tearDown.
    """

    @classmethod
    def setUpClass(cls):
        super(TestCase, cls).setUpClass()
        set_thread_variable("request", None)

    @classmethod
    def tearDownClass(cls):
        set_thread_variable("request", None)
        super(TestCase, cls).tearDownClass()

    def setUp(self):
        super(TestCase, self).setUp()
        set_thread_variable("request", None)

    def tearDown(self):
        set_thread_variable("request", None)
        super(TestCase, self).tearDown()


def monkey_patch_cleanse_setting():
    # monkey-patch django.views.debug.cleanse_setting to check for CELERY_RESULT_BACKEND
    _cleanse_setting = debug.cleanse_setting

    def cleanse_setting(key, value):
        cleansed = _cleanse_setting(key, value)
        if HIDDEN_SETTING.search(key):
            try:
                parsed = None
                if isinstance(value, string_types):
                    parsed = urlparse(value)
                if parsed and parsed.password:
                    # urlparse returns a read-only tuple, use a list to rewrite parts
                    parsed_list = list(parsed)
                    parsed_list[1] = parsed.netloc.replace(
                        f":{parsed.password}", ":**********", 1
                    )
                    # put Humpty Dumpty back together again
                    cleansed = urlunparse(parsed_list)
            except Exception:
                logger.exception("Exception cleansing URLs for error reporting")
        return cleansed

    debug.cleanse_setting = cleanse_setting


def monkey_patch_mail_admins():
    # monkey-patch django.core.mail.mail_admins to properly wrap long lines
    _mail_admins = mail.mail_admins

    def mail_admins(subject, message, *args, **kwargs):
        """
        Wraps the mail_admins function from Django to wrap long lines in emails.
        The exim mail server used in EDD dis-allows lines longer than 998 bytes.
        """
        wrapper = TextWrapper(
            width=79,
            break_on_hyphens=False,
            replace_whitespace=False,
            subsequent_indent="  ",
        )
        message = "\n".join(
            chain(*(wrapper.wrap(line) for line in message.splitlines()))
        )
        _mail_admins(subject, message, *args, **kwargs)

    mail.mail_admins = mail_admins


monkey_patch_cleanse_setting()
monkey_patch_mail_admins()


__all__ = ("celery_app", "TestCase")

# coding: utf-8 # patch the default formatter to use a unicode format string Overrides the default Django TestCase to clear out the threadlocal request     variable during class setUp and tearDown. # monkey-patch django.views.debug.cleanse_setting to check for CELERY_RESULT_BACKEND # urlparse returns a read-only tuple, use a list to rewrite parts # put Humpty Dumpty back together again # monkey-patch django.core.mail.mail_admins to properly wrap long lines Wraps the mail_admins function from Django to wrap long lines in emails.         The exim mail server used in EDD dis-allows lines longer than 998 bytes.