Sfoglia il codice sorgente

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

Claude Paroz 6 anni fa
parent
commit
65503ca097

+ 11 - 9
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),
             ))

+ 3 - 3
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)

+ 36 - 34
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):

+ 3 - 3
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)

+ 6 - 6
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):