Permalink
Browse files

Proof of concept implementation for disabling import time queries dur…

…ing test setup
  • Loading branch information...
1 parent 9fd2f9c commit 1b99fcee4c0b3782d3136744cfaaccfea1d535e0 @akaariai committed Oct 23, 2012
Showing with 32 additions and 3 deletions.
  1. +10 −1 django/db/__init__.py
  2. +6 −0 django/db/backends/__init__.py
  3. +16 −2 django/test/simple.py
View
@@ -5,14 +5,23 @@
load_backend, DEFAULT_DB_ALIAS, DatabaseError, IntegrityError)
__all__ = ('backend', 'connection', 'connections', 'router', 'DatabaseError',
- 'IntegrityError', 'DEFAULT_DB_ALIAS')
+ 'IntegrityError', 'DEFAULT_DB_ALIAS', '_disable_connections',
+ '_enable_connections')
if DEFAULT_DB_ALIAS not in settings.DATABASES:
raise ImproperlyConfigured("You must define a '%s' database" % DEFAULT_DB_ALIAS)
connections = ConnectionHandler(settings.DATABASES)
+def _disable_connections():
+ for alias in connections:
+ connections[alias]._queries_disabled = True
+
+def _enable_connections():
+ for alias in connections:
+ connections[alias]._queries_disabled = False
+
router = ConnectionRouter(settings.DATABASE_ROUTERS)
# `connection`, `DatabaseError` and `IntegrityError` are convenient aliases
@@ -40,6 +40,7 @@ def __init__(self, settings_dict, alias=DEFAULT_DB_ALIAS,
self._dirty = None
self._thread_ident = thread.get_ident()
self.allow_thread_sharing = allow_thread_sharing
+ self._queries_disabled = False
def __eq__(self, other):
return self.alias == other.alias
@@ -307,7 +308,12 @@ def close(self):
self.connection.close()
self.connection = None
+ def _disable_queries(self):
+ self._queries_disabled = True
+
def cursor(self):
+ if self._queries_disabled:
+ raise RuntimeError("Queries disabled. Avoid import time queries...")
self.validate_thread_sharing()
if (self.use_debug_cursor or
(self.use_debug_cursor is None and settings.DEBUG)):
View
@@ -233,6 +233,9 @@ def dependency_ordered(test_databases, dependencies):
test_databases = deferred
return ordered_test_databases
+def disable_global_connections():
+ from django.db import _disable_connections
+ _disable_connections()
class DjangoTestSuiteRunner(object):
def __init__(self, verbosity=1, interactive=True, failfast=True, **kwargs):
@@ -241,6 +244,10 @@ def __init__(self, verbosity=1, interactive=True, failfast=True, **kwargs):
self.failfast = failfast
def setup_test_environment(self, **kwargs):
+ # Make a local copy of the global connections, remove them from
+ # use to make sure import time behavior doesn't access production
+ # db.
+ disable_global_connections()
setup_test_environment()
settings.DEBUG = False
unittest.installHandler()
@@ -266,13 +273,14 @@ def build_suite(self, test_labels, extra_tests=None, **kwargs):
return reorder_suite(suite, (unittest.TestCase,))
def setup_databases(self, **kwargs):
- from django.db import connections, DEFAULT_DB_ALIAS
+ from django.db import DEFAULT_DB_ALIAS, connections
# First pass -- work out which databases actually need to be created,
# and which ones are test mirrors or duplicate entries in DATABASES
mirrored_aliases = {}
test_databases = {}
dependencies = {}
+
for alias in connections:
connection = connections[alias]
if connection.settings_dict['TEST_MIRROR']:
@@ -302,6 +310,13 @@ def setup_databases(self, **kwargs):
old_names = []
mirrors = []
+ # Enable connections. We might still run queries against the production
+ # db (the database NAME isn't changed yet). There is minimal risk
+ # import time queries at this stage, so enabling connections should be
+ # safe enough.
+ from django.db import _enable_connections, connections
+ _enable_connections()
+
for signature, (db_name, aliases) in dependency_ordered(
test_databases.items(), dependencies):
test_db_name = None
@@ -320,7 +335,6 @@ def setup_databases(self, **kwargs):
mirrors.append((alias, connections[alias].settings_dict['NAME']))
connections[alias].settings_dict['NAME'] = (
connections[mirror_alias].settings_dict['NAME'])
-
return old_names, mirrors
def run_suite(self, suite, **kwargs):

0 comments on commit 1b99fce

Please sign in to comment.