Hi all, I've been looking at #14799, and trying to work out the best approach for a solution. I can see three options, none of which are are particularly attractive. I'm looking for feedback on which one smells the least.
First off - the problem: * The test framework needs to create test databases * The DB backend call to create the test database implies a call to syncdb on that database * But a post_syncdb handler can invoke a query on *any* database * If the database required by the code in a post_syncdb handler hasn't been created yet, the test system falls over during database setup. * The test databases are specified as a dictionary, so there's no guarantee on the order in which tests databases are created. There is one obvious manifestation of this bug. If you run Django's own test suite, and the 'other' alias is created before the 'default' alias, the test suite fails to initialize, because the post_syncdb handler for contenttypes tries to run ContentTypes.objects.get() on the 'default' database, but that database doesn't exist yet. Jacob has committed an interim fix for this problem, which involves simply ensuring that the 'default' database is created first. This works for Django's own test suite, but doesn't work in the general case -- if you have a router that directs contenttypes read queries to 'other', the suite will fail for exactly the same reason. Similarly, if you have some other post_syncdb handler with dependency on something other than default, So - how can this be fixed? Option 1: The documentation approach: "You may only assume that the default database exists when post_syncdb runs on a non-default database". This is the non-solution; the current code on trunk will be sufficient, but it will leave some users high and dry. Option 2: Force the use of SortedDict when defining DATABASES. This removes the non-deterministic database creation order, but requires imports in the settings file, and requires action on the part of every person that has migrated to using the DATABASES format. Option 3: Split syncdb into two parts -- phase 1: create tables, and phase 2: post_syncdb, custom SQL, index creation and initial data. I haven't implemented this -- but I've taken a look at what will be needed, and it will be messy. The current syncdb command and backend.create_test_db() API guarantees a full syncdb cycle, so implementing this in a way that preserves backwards compatibility will involve introducing a bunch of flags that only do partial syncdb runs (either phase 1 or phase 2). There's also the question of whether this will violate any existing expectations -- after all, we will be effectively changing the order in which syncdb will be invoked in a non-configurable way. Option 4: Introduce a per-database setting -- TEST_DEPENDENCIES -- that allows the developer to explicitly encode the dependency between databases. This means the developer can explicitly encode the dependencies that exists in database creation order. We can default to assuming 'everything depends on default' (which is what the current trunk implements); but this gives end users the flexibility to define any dependency they need. The patch on #14799 implements this solution (although it needs some tests for the dependency resolution code and documentation for the setting itself) My personal preference is for (4). I don't like the addition of a setting, but it's a setting that most users will be able to ignore (since there is a reasonably sensible default), and it is the most explicit and configurable option available. Opinions? Alternatives? Yours, Russ Magee %-) -- You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-develop...@googlegroups.com. To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-developers?hl=en.