Fixed override_settings when set_available_apps raises an exception.
Previously, this would corrupt the settings, because __exit__ isn't called when __enter__raises an exception.
This commit is contained in:
parent
7577d03809
commit
2ec8e3443b
|
@ -52,7 +52,7 @@ class AppCache(object):
|
||||||
# Cache for get_models.
|
# Cache for get_models.
|
||||||
self._get_models_cache = {}
|
self._get_models_cache = {}
|
||||||
|
|
||||||
def populate_apps(self):
|
def populate_apps(self, installed_apps=None):
|
||||||
"""
|
"""
|
||||||
Populate app-related information.
|
Populate app-related information.
|
||||||
|
|
||||||
|
@ -77,7 +77,9 @@ class AppCache(object):
|
||||||
# Application modules aren't expected to import anything, and
|
# Application modules aren't expected to import anything, and
|
||||||
# especially not other application modules, even indirectly.
|
# especially not other application modules, even indirectly.
|
||||||
# Therefore we simply import them sequentially.
|
# Therefore we simply import them sequentially.
|
||||||
for app_name in settings.INSTALLED_APPS:
|
if installed_apps is None:
|
||||||
|
installed_apps = settings.INSTALLED_APPS
|
||||||
|
for app_name in installed_apps:
|
||||||
app_config = AppConfig.create(app_name)
|
app_config = AppConfig.create(app_name)
|
||||||
self.app_configs[app_config.label] = app_config
|
self.app_configs[app_config.label] = app_config
|
||||||
|
|
||||||
|
@ -299,6 +301,8 @@ class AppCache(object):
|
||||||
|
|
||||||
available must be an iterable of application names.
|
available must be an iterable of application names.
|
||||||
|
|
||||||
|
set_available_apps() must be balanced with unset_available_apps().
|
||||||
|
|
||||||
Primarily used for performance optimization in TransactionTestCase.
|
Primarily used for performance optimization in TransactionTestCase.
|
||||||
|
|
||||||
This method is safe is the sense that it doesn't trigger any imports.
|
This method is safe is the sense that it doesn't trigger any imports.
|
||||||
|
@ -323,10 +327,13 @@ class AppCache(object):
|
||||||
|
|
||||||
def set_installed_apps(self, installed):
|
def set_installed_apps(self, installed):
|
||||||
"""
|
"""
|
||||||
Enables a different set of installed_apps for get_app_config[s].
|
Enables a different set of installed apps for get_app_config[s].
|
||||||
|
|
||||||
installed must be an iterable in the same format as INSTALLED_APPS.
|
installed must be an iterable in the same format as INSTALLED_APPS.
|
||||||
|
|
||||||
|
set_installed_apps() must be balanced with unset_installed_apps(),
|
||||||
|
even if it exits with an exception.
|
||||||
|
|
||||||
Primarily used as a receiver of the setting_changed signal in tests.
|
Primarily used as a receiver of the setting_changed signal in tests.
|
||||||
|
|
||||||
This method may trigger new imports, which may add new models to the
|
This method may trigger new imports, which may add new models to the
|
||||||
|
@ -337,14 +344,10 @@ class AppCache(object):
|
||||||
"""
|
"""
|
||||||
self.stored_app_configs.append(self.app_configs)
|
self.stored_app_configs.append(self.app_configs)
|
||||||
self.app_configs = OrderedDict()
|
self.app_configs = OrderedDict()
|
||||||
try:
|
|
||||||
self._apps_loaded = False
|
self._apps_loaded = False
|
||||||
self.populate_apps()
|
self.populate_apps(installed)
|
||||||
self._models_loaded = False
|
self._models_loaded = False
|
||||||
self.populate_models()
|
self.populate_models()
|
||||||
except Exception:
|
|
||||||
self.unset_installed_apps()
|
|
||||||
raise
|
|
||||||
|
|
||||||
def unset_installed_apps(self):
|
def unset_installed_apps(self):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -225,22 +225,28 @@ class override_settings(object):
|
||||||
test_func._overridden_settings, **self.options)
|
test_func._overridden_settings, **self.options)
|
||||||
|
|
||||||
def enable(self):
|
def enable(self):
|
||||||
|
# Keep this code at the beginning to leave the settings unchanged
|
||||||
|
# in case it raises an exception because INSTALLED_APPS is invalid.
|
||||||
|
if 'INSTALLED_APPS' in self.options:
|
||||||
|
try:
|
||||||
|
app_cache.set_installed_apps(self.options['INSTALLED_APPS'])
|
||||||
|
except Exception:
|
||||||
|
app_cache.unset_installed_apps()
|
||||||
|
raise
|
||||||
override = UserSettingsHolder(settings._wrapped)
|
override = UserSettingsHolder(settings._wrapped)
|
||||||
for key, new_value in self.options.items():
|
for key, new_value in self.options.items():
|
||||||
setattr(override, key, new_value)
|
setattr(override, key, new_value)
|
||||||
self.wrapped = settings._wrapped
|
self.wrapped = settings._wrapped
|
||||||
settings._wrapped = override
|
settings._wrapped = override
|
||||||
if 'INSTALLED_APPS' in self.options:
|
|
||||||
app_cache.set_installed_apps(settings.INSTALLED_APPS)
|
|
||||||
for key, new_value in self.options.items():
|
for key, new_value in self.options.items():
|
||||||
setting_changed.send(sender=settings._wrapped.__class__,
|
setting_changed.send(sender=settings._wrapped.__class__,
|
||||||
setting=key, value=new_value, enter=True)
|
setting=key, value=new_value, enter=True)
|
||||||
|
|
||||||
def disable(self):
|
def disable(self):
|
||||||
settings._wrapped = self.wrapped
|
|
||||||
del self.wrapped
|
|
||||||
if 'INSTALLED_APPS' in self.options:
|
if 'INSTALLED_APPS' in self.options:
|
||||||
app_cache.unset_installed_apps()
|
app_cache.unset_installed_apps()
|
||||||
|
settings._wrapped = self.wrapped
|
||||||
|
del self.wrapped
|
||||||
for key in self.options:
|
for key in self.options:
|
||||||
new_value = getattr(settings, key, None)
|
new_value = getattr(settings, key, None)
|
||||||
setting_changed.send(sender=settings._wrapped.__class__,
|
setting_changed.send(sender=settings._wrapped.__class__,
|
||||||
|
|
Loading…
Reference in New Issue