diff --git a/django/db/backends/base/creation.py b/django/db/backends/base/creation.py index fe1d1b4dea..f36d60a5fe 100644 --- a/django/db/backends/base/creation.py +++ b/django/db/backends/base/creation.py @@ -1,3 +1,4 @@ +import os import sys from io import StringIO @@ -26,6 +27,9 @@ class BaseDatabaseCreation: """ return self.connection._nodb_connection + def log(self, msg): + sys.stderr.write(msg + os.linesep) + def create_test_db(self, verbosity=1, autoclobber=False, serialize=True, keepdb=False): """ Create a test database, prompting the user for confirmation if the @@ -41,7 +45,7 @@ class BaseDatabaseCreation: if keepdb: action = "Using existing" - print("%s test database for alias %s..." % ( + self.log('%s test database for alias %s...' % ( action, self._get_database_display_str(verbosity, test_database_name), )) @@ -170,8 +174,7 @@ class BaseDatabaseCreation: if keepdb: return test_database_name - sys.stderr.write( - "Got an error creating the test database: %s\n" % e) + self.log('Got an error creating the test database: %s' % e) if not autoclobber: confirm = input( "Type 'yes' if you would like to try deleting the test " @@ -179,17 +182,16 @@ class BaseDatabaseCreation: if autoclobber or confirm == 'yes': try: if verbosity >= 1: - print("Destroying old test database for alias %s..." % ( + self.log('Destroying old test database for alias %s...' % ( self._get_database_display_str(verbosity, test_database_name), )) cursor.execute('DROP DATABASE %(dbname)s' % test_db_params) self._execute_create_test_db(cursor, test_db_params, keepdb) except Exception as e: - sys.stderr.write( - "Got an error recreating the test database: %s\n" % e) + self.log('Got an error recreating the test database: %s' % e) sys.exit(2) else: - print("Tests cancelled.") + self.log('Tests cancelled.') sys.exit(1) return test_database_name @@ -204,7 +206,7 @@ class BaseDatabaseCreation: action = 'Cloning test database' if keepdb: action = 'Using existing clone' - print("%s for alias %s..." % ( + self.log('%s for alias %s...' % ( action, self._get_database_display_str(verbosity, source_database_name), )) @@ -246,7 +248,7 @@ class BaseDatabaseCreation: action = 'Destroying' if keepdb: action = 'Preserving' - print("%s test database for alias %s..." % ( + self.log('%s test database for alias %s...' % ( action, self._get_database_display_str(verbosity, test_database_name), )) diff --git a/django/db/backends/mysql/creation.py b/django/db/backends/mysql/creation.py index 190d5cc564..3c702d6979 100644 --- a/django/db/backends/mysql/creation.py +++ b/django/db/backends/mysql/creation.py @@ -33,7 +33,7 @@ class DatabaseCreation(BaseDatabaseCreation): except Exception as e: if len(e.args) < 1 or e.args[0] != 1007: # All errors except "database exists" (1007) cancel tests. - sys.stderr.write('Got an error creating the test database: %s\n' % e) + self.log('Got an error creating the test database: %s' % e) sys.exit(2) else: raise e @@ -51,13 +51,13 @@ class DatabaseCreation(BaseDatabaseCreation): except Exception: try: if verbosity >= 1: - print("Destroying old test database for alias %s..." % ( + self.log('Destroying old test database for alias %s...' % ( self._get_database_display_str(verbosity, target_database_name), )) cursor.execute('DROP DATABASE %(dbname)s' % test_db_params) self._execute_create_test_db(cursor, test_db_params, keepdb) except Exception as e: - sys.stderr.write("Got an error recreating the test database: %s\n" % e) + self.log('Got an error recreating the test database: %s' % e) sys.exit(2) dump_cmd = DatabaseClient.settings_to_cmd_args(self.connection.settings_dict) diff --git a/django/db/backends/oracle/creation.py b/django/db/backends/oracle/creation.py index 8f3d847d3a..1f30844330 100644 --- a/django/db/backends/oracle/creation.py +++ b/django/db/backends/oracle/creation.py @@ -36,7 +36,7 @@ class DatabaseCreation(BaseDatabaseCreation): except Exception as e: if 'ORA-01543' not in str(e): # All errors except "tablespace already exists" cancel tests - sys.stderr.write("Got an error creating the test database: %s\n" % e) + self.log('Got an error creating the test database: %s' % e) sys.exit(2) if not autoclobber: confirm = input( @@ -44,7 +44,7 @@ class DatabaseCreation(BaseDatabaseCreation): "Type 'yes' to delete it, or 'no' to cancel: " % parameters['user']) if autoclobber or confirm == 'yes': if verbosity >= 1: - print("Destroying old test database for alias '%s'..." % self.connection.alias) + self.log("Destroying old test database for alias '%s'..." % self.connection.alias) try: self._execute_test_db_destruction(cursor, parameters, verbosity) except DatabaseError as e: @@ -53,29 +53,29 @@ class DatabaseCreation(BaseDatabaseCreation): verbosity, autoclobber) else: # Ran into a database error that isn't about leftover objects in the tablespace - sys.stderr.write("Got an error destroying the old test database: %s\n" % e) + self.log('Got an error destroying the old test database: %s' % e) sys.exit(2) except Exception as e: - sys.stderr.write("Got an error destroying the old test database: %s\n" % e) + self.log('Got an error destroying the old test database: %s' % e) sys.exit(2) try: self._execute_test_db_creation(cursor, parameters, verbosity, keepdb) except Exception as e: - sys.stderr.write("Got an error recreating the test database: %s\n" % e) + self.log('Got an error recreating the test database: %s' % e) sys.exit(2) else: - print("Tests cancelled.") + self.log('Tests cancelled.') sys.exit(1) if self._test_user_create(): if verbosity >= 1: - print("Creating test user...") + self.log('Creating test user...') try: self._create_test_user(cursor, parameters, verbosity, keepdb) except Exception as e: if 'ORA-01920' not in str(e): # All errors except "user already exists" cancel tests - sys.stderr.write("Got an error creating the test user: %s\n" % e) + self.log('Got an error creating the test user: %s' % e) sys.exit(2) if not autoclobber: confirm = input( @@ -84,16 +84,16 @@ class DatabaseCreation(BaseDatabaseCreation): if autoclobber or confirm == 'yes': try: if verbosity >= 1: - print("Destroying old test user...") + self.log('Destroying old test user...') self._destroy_test_user(cursor, parameters, verbosity) if verbosity >= 1: - print("Creating test user...") + self.log('Creating test user...') self._create_test_user(cursor, parameters, verbosity, keepdb) except Exception as e: - sys.stderr.write("Got an error recreating the test user: %s\n" % e) + self.log('Got an error recreating the test user: %s' % e) sys.exit(2) else: - print("Tests cancelled.") + self.log('Tests cancelled.') sys.exit(1) self._maindb_connection.close() # done with main user -- test user and tablespaces created self._switch_to_test_user(parameters) @@ -130,36 +130,38 @@ class DatabaseCreation(BaseDatabaseCreation): def _handle_objects_preventing_db_destruction(self, cursor, parameters, verbosity, autoclobber): # There are objects in the test tablespace which prevent dropping it # The easy fix is to drop the test user -- but are we allowed to do so? - print("There are objects in the old test database which prevent its destruction.") - print("If they belong to the test user, deleting the user will allow the test " - "database to be recreated.") - print("Otherwise, you will need to find and remove each of these objects, " - "or use a different tablespace.\n") + self.log( + 'There are objects in the old test database which prevent its destruction.\n' + 'If they belong to the test user, deleting the user will allow the test ' + 'database to be recreated.\n' + 'Otherwise, you will need to find and remove each of these objects, ' + 'or use a different tablespace.\n' + ) if self._test_user_create(): if not autoclobber: confirm = input("Type 'yes' to delete user %s: " % parameters['user']) if autoclobber or confirm == 'yes': try: if verbosity >= 1: - print("Destroying old test user...") + self.log('Destroying old test user...') self._destroy_test_user(cursor, parameters, verbosity) except Exception as e: - sys.stderr.write("Got an error destroying the test user: %s\n" % e) + self.log('Got an error destroying the test user: %s' % e) sys.exit(2) try: if verbosity >= 1: - print("Destroying old test database for alias '%s'..." % self.connection.alias) + self.log("Destroying old test database for alias '%s'..." % self.connection.alias) self._execute_test_db_destruction(cursor, parameters, verbosity) except Exception as e: - sys.stderr.write("Got an error destroying the test database: %s\n" % e) + self.log('Got an error destroying the test database: %s' % e) sys.exit(2) else: - print("Tests cancelled -- test database cannot be recreated.") + self.log('Tests cancelled -- test database cannot be recreated.') sys.exit(1) else: - print("Django is configured to use pre-existing test user '%s'," - " and will not attempt to delete it.\n" % parameters['user']) - print("Tests cancelled -- test database cannot be recreated.") + self.log("Django is configured to use pre-existing test user '%s'," + " and will not attempt to delete it." % parameters['user']) + self.log('Tests cancelled -- test database cannot be recreated.') sys.exit(1) def _destroy_test_db(self, test_database_name, verbosity=1): @@ -174,17 +176,17 @@ class DatabaseCreation(BaseDatabaseCreation): with self._maindb_connection.cursor() as cursor: if self._test_user_create(): if verbosity >= 1: - print('Destroying test user...') + self.log('Destroying test user...') self._destroy_test_user(cursor, parameters, verbosity) if self._test_database_create(): if verbosity >= 1: - print('Destroying test database tables...') + self.log('Destroying test database tables...') self._execute_test_db_destruction(cursor, parameters, verbosity) self._maindb_connection.close() def _execute_test_db_creation(self, cursor, parameters, verbosity, keepdb=False): if verbosity >= 2: - print("_create_test_db(): dbname = %s" % parameters['user']) + self.log('_create_test_db(): dbname = %s' % parameters['user']) statements = [ """CREATE TABLESPACE %(tblspace)s DATAFILE '%(datafile)s' SIZE %(size)s @@ -201,7 +203,7 @@ class DatabaseCreation(BaseDatabaseCreation): def _create_test_user(self, cursor, parameters, verbosity, keepdb=False): if verbosity >= 2: - print("_create_test_user(): username = %s" % parameters['user']) + self.log('_create_test_user(): username = %s' % parameters['user']) statements = [ """CREATE USER %(user)s IDENTIFIED BY "%(password)s" @@ -227,11 +229,11 @@ class DatabaseCreation(BaseDatabaseCreation): extra = "GRANT CREATE VIEW TO %(user)s" success = self._execute_allow_fail_statements(cursor, [extra], parameters, verbosity, 'ORA-01031') if not success and verbosity >= 2: - print("Failed to grant CREATE VIEW permission to test user. This may be ok.") + self.log('Failed to grant CREATE VIEW permission to test user. This may be ok.') def _execute_test_db_destruction(self, cursor, parameters, verbosity): if verbosity >= 2: - print("_execute_test_db_destruction(): dbname=%s" % parameters['user']) + self.log('_execute_test_db_destruction(): dbname=%s' % parameters['user']) statements = [ 'DROP TABLESPACE %(tblspace)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', 'DROP TABLESPACE %(tblspace_temp)s INCLUDING CONTENTS AND DATAFILES CASCADE CONSTRAINTS', @@ -240,8 +242,8 @@ class DatabaseCreation(BaseDatabaseCreation): def _destroy_test_user(self, cursor, parameters, verbosity): if verbosity >= 2: - print("_destroy_test_user(): user=%s" % parameters['user']) - print("Be patient. This can take some time...") + self.log('_destroy_test_user(): user=%s' % parameters['user']) + self.log('Be patient. This can take some time...') statements = [ 'DROP USER %(user)s CASCADE', ] @@ -256,7 +258,7 @@ class DatabaseCreation(BaseDatabaseCreation): cursor.execute(stmt) except Exception as err: if (not allow_quiet_fail) or verbosity >= 2: - sys.stderr.write("Failed (%s)\n" % (err)) + self.log('Failed (%s)' % (err)) raise def _execute_allow_fail_statements(self, cursor, statements, parameters, verbosity, acceptable_ora_err): diff --git a/django/db/backends/postgresql/creation.py b/django/db/backends/postgresql/creation.py index 0169fc5c1f..8b6c4eff19 100644 --- a/django/db/backends/postgresql/creation.py +++ b/django/db/backends/postgresql/creation.py @@ -34,7 +34,7 @@ class DatabaseCreation(BaseDatabaseCreation): except Exception as e: if getattr(e.__cause__, 'pgcode', '') != errorcodes.DUPLICATE_DATABASE: # All errors except "database already exists" cancel tests. - sys.stderr.write('Got an error creating the test database: %s\n' % e) + self.log('Got an error creating the test database: %s' % e) sys.exit(2) elif not keepdb: # If the database should be kept, ignore "database already @@ -58,11 +58,11 @@ class DatabaseCreation(BaseDatabaseCreation): except Exception as e: try: if verbosity >= 1: - print("Destroying old test database for alias %s..." % ( + self.log('Destroying old test database for alias %s...' % ( self._get_database_display_str(verbosity, target_database_name), )) cursor.execute('DROP DATABASE %(dbname)s' % test_db_params) self._execute_create_test_db(cursor, test_db_params, keepdb) except Exception as e: - sys.stderr.write("Got an error cloning the test database: %s\n" % e) + self.log('Got an error cloning the test database: %s' % e) sys.exit(2) diff --git a/django/db/backends/sqlite3/creation.py b/django/db/backends/sqlite3/creation.py index 345954eb49..7e929f3451 100644 --- a/django/db/backends/sqlite3/creation.py +++ b/django/db/backends/sqlite3/creation.py @@ -25,7 +25,7 @@ class DatabaseCreation(BaseDatabaseCreation): if not self.is_in_memory_db(test_database_name): # Erase the old test database if verbosity >= 1: - print("Destroying old test database for alias %s..." % ( + self.log('Destroying old test database for alias %s...' % ( self._get_database_display_str(verbosity, test_database_name), )) if os.access(test_database_name, os.F_OK): @@ -38,10 +38,10 @@ class DatabaseCreation(BaseDatabaseCreation): try: os.remove(test_database_name) except Exception as e: - sys.stderr.write("Got an error deleting the old test database: %s\n" % e) + self.log('Got an error deleting the old test database: %s' % e) sys.exit(2) else: - print("Tests cancelled.") + self.log('Tests cancelled.') sys.exit(1) return test_database_name @@ -64,18 +64,18 @@ class DatabaseCreation(BaseDatabaseCreation): if keepdb: return if verbosity >= 1: - print("Destroying old test database for alias %s..." % ( + self.log('Destroying old test database for alias %s...' % ( self._get_database_display_str(verbosity, target_database_name), )) try: os.remove(target_database_name) except Exception as e: - sys.stderr.write("Got an error deleting the old test database: %s\n" % e) + self.log('Got an error deleting the old test database: %s' % e) sys.exit(2) try: shutil.copy(source_database_name, target_database_name) except Exception as e: - sys.stderr.write("Got an error cloning the test database: %s\n" % e) + self.log('Got an error cloning the test database: %s' % e) sys.exit(2) def _destroy_test_db(self, test_database_name, verbosity):