mirror of
				https://github.com/django/django.git
				synced 2025-10-31 01:25:32 +00:00 
			
		
		
		
	Fixed #32403 -- Fixed re-raising DatabaseErrors when using only 'postgres' database.
Thanks Kazantcev Andrey for the report.
Regression in f48f671223.
			
			
This commit is contained in:
		| @@ -332,6 +332,9 @@ class DatabaseWrapper(BaseDatabaseWrapper): | |||||||
|                             yield cursor |                             yield cursor | ||||||
|                     finally: |                     finally: | ||||||
|                         conn.close() |                         conn.close() | ||||||
|  |                     break | ||||||
|  |             else: | ||||||
|  |                 raise | ||||||
|  |  | ||||||
|     @cached_property |     @cached_property | ||||||
|     def pg_version(self): |     def pg_version(self): | ||||||
|   | |||||||
| @@ -9,4 +9,6 @@ Django 3.1.7 fixes several bugs in 3.1.6. | |||||||
| Bugfixes | Bugfixes | ||||||
| ======== | ======== | ||||||
|  |  | ||||||
| * ... | * Fixed a regression in Django 3.1 that caused ``RuntimeError`` instead of | ||||||
|  |   connection errors when using only the ``'postgres'`` database | ||||||
|  |   (:ticket:`32403`). | ||||||
|   | |||||||
| @@ -1,9 +1,10 @@ | |||||||
|  | import copy | ||||||
| import unittest | import unittest | ||||||
| from io import StringIO | from io import StringIO | ||||||
| from unittest import mock | from unittest import mock | ||||||
|  |  | ||||||
| from django.core.exceptions import ImproperlyConfigured | from django.core.exceptions import ImproperlyConfigured | ||||||
| from django.db import DatabaseError, connection, connections | from django.db import DEFAULT_DB_ALIAS, DatabaseError, connection, connections | ||||||
| from django.db.backends.base.base import BaseDatabaseWrapper | from django.db.backends.base.base import BaseDatabaseWrapper | ||||||
| from django.test import TestCase, override_settings | from django.test import TestCase, override_settings | ||||||
|  |  | ||||||
| @@ -54,6 +55,53 @@ class Tests(TestCase): | |||||||
|         self.assertIsNone(cursor.db.connection) |         self.assertIsNone(cursor.db.connection) | ||||||
|         self.assertIsNotNone(cursor.db.settings_dict['NAME']) |         self.assertIsNotNone(cursor.db.settings_dict['NAME']) | ||||||
|         self.assertEqual(cursor.db.settings_dict['NAME'], connections['other'].settings_dict['NAME']) |         self.assertEqual(cursor.db.settings_dict['NAME'], connections['other'].settings_dict['NAME']) | ||||||
|  |         # Cursor is yielded only for the first PostgreSQL database. | ||||||
|  |         with self.assertWarnsMessage(RuntimeWarning, msg): | ||||||
|  |             with mock.patch( | ||||||
|  |                 'django.db.backends.base.base.BaseDatabaseWrapper.connect', | ||||||
|  |                 side_effect=mocked_connect, | ||||||
|  |                 autospec=True, | ||||||
|  |             ): | ||||||
|  |                 with connection._nodb_cursor() as cursor: | ||||||
|  |                     self.assertIs(cursor.closed, False) | ||||||
|  |                     self.assertIsNotNone(cursor.db.connection) | ||||||
|  |  | ||||||
|  |     def test_nodb_cursor_raises_postgres_authentication_failure(self): | ||||||
|  |         """ | ||||||
|  |         _nodb_cursor() re-raises authentication failure to the 'postgres' db | ||||||
|  |         when other connection to the PostgreSQL database isn't available. | ||||||
|  |         """ | ||||||
|  |         def mocked_connect(self): | ||||||
|  |             raise DatabaseError() | ||||||
|  |  | ||||||
|  |         def mocked_all(self): | ||||||
|  |             test_connection = copy.copy(connections[DEFAULT_DB_ALIAS]) | ||||||
|  |             test_connection.settings_dict = copy.deepcopy(connection.settings_dict) | ||||||
|  |             test_connection.settings_dict['NAME'] = 'postgres' | ||||||
|  |             return [test_connection] | ||||||
|  |  | ||||||
|  |         msg = ( | ||||||
|  |             "Normally Django will use a connection to the 'postgres' database " | ||||||
|  |             "to avoid running initialization queries against the production " | ||||||
|  |             "database when it's not needed (for example, when running tests). " | ||||||
|  |             "Django was unable to create a connection to the 'postgres' " | ||||||
|  |             "database and will use the first PostgreSQL database instead." | ||||||
|  |         ) | ||||||
|  |         with self.assertWarnsMessage(RuntimeWarning, msg): | ||||||
|  |             mocker_connections_all = mock.patch( | ||||||
|  |                 'django.utils.connection.BaseConnectionHandler.all', | ||||||
|  |                 side_effect=mocked_all, | ||||||
|  |                 autospec=True, | ||||||
|  |             ) | ||||||
|  |             mocker_connect = mock.patch( | ||||||
|  |                 'django.db.backends.base.base.BaseDatabaseWrapper.connect', | ||||||
|  |                 side_effect=mocked_connect, | ||||||
|  |                 autospec=True, | ||||||
|  |             ) | ||||||
|  |             with mocker_connections_all, mocker_connect: | ||||||
|  |                 with self.assertRaises(DatabaseError): | ||||||
|  |                     with connection._nodb_cursor(): | ||||||
|  |                         pass | ||||||
|  |  | ||||||
|     def test_database_name_too_long(self): |     def test_database_name_too_long(self): | ||||||
|         from django.db.backends.postgresql.base import DatabaseWrapper |         from django.db.backends.postgresql.base import DatabaseWrapper | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user