Populated Apps instances immediately by default.

This commit is contained in:
Aymeric Augustin 2013-12-30 16:03:06 +01:00
parent c31d7c4813
commit 7ed20e0153
5 changed files with 21 additions and 27 deletions

View File

@ -19,11 +19,12 @@ class Apps(object):
It also keeps track of models eg. to provide reverse-relations. It also keeps track of models eg. to provide reverse-relations.
""" """
def __init__(self, master=False): def __init__(self, installed_apps=()):
# Only one master registry may exist at a given time, and it shall be # installed_apps is set to None when creating the master registry
# the apps variable defined at the end of this module. # because it cannot be populated at that point. Other registries must
if master and hasattr(sys.modules[__name__], 'apps'): # provide a list of installed apps and are populated immediately.
raise RuntimeError("You may create only one master registry.") if installed_apps is None and hasattr(sys.modules[__name__], 'apps'):
raise RuntimeError("You must supply an installed_apps argument.")
# Mapping of app labels => model names => model classes. Every time a # Mapping of app labels => model names => model classes. Every time a
# model is imported, ModelBase.__new__ calls apps.register_model which # model is imported, ModelBase.__new__ calls apps.register_model which
@ -48,6 +49,11 @@ class Apps(object):
# Pending lookups for lazy relations. # Pending lookups for lazy relations.
self._pending_lookups = {} self._pending_lookups = {}
# Populate apps and models, unless it's the master registry.
if installed_apps is not None:
self.populate_apps(installed_apps)
self.populate_models()
def populate_apps(self, installed_apps=None): def populate_apps(self, installed_apps=None):
""" """
Populate app-related information. Populate app-related information.
@ -442,4 +448,4 @@ class Apps(object):
self.register_model(app_label, model) self.register_model(app_label, model)
apps = Apps(master=True) apps = Apps(installed_apps=None)

View File

@ -33,12 +33,9 @@ class ProjectState(object):
def render(self): def render(self):
"Turns the project state into actual models in a new Apps" "Turns the project state into actual models in a new Apps"
if self.apps is None: if self.apps is None:
self.apps = Apps()
# Populate the app registry with a stub for each application. # Populate the app registry with a stub for each application.
app_labels = set(model_state.app_label for model_state in self.models.values()) app_labels = set(model_state.app_label for model_state in self.models.values())
app_configs = [AppConfigStub(label) for label in sorted(app_labels)] self.apps = Apps([AppConfigStub(label) for label in sorted(app_labels)])
self.apps.populate_apps(app_configs)
self.apps.populate_models()
# We keep trying to render the models in a loop, ignoring invalid # We keep trying to render the models in a loop, ignoring invalid
# base errors, until the size of the unrendered models doesn't # base errors, until the size of the unrendered models doesn't
# decrease by at least one, meaning there's a base dependency loop/ # decrease by at least one, meaning there's a base dependency loop/

View File

@ -6,7 +6,7 @@ from django.db import models
# We're testing app registry presence on load, so this is handy. # We're testing app registry presence on load, so this is handy.
new_apps = Apps() new_apps = Apps(['apps'])
class TotallyNormal(models.Model): class TotallyNormal(models.Model):

View File

@ -36,7 +36,7 @@ class AppsTests(TestCase):
Ensures that only one master registry can exist. Ensures that only one master registry can exist.
""" """
with self.assertRaises(RuntimeError): with self.assertRaises(RuntimeError):
Apps(master=True) Apps(installed_apps=None)
def test_ready(self): def test_ready(self):
""" """
@ -44,17 +44,8 @@ class AppsTests(TestCase):
""" """
# The master app registry is always ready when the tests run. # The master app registry is always ready when the tests run.
self.assertTrue(apps.ready) self.assertTrue(apps.ready)
# Non-master app registries are populated in __init__.
def test_non_master_ready(self): self.assertTrue(Apps().ready)
"""
Tests the ready property of a registry other than the master.
"""
apps = Apps()
self.assertFalse(apps.ready)
apps.populate_apps([])
self.assertFalse(apps.ready)
apps.populate_models()
self.assertTrue(apps.ready)
def test_bad_app_config(self): def test_bad_app_config(self):
""" """
@ -162,7 +153,7 @@ class AppsTests(TestCase):
old_models = list(apps.get_app_config("apps").get_models()) old_models = list(apps.get_app_config("apps").get_models())
# Construct a new model in a new app registry # Construct a new model in a new app registry
body = {} body = {}
new_apps = Apps() new_apps = Apps(["apps"])
meta_contents = { meta_contents = {
'app_label': "apps", 'app_label': "apps",
'apps': new_apps, 'apps': new_apps,

View File

@ -14,7 +14,7 @@ class StateTests(TestCase):
Tests making a ProjectState from an Apps Tests making a ProjectState from an Apps
""" """
new_apps = Apps() new_apps = Apps(["migrations"])
class Author(models.Model): class Author(models.Model):
name = models.CharField(max_length=255) name = models.CharField(max_length=255)
@ -108,7 +108,7 @@ class StateTests(TestCase):
apps = Apps() apps = Apps()
# First, test rendering individually # First, test rendering individually
apps = Apps() apps = Apps(["migrations"])
# We shouldn't be able to render yet # We shouldn't be able to render yet
ms = ModelState.from_model(Novel) ms = ModelState.from_model(Novel)
@ -135,7 +135,7 @@ class StateTests(TestCase):
app_label = "migrations" app_label = "migrations"
apps = Apps() apps = Apps()
apps = Apps() apps = Apps(["migrations"])
# We shouldn't be able to render yet # We shouldn't be able to render yet
ms = ModelState.from_model(FooBar) ms = ModelState.from_model(FooBar)