db_reuse.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. """Functions to aid in creating, reusing and destroying Django test databases
  2. """
  3. import os.path
  4. import sys
  5. import types
  6. def test_database_exists_from_previous_run(connection):
  7. # Try to open a cursor to the test database
  8. test_db_name = connection.creation._get_test_db_name()
  9. # When using a real SQLite backend (via TEST_NAME), check if the file
  10. # exists, because it gets created automatically.
  11. if connection.settings_dict['ENGINE'] == 'django.db.backends.sqlite3':
  12. if not os.path.exists(test_db_name):
  13. return False
  14. orig_db_name = connection.settings_dict['NAME']
  15. connection.settings_dict['NAME'] = test_db_name
  16. # With SQLite memory databases the db never exists.
  17. if connection.settings_dict['NAME'] == ':memory:':
  18. return False
  19. try:
  20. connection.cursor()
  21. return True
  22. except Exception: # TODO: Be more discerning but still DB agnostic.
  23. return False
  24. finally:
  25. connection.close()
  26. connection.settings_dict['NAME'] = orig_db_name
  27. def _monkeypatch(obj, method_name, new_method):
  28. assert hasattr(obj, method_name), method_name
  29. if sys.version_info < (3, 0):
  30. wrapped_method = types.MethodType(new_method, obj, obj.__class__)
  31. else:
  32. wrapped_method = types.MethodType(new_method, obj)
  33. setattr(obj, method_name, wrapped_method)
  34. def create_test_db_with_reuse(self, verbosity=1, autoclobber=False,
  35. keepdb=False, serialize=False):
  36. """
  37. This method is a monkey patched version of create_test_db that
  38. will not actually create a new database, but just reuse the
  39. existing.
  40. This is only used with Django < 1.8.
  41. """
  42. test_database_name = self._get_test_db_name()
  43. self.connection.settings_dict['NAME'] = test_database_name
  44. if verbosity >= 1:
  45. test_db_repr = ''
  46. if verbosity >= 2:
  47. test_db_repr = " ('%s')" % test_database_name
  48. print("Re-using existing test database for alias '%s'%s..." % (
  49. self.connection.alias, test_db_repr))
  50. return test_database_name
  51. def monkey_patch_creation_for_db_reuse():
  52. from django.db import connections
  53. for connection in connections.all():
  54. if test_database_exists_from_previous_run(connection):
  55. _monkeypatch(connection.creation, 'create_test_db',
  56. create_test_db_with_reuse)