Fixed #22811 -- Allowed setting both the old and new TEST database settings.

An ImproperlyConfigured exception will be raised they mismatch.
This commit is contained in:
Tim Graham 2014-06-11 15:26:17 -04:00
parent dfa3505ff1
commit 1c58cabad7
4 changed files with 141 additions and 8 deletions

View File

@ -183,6 +183,7 @@ class ConnectionHandler(object):
'USER_CREATE': 'CREATE_USER', 'USER_CREATE': 'CREATE_USER',
'PASSWD': 'PASSWORD', 'PASSWD': 'PASSWORD',
} }
TEST_SETTING_RENAMES_REVERSE = {v: k for k, v in TEST_SETTING_RENAMES.items()}
def prepare_test_settings(self, alias): def prepare_test_settings(self, alias):
""" """
@ -193,18 +194,29 @@ class ConnectionHandler(object):
except KeyError: except KeyError:
raise ConnectionDoesNotExist("The connection %s doesn't exist" % alias) raise ConnectionDoesNotExist("The connection %s doesn't exist" % alias)
test_dict_set = 'TEST' in conn
test_settings = conn.setdefault('TEST', {}) test_settings = conn.setdefault('TEST', {})
old_test_settings = {}
for key, value in six.iteritems(conn): for key, value in six.iteritems(conn):
if key.startswith('TEST_'): if key.startswith('TEST_'):
new_key = key[5:] new_key = key[5:]
new_key = self.TEST_SETTING_RENAMES.get(new_key, new_key) new_key = self.TEST_SETTING_RENAMES.get(new_key, new_key)
if new_key in test_settings: old_test_settings[new_key] = value
raise ImproperlyConfigured("Connection %s has both %s and TEST[%s] specified." %
(alias, key, new_key)) if old_test_settings:
warnings.warn("In Django 1.9 the %s connection setting will be moved " if test_dict_set:
"to a %s entry in the TEST setting" % (key, new_key), if test_settings != old_test_settings:
RemovedInDjango19Warning, stacklevel=2) raise ImproperlyConfigured(
test_settings[new_key] = value "Connection '%s' has mismatched TEST and TEST_* "
"database settings." % alias)
else:
test_settings = old_test_settings
for key, _ in six.iteritems(old_test_settings):
warnings.warn("In Django 1.9 the %s connection setting will be moved "
"to a %s entry in the TEST setting" %
(self.TEST_SETTING_RENAMES_REVERSE.get(key, key), key),
RemovedInDjango19Warning, stacklevel=2)
for key in list(conn.keys()): for key in list(conn.keys()):
if key.startswith('TEST_'): if key.startswith('TEST_'):
del conn[key] del conn[key]

View File

@ -586,6 +586,8 @@ TEST
All :setting:`TEST <DATABASE-TEST>` sub-entries used to be independent All :setting:`TEST <DATABASE-TEST>` sub-entries used to be independent
entries in the database settings dictionary, with a ``TEST_`` prefix. entries in the database settings dictionary, with a ``TEST_`` prefix.
For backwards compatibility with older versions of Django, you can define
both versions of the settings as long as they match.
Further, ``TEST_CREATE``, ``TEST_USER_CREATE`` and ``TEST_PASSWD`` Further, ``TEST_CREATE``, ``TEST_USER_CREATE`` and ``TEST_PASSWD``
were changed to ``CREATE_DB``, ``CREATE_USER`` and ``PASSWORD`` were changed to ``CREATE_DB``, ``CREATE_USER`` and ``PASSWORD``
respectively. respectively.

View File

@ -1546,9 +1546,12 @@ will be removed in Django 1.8.
Reorganization of database test settings Reorganization of database test settings
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
All database settings with a ``TEST_`` prefix have been deprecated in favor of All database settings with a ``TEST_`` prefix have been deprecated in favor of
entries in a :setting:`TEST <DATABASE-TEST>` dictionary in the database entries in a :setting:`TEST <DATABASE-TEST>` dictionary in the database
settings. The old settings will be supported until Django 1.9. settings. The old settings will be supported until Django 1.9. For backwards
compatibility with older versions of Django, you can define both versions of
the settings as long as they match.
FastCGI support FastCGI support
~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~

View File

@ -11,6 +11,7 @@ import unittest
import warnings import warnings
from django.conf import settings from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.management.color import no_style from django.core.management.color import no_style
from django.db import (connection, connections, DEFAULT_DB_ALIAS, from django.db import (connection, connections, DEFAULT_DB_ALIAS,
DatabaseError, IntegrityError, reset_queries, transaction) DatabaseError, IntegrityError, reset_queries, transaction)
@ -1077,3 +1078,118 @@ class BackendUtilTests(TestCase):
'0.1') '0.1')
equal('0.1234567890', 12, 0, equal('0.1234567890', 12, 0,
'0') '0')
class DBTestSettingsRenamedTests(TestCase):
mismatch_msg = ("Connection 'test-deprecation' has mismatched TEST "
"and TEST_* database settings.")
def setUp(self):
self.handler = ConnectionHandler()
self.db_settings = {'default': {}}
def test_mismatched_database_test_settings_1(self):
# if the TEST setting is used, all TEST_* keys must appear in it.
self.db_settings.update({
'test-deprecation': {
'TEST': {},
'TEST_NAME': 'foo',
}
})
with override_settings(DATABASES=self.db_settings):
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
self.handler.prepare_test_settings('test-deprecation')
def test_mismatched_database_test_settings_2(self):
# if the TEST setting is used, all TEST_* keys must match.
self.db_settings.update({
'test-deprecation': {
'TEST': {'NAME': 'foo'},
'TEST_NAME': 'bar',
},
})
with override_settings(DATABASES=self.db_settings):
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
self.handler.prepare_test_settings('test-deprecation')
def test_mismatched_database_test_settings_3(self):
# Verifies the mapping of an aliased key.
self.db_settings.update({
'test-deprecation': {
'TEST': {'CREATE_DB': 'foo'},
'TEST_CREATE': 'bar',
},
})
with override_settings(DATABASES=self.db_settings):
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
self.handler.prepare_test_settings('test-deprecation')
def test_mismatched_database_test_settings_4(self):
# Verifies the mapping of an aliased key when the aliased key is missing.
self.db_settings.update({
'test-deprecation': {
'TEST': {},
'TEST_CREATE': 'bar',
},
})
with override_settings(DATABASES=self.db_settings):
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
self.handler.prepare_test_settings('test-deprecation')
def test_mismatched_settings_old_none(self):
self.db_settings.update({
'test-deprecation': {
'TEST': {'CREATE_DB': None},
'TEST_CREATE': '',
},
})
with override_settings(DATABASES=self.db_settings):
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
self.handler.prepare_test_settings('test-deprecation')
def test_mismatched_settings_new_none(self):
self.db_settings.update({
'test-deprecation': {
'TEST': {},
'TEST_CREATE': None,
},
})
with override_settings(DATABASES=self.db_settings):
with self.assertRaisesMessage(ImproperlyConfigured, self.mismatch_msg):
self.handler.prepare_test_settings('test-deprecation')
def test_matched_test_settings(self):
# should be able to define new settings and the old, if they match
self.db_settings.update({
'test-deprecation': {
'TEST': {'NAME': 'foo'},
'TEST_NAME': 'foo',
},
})
with override_settings(DATABASES=self.db_settings):
self.handler.prepare_test_settings('test-deprecation')
def test_new_settings_only(self):
# should be able to define new settings without the old
self.db_settings.update({
'test-deprecation': {
'TEST': {'NAME': 'foo'},
},
})
with override_settings(DATABASES=self.db_settings):
self.handler.prepare_test_settings('test-deprecation')
def test_old_settings_only(self):
# should be able to define old settings without the new
self.db_settings.update({
'test-deprecation': {
'TEST_NAME': 'foo',
},
})
with override_settings(DATABASES=self.db_settings):
self.handler.prepare_test_settings('test-deprecation')
def test_empty_settings(self):
with override_settings(DATABASES=self.db_settings):
self.handler.prepare_test_settings('default')