Browse Source

Populated Apps instances immediately by default.

Aymeric Augustin 11 years ago
parent
commit
7ed20e0153

+ 12 - 6
django/apps/registry.py

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

+ 1 - 4
django/db/migrations/state.py

@@ -33,12 +33,9 @@ class ProjectState(object):
     def render(self):
         "Turns the project state into actual models in a new Apps"
         if self.apps is None:
-            self.apps = Apps()
             # 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_configs = [AppConfigStub(label) for label in sorted(app_labels)]
-            self.apps.populate_apps(app_configs)
-            self.apps.populate_models()
+            self.apps = Apps([AppConfigStub(label) for label in sorted(app_labels)])
             # We keep trying to render the models in a loop, ignoring invalid
             # base errors, until the size of the unrendered models doesn't
             # decrease by at least one, meaning there's a base dependency loop/

+ 1 - 1
tests/apps/models.py

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

+ 4 - 13
tests/apps/tests.py

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

+ 3 - 3
tests/migrations/test_state.py

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