Fixed #29040 -- Made test database creation messages use a consistent output stream.

This commit is contained in:
Claude Paroz 2018-07-20 00:05:33 +02:00 committed by Tim Graham
parent 1e9b02a4c2
commit 65503ca097
5 changed files with 59 additions and 55 deletions

View File

@ -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),
))

View File

@ -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)

View File

@ -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):

View File

@ -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)

View File

@ -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):