Ticket #15561: 15561.2.diff

File 15561.2.diff, 12.2 KB (added by Jannis Leidel, 13 years ago)

with_settings decorator/context manager combo

  • django/test/testcases.py

    diff --git a/django/test/testcases.py b/django/test/testcases.py
    index d85bc27..4597034 100644
    a b from __future__ import with_statement  
    22
    33import re
    44import sys
    5 from contextlib import contextmanager
    65from functools import wraps
    76from urlparse import urlsplit, urlunsplit
    87from xml.dom.minidom import parseString, Node
    from django.db import (transaction, connection, connections, DEFAULT_DB_ALIAS,  
    1716from django.http import QueryDict
    1817from django.test import _doctest as doctest
    1918from django.test.client import Client
    20 from django.test.utils import get_warnings_state, restore_warnings_state
     19from django.test.utils import get_warnings_state, restore_warnings_state, with_settings
    2120from django.utils import simplejson, unittest as ut2
    2221from django.utils.encoding import smart_str
    2322
    class TransactionTestCase(ut2.TestCase):  
    342341        """
    343342        restore_warnings_state(self._warnings_state)
    344343
    345     @contextmanager
    346     def settings(self, **options):
     344    def settings(self, **kwargs):
    347345        """
    348346        A context manager that temporarily sets a setting and reverts
    349347        back to the original value when exiting the context.
    350348        """
    351         old_wrapped = settings._wrapped
    352         override = UserSettingsHolder(settings._wrapped)
    353         try:
    354             for key, new_value in options.items():
    355                 setattr(override, key, new_value)
    356             settings._wrapped = override
    357             yield
    358         finally:
    359             settings._wrapped = old_wrapped
     349        return with_settings(**kwargs)
    360350
    361351    def assertRedirects(self, response, expected_url, status_code=302,
    362352                        target_status_code=200, host=None, msg_prefix=''):
  • django/test/utils.py

    diff --git a/django/test/utils.py b/django/test/utils.py
    index bf1dc4f..f4bb0a3 100644
    a b import sys  
    22import time
    33import os
    44import warnings
    5 from django.conf import settings
     5from django.conf import settings, UserSettingsHolder
    66from django.core import mail
    77from django.core.mail.backends import locmem
    88from django.test import signals
    99from django.template import Template, loader, TemplateDoesNotExist
    1010from django.template.loaders import cached
    1111from django.utils.translation import deactivate
     12from django.utils.functional import wraps
    1213
    13 __all__ = ('Approximate', 'ContextList', 'setup_test_environment',
    14        'teardown_test_environment', 'get_runner')
     14
     15__all__ = (
     16    'Approximate', 'ContextList',  'get_runner', 'with_settings',
     17    'setup_test_environment', 'teardown_test_environment',
     18    'setup_test_template_loader', 'restore_template_loaders',
     19)
    1520
    1621RESTORE_LOADERS_ATTR = '_original_template_source_loaders'
    1722
    def restore_template_loaders():  
    160165    """
    161166    loader.template_source_loaders = getattr(loader, RESTORE_LOADERS_ATTR)
    162167    delattr(loader, RESTORE_LOADERS_ATTR)
     168
     169
     170class with_settings(object):
     171    """
     172    Acts as either a decorator, or a context manager.  If it's a decorator it
     173    takes a function and returns a wrapped function.  If it's a contextmanager
     174    it's used with the ``with`` statement.  In either event entering/exiting
     175    are called before and after, respectively, the function/block is executed.
     176    """
     177
     178    def __init__(self, **kwargs):
     179        self.options = kwargs
     180        self.wrapped = settings._wrapped
     181
     182    def __enter__(self):
     183        self.enable()
     184
     185    def __exit__(self, exc_type, exc_value, traceback):
     186        self.disable()
     187
     188    def __call__(self, func):
     189        @wraps(func)
     190        def inner(*args, **kwargs):
     191            self.enable()
     192            result = func(*args, **kwargs)
     193            self.disable()
     194            return result
     195        return inner
     196
     197    def enable(self):
     198        override = UserSettingsHolder(settings._wrapped)
     199        for key, new_value in self.options.items():
     200            setattr(override, key, new_value)
     201        settings._wrapped = override
     202
     203    def disable(self):
     204        settings._wrapped = self.wrapped
  • tests/regressiontests/mail/tests.py

    diff --git a/tests/regressiontests/mail/tests.py b/tests/regressiontests/mail/tests.py
    index 706b3af..c4d727a 100644
    a b from StringIO import StringIO  
    99import tempfile
    1010import threading
    1111
    12 from django.conf import settings
    1312from django.core import mail
    1413from django.core.mail import (EmailMessage, mail_admins, mail_managers,
    1514        EmailMultiAlternatives, send_mail, send_mass_mail)
    1615from django.core.mail.backends import console, dummy, locmem, filebased, smtp
    1716from django.core.mail.message import BadHeaderError
    1817from django.test import TestCase
     18from django.test.utils import with_settings
    1919from django.utils.translation import ugettext_lazy
    20 from django.utils.functional import wraps
    21 
    22 
    23 def alter_django_settings(**kwargs):
    24     oldvalues = {}
    25     nonexistant = []
    26     for setting, newvalue in kwargs.iteritems():
    27         try:
    28             oldvalues[setting] = getattr(settings, setting)
    29         except AttributeError:
    30             nonexistant.append(setting)
    31         setattr(settings, setting, newvalue)
    32     return oldvalues, nonexistant
    33 
    34 
    35 def restore_django_settings(state):
    36     oldvalues, nonexistant = state
    37     for setting, oldvalue in oldvalues.iteritems():
    38         setattr(settings, setting, oldvalue)
    39     for setting in nonexistant:
    40         delattr(settings, setting)
    41 
    42 
    43 def with_django_settings(**kwargs):
    44     def decorator(test):
    45         @wraps(test)
    46         def decorated_test(self):
    47             state = alter_django_settings(**kwargs)
    48             try:
    49                 return test(self)
    50             finally:
    51                 restore_django_settings(state)
    52         return decorated_test
    53     return decorator
    5420
    5521
    5622class MailTests(TestCase):
    class MailTests(TestCase):  
    251217            shutil.rmtree(tmp_dir)
    252218        self.assertTrue(isinstance(mail.get_connection(), locmem.EmailBackend))
    253219
    254     @with_django_settings(
     220    @with_settings(
    255221        EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend',
    256222        ADMINS=[('nobody', 'nobody@example.com')],
    257223        MANAGERS=[('nobody', 'nobody@example.com')])
    class BaseEmailBackendTests(object):  
    323289    email_backend = None
    324290
    325291    def setUp(self):
    326         self.__settings_state = alter_django_settings(EMAIL_BACKEND=self.email_backend)
     292        self.settings_override = with_settings(EMAIL_BACKEND=self.email_backend)
     293        self.settings_override.enable()
    327294
    328295    def tearDown(self):
    329         restore_django_settings(self.__settings_state)
     296        self.settings_override.disable()
    330297
    331298    def assertStartsWith(self, first, second):
    332299        if not first.startswith(second):
    class BaseEmailBackendTests(object):  
    375342        self.assertEqual(message.get_payload(), "Content")
    376343        self.assertEqual(message["from"], "=?utf-8?q?Firstname_S=C3=BCrname?= <from@example.com>")
    377344
    378     @with_django_settings(MANAGERS=[('nobody', 'nobody@example.com')])
     345    @with_settings(MANAGERS=[('nobody', 'nobody@example.com')])
    379346    def test_html_mail_managers(self):
    380347        """Test html_message argument to mail_managers"""
    381348        mail_managers('Subject', 'Content', html_message='HTML Content')
    class BaseEmailBackendTests(object):  
    390357        self.assertEqual(message.get_payload(1).get_payload(), 'HTML Content')
    391358        self.assertEqual(message.get_payload(1).get_content_type(), 'text/html')
    392359
    393     @with_django_settings(ADMINS=[('nobody', 'nobody@example.com')])
     360    @with_settings(ADMINS=[('nobody', 'nobody@example.com')])
    394361    def test_html_mail_admins(self):
    395362        """Test html_message argument to mail_admins """
    396363        mail_admins('Subject', 'Content', html_message='HTML Content')
    class BaseEmailBackendTests(object):  
    405372        self.assertEqual(message.get_payload(1).get_payload(), 'HTML Content')
    406373        self.assertEqual(message.get_payload(1).get_content_type(), 'text/html')
    407374
    408     @with_django_settings(ADMINS=[('nobody', 'nobody+admin@example.com')],
    409                          MANAGERS=[('nobody', 'nobody+manager@example.com')])
     375    @with_settings(
     376        ADMINS=[('nobody', 'nobody+admin@example.com')],
     377        MANAGERS=[('nobody', 'nobody+manager@example.com')])
    410378    def test_manager_and_admin_mail_prefix(self):
    411379        """
    412380        String prefix + lazy translated subject = bad output
    class BaseEmailBackendTests(object):  
    421389        message = self.get_the_message()
    422390        self.assertEqual(message.get('subject'), '[Django] Subject')
    423391
    424     @with_django_settings(ADMINS=(), MANAGERS=())
     392    @with_settings(ADMINS=(), MANAGERS=())
    425393    def test_empty_admins(self):
    426394        """
    427395        Test that mail_admins/mail_managers doesn't connect to the mail server
    class FileBackendTests(BaseEmailBackendTests, TestCase):  
    501469    email_backend = 'django.core.mail.backends.filebased.EmailBackend'
    502470
    503471    def setUp(self):
    504         super(FileBackendTests, self).setUp()
    505472        self.tmp_dir = tempfile.mkdtemp()
    506         self.__settings_state = alter_django_settings(EMAIL_FILE_PATH=self.tmp_dir)
     473        self.addCleanup(shutil.rmtree, self.tmp_dir)
     474        self.settings_override = with_settings(EMAIL_FILE_PATH=self.tmp_dir)
     475        self.settings_override.enable()
     476        super(FileBackendTests, self).setUp()
    507477
    508478    def tearDown(self):
    509         restore_django_settings(self.__settings_state)
    510         shutil.rmtree(self.tmp_dir)
     479        self.settings_override.disable()
    511480        super(FileBackendTests, self).tearDown()
    512481
    513482    def flush_mailbox(self):
    class SMTPBackendTests(BaseEmailBackendTests, TestCase):  
    642611    @classmethod
    643612    def setUpClass(cls):
    644613        cls.server = FakeSMTPServer(('127.0.0.1', 0), None)
    645         cls.settings = alter_django_settings(
     614        cls.settings_override = with_settings(
    646615            EMAIL_HOST="127.0.0.1",
    647616            EMAIL_PORT=cls.server.socket.getsockname()[1])
     617        cls.settings_override.enable()
    648618        cls.server.start()
    649619
    650620    @classmethod
    651621    def tearDownClass(cls):
     622        cls.settings_override.disable()
    652623        cls.server.stop()
    653624
    654625    def setUp(self):
  • tests/regressiontests/settings_tests/tests.py

    diff --git a/tests/regressiontests/settings_tests/tests.py b/tests/regressiontests/settings_tests/tests.py
    index 750ccc6..dc9c5e4 100644
    a b  
    11from __future__ import with_statement
    2 import os
     2import os, sys
    33from django.conf import settings, global_settings
    44from django.test import TestCase
     5from django.test.utils import with_settings
     6from django.utils.unittest import skipIf
     7
     8
     9class SettingGetter(object):
     10    def __init__(self):
     11        self.test = getattr(settings, 'TEST', 'undefined')
     12
    513
    614class SettingsTests(TestCase):
    715
    class SettingsTests(TestCase):  
    2937            settings.TEST = 'test'
    3038        self.assertRaises(AttributeError, getattr, settings, 'TEST')
    3139
     40    @with_settings(TEST='override')
     41    def test_decorator(self):
     42        self.assertEqual('override', settings.TEST)
     43
     44    def test_context_manager(self):
     45        self.assertRaises(AttributeError, getattr, settings, 'TEST')
     46        override = with_settings(TEST='override')
     47        self.assertRaises(AttributeError, getattr, settings, 'TEST')
     48        override.enable()
     49        self.assertEqual('override', settings.TEST)
     50        override.disable()
     51        self.assertRaises(AttributeError, getattr, settings, 'TEST')
     52
     53    def test_class_decorator(self):
     54        self.assertEqual(SettingGetter().test, 'undefined')
     55        DecoratedSettingGetter = with_settings(TEST='override')(SettingGetter)
     56        self.assertEqual(DecoratedSettingGetter().test, 'override')
     57        self.assertRaises(AttributeError, getattr, settings, 'TEST')
     58
     59    @skipIf(sys.version_info[:2] < (2, 6), "Python version is lower than 2.6")
     60    def test_new_class_decorator(self):
     61        self.assertEqual(SettingGetter().test, 'undefined')
     62        @with_settings(TEST='override')
     63        class DecoratedSettingGetter(SettingGetter):
     64            pass
     65        self.assertEqual(DecoratedSettingGetter().test, 'override')
     66        self.assertRaises(AttributeError, getattr, settings, 'TEST')
     67
     68
    3269    #
    3370    # Regression tests for #10130: deleting settings.
    3471    #
Back to Top