Deprecated load_app().

Adjusted several tests that used it to add apps to the app cache and
then attempted to remove them by manipulating attributes directly.

Also renamed invalid_models to invalid_models_tests to avoid clashing
application labels between the outer and the inner invalid_models
applications.
This commit is contained in:
Aymeric Augustin 2013-12-18 17:56:11 +01:00
parent 439b364e1e
commit f25fa9d859
10 changed files with 47 additions and 64 deletions

View File

@ -133,16 +133,6 @@ class AppCache(object):
self._models_loaded = True self._models_loaded = True
def load_app(self, app_name):
"""
Loads the app with the provided fully qualified name, and returns the
model module.
"""
app_config = AppConfig(app_name)
app_config.import_models(self.all_models[app_config.label])
self.app_configs[app_config.label] = app_config
return app_config.models_module
def app_cache_ready(self): def app_cache_ready(self):
""" """
Returns true if the model cache is fully populated. Returns true if the model cache is fully populated.
@ -377,6 +367,19 @@ class AppCache(object):
### DEPRECATED METHODS GO BELOW THIS LINE ### ### DEPRECATED METHODS GO BELOW THIS LINE ###
def load_app(self, app_name):
"""
Loads the app with the provided fully qualified name, and returns the
model module.
"""
warnings.warn(
"load_app(app_name) is deprecated.",
PendingDeprecationWarning, stacklevel=2)
app_config = AppConfig(app_name)
app_config.import_models(self.all_models[app_config.label])
self.app_configs[app_config.label] = app_config
return app_config.models_module
def get_app(self, app_label): def get_app(self, app_label):
""" """
Returns the module containing the models for the given app_label. Returns the module containing the models for the given app_label.
@ -447,7 +450,7 @@ class AppCache(object):
Register a set of models as belonging to an app. Register a set of models as belonging to an app.
""" """
warnings.warn( warnings.warn(
"register_models(app_label, models) is deprecated.", "register_models(app_label, *models) is deprecated.",
PendingDeprecationWarning, stacklevel=2) PendingDeprecationWarning, stacklevel=2)
for model in models: for model in models:
self.register_model(app_label, model) self.register_model(app_label, model)

View File

@ -1094,7 +1094,7 @@ class ManageValidate(AdminScriptTestCase):
self.assertOutput(err, 'ImportError') self.assertOutput(err, 'ImportError')
def test_complex_app(self): def test_complex_app(self):
"manage.py validate does not raise an ImportError validating a complex app with nested calls to load_app" "manage.py validate does not raise an ImportError validating a complex app"
self.write_settings('settings.py', self.write_settings('settings.py',
apps=['admin_scripts.complex_app', 'admin_scripts.simple_app'], apps=['admin_scripts.complex_app', 'admin_scripts.simple_app'],
sdict={'DEBUG': True}) sdict={'DEBUG': True})

View File

@ -8,6 +8,7 @@ from django.core.apps import app_cache
from django.core.apps.cache import AppCache from django.core.apps.cache import AppCache
from django.test.utils import override_settings from django.test.utils import override_settings
from django.utils._os import upath from django.utils._os import upath
from django.utils import six
class EggLoadingTest(TestCase): class EggLoadingTest(TestCase):
@ -31,45 +32,41 @@ class EggLoadingTest(TestCase):
"""Models module can be loaded from an app in an egg""" """Models module can be loaded from an app in an egg"""
egg_name = '%s/modelapp.egg' % self.egg_dir egg_name = '%s/modelapp.egg' % self.egg_dir
sys.path.append(egg_name) sys.path.append(egg_name)
models = app_cache.load_app('app_with_models') with app_cache._with_app('app_with_models'):
self.assertFalse(models is None) models_module = app_cache.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
def test_egg2(self): def test_egg2(self):
"""Loading an app from an egg that has no models returns no models (and no error)""" """Loading an app from an egg that has no models returns no models (and no error)"""
egg_name = '%s/nomodelapp.egg' % self.egg_dir egg_name = '%s/nomodelapp.egg' % self.egg_dir
sys.path.append(egg_name) sys.path.append(egg_name)
models = app_cache.load_app('app_no_models') with app_cache._with_app('app_no_models'):
self.assertTrue(models is None) models_module = app_cache.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
def test_egg3(self): def test_egg3(self):
"""Models module can be loaded from an app located under an egg's top-level package""" """Models module can be loaded from an app located under an egg's top-level package"""
egg_name = '%s/omelet.egg' % self.egg_dir egg_name = '%s/omelet.egg' % self.egg_dir
sys.path.append(egg_name) sys.path.append(egg_name)
models = app_cache.load_app('omelet.app_with_models') with app_cache._with_app('omelet.app_with_models'):
self.assertFalse(models is None) models_module = app_cache.get_app_config('app_with_models').models_module
self.assertIsNotNone(models_module)
def test_egg4(self): def test_egg4(self):
"""Loading an app with no models from under the top-level egg package generates no error""" """Loading an app with no models from under the top-level egg package generates no error"""
egg_name = '%s/omelet.egg' % self.egg_dir egg_name = '%s/omelet.egg' % self.egg_dir
sys.path.append(egg_name) sys.path.append(egg_name)
models = app_cache.load_app('omelet.app_no_models') with app_cache._with_app('omelet.app_no_models'):
self.assertTrue(models is None) models_module = app_cache.get_app_config('app_no_models').models_module
self.assertIsNone(models_module)
def test_egg5(self): def test_egg5(self):
"""Loading an app from an egg that has an import error in its models module raises that error""" """Loading an app from an egg that has an import error in its models module raises that error"""
egg_name = '%s/brokenapp.egg' % self.egg_dir egg_name = '%s/brokenapp.egg' % self.egg_dir
sys.path.append(egg_name) sys.path.append(egg_name)
self.assertRaises(ImportError, app_cache.load_app, 'broken_app') with six.assertRaisesRegex(self, ImportError, 'modelz'):
raised = None with app_cache._with_app('broken_app'):
try: app_cache.get_app_config('omelet.app_no_models').models_module
app_cache.load_app('broken_app')
except ImportError as e:
raised = e
# Make sure the message is indicating the actual
# problem in the broken app.
self.assertTrue(raised is not None)
self.assertTrue("modelz" in raised.args[0])
def test_missing_app(self): def test_missing_app(self):
""" """

View File

@ -18,14 +18,7 @@ class InvalidModelTestCase(unittest.TestCase):
self.stdout = StringIO() self.stdout = StringIO()
sys.stdout = self.stdout sys.stdout = self.stdout
# The models need to be removed after the test in order to prevent bad
# interactions with the flush operation in other tests.
self._old_models = app_cache.app_configs['invalid_models'].models.copy()
def tearDown(self): def tearDown(self):
app_cache.app_configs['invalid_models'].models = self._old_models
app_cache.all_models['invalid_models'] = self._old_models
app_cache._get_models_cache = {}
sys.stdout = self.old_stdout sys.stdout = self.old_stdout
# Technically, this isn't an override -- TEST_SWAPPED_MODEL must be # Technically, this isn't an override -- TEST_SWAPPED_MODEL must be
@ -38,12 +31,10 @@ class InvalidModelTestCase(unittest.TestCase):
TEST_SWAPPED_MODEL_BAD_MODEL='not_an_app.Target', TEST_SWAPPED_MODEL_BAD_MODEL='not_an_app.Target',
) )
def test_invalid_models(self): def test_invalid_models(self):
try: with app_cache._with_app("invalid_models_tests.invalid_models"):
module = app_cache.load_app("invalid_models.invalid_models") module = app_cache.get_app_config("invalid_models").models_module
except Exception:
self.fail('Unable to load invalid model module')
get_validation_errors(self.stdout, module) get_validation_errors(self.stdout, module)
self.stdout.seek(0) self.stdout.seek(0)
error_log = self.stdout.read() error_log = self.stdout.read()
actual = error_log.split('\n') actual = error_log.split('\n')

View File

@ -124,7 +124,7 @@ class WriterTests(TestCase):
with override_settings(INSTALLED_APPS=test_apps): with override_settings(INSTALLED_APPS=test_apps):
for app in test_apps: for app in test_apps:
app_cache.load_app(app) with app_cache._with_app(app):
migration = migrations.Migration('0001_initial', app.split('.')[-1]) migration = migrations.Migration('0001_initial', app.split('.')[-1])
expected_path = os.path.join(base_dir, *(app.split('.') + ['migrations', '0001_initial.py'])) expected_path = os.path.join(base_dir, *(app.split('.') + ['migrations', '0001_initial.py']))
writer = MigrationWriter(migration) writer = MigrationWriter(migration)

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import os import os
import sys import sys
from django.conf import settings
from django.core.apps import app_cache from django.core.apps import app_cache
from django.core.management import call_command from django.core.management import call_command
from django.test import TestCase, TransactionTestCase from django.test import TestCase, TransactionTestCase
@ -21,28 +20,21 @@ class ProxyModelInheritanceTests(TransactionTestCase):
for the proxied model (as described in #12286). This test creates two dummy for the proxied model (as described in #12286). This test creates two dummy
apps and calls migrate, then verifies that the table has been created. apps and calls migrate, then verifies that the table has been created.
""" """
available_apps = ['app1', 'app2']
available_apps = []
def setUp(self): def setUp(self):
self.old_sys_path = sys.path[:] self.old_sys_path = sys.path[:]
sys.path.append(os.path.dirname(os.path.abspath(upath(__file__)))) sys.path.append(os.path.dirname(os.path.abspath(upath(__file__))))
for app in settings.INSTALLED_APPS: self._with_app1 = app_cache._begin_with_app('app1')
app_cache.load_app(app) self._with_app2 = app_cache._begin_with_app('app2')
def tearDown(self): def tearDown(self):
app_cache._end_with_app(self._with_app1)
app_cache._end_with_app(self._with_app2)
sys.path = self.old_sys_path sys.path = self.old_sys_path
del app_cache.app_configs['app1']
del app_cache.app_configs['app2']
del app_cache.all_models['app1']
del app_cache.all_models['app2']
def test_table_exists(self): def test_table_exists(self):
try:
app_cache.set_available_apps(settings.INSTALLED_APPS)
call_command('migrate', verbosity=0) call_command('migrate', verbosity=0)
finally:
app_cache.unset_available_apps()
from .app1.models import ProxyModel from .app1.models import ProxyModel
from .app2.models import NiceModel from .app2.models import NiceModel
self.assertEqual(NiceModel.objects.all().count(), 0) self.assertEqual(NiceModel.objects.all().count(), 0)
@ -56,7 +48,6 @@ class MultiTableInheritanceProxyTest(TestCase):
Deleting an instance of a model proxying a multi-table inherited Deleting an instance of a model proxying a multi-table inherited
subclass should cascade delete down the whole inheritance chain (see subclass should cascade delete down the whole inheritance chain (see
#18083). #18083).
""" """
instance = ConcreteModelSubclassProxy.objects.create() instance = ConcreteModelSubclassProxy.objects.create()
instance.delete() instance.delete()

View File

@ -164,7 +164,8 @@ def setup(verbosity, test_labels):
if module_found_in_labels: if module_found_in_labels:
if verbosity >= 2: if verbosity >= 2:
print("Importing application %s" % module_name) print("Importing application %s" % module_name)
app_cache.load_app(module_label) # HACK.
app_cache._begin_with_app(module_label)
if module_label not in settings.INSTALLED_APPS: if module_label not in settings.INSTALLED_APPS:
settings.INSTALLED_APPS.append(module_label) settings.INSTALLED_APPS.append(module_label)