tests for django db utils import unittest from django core exceptions import improperlyconfigured from django db import defaultdbalias programmingerror connection from django db utils import connectionhandler loadbackend from django test import simpletestcase testcase from django utils connection import connectiondoesnotexist class connectionhandlertestssimpletestcase def testconnectionhandlernodatabasesself for databases in empty databases setting default empty default database with self subtestdatabasesdatabases self assertimproperlyconfigureddatabases def assertimproperlyconfiguredself databases conns connectionhandlerdatabases self assertequal connsdefaultdbalias settingsdictengine django db backends dummy msg settings databases is improperly configured please supply the engine value check settings documentation for more details with self assertraisesmessageimproperlyconfigured msg connsdefaultdbalias ensureconnection def testnodefaultdatabaseself databases other conns connectionhandlerdatabases msg you must define a default database with self assertraisesmessageimproperlyconfigured msg connsother ensureconnection def testdatabasespropertyself the databases property is maintained for backwards compatibility with 3rd party packages it should be an alias of the settings property conn connectionhandler self assertnotequalconn settings self assertequalconn settings conn databases def testnonexistentaliasself msg the connection nonexistent doesn t exist conns connectionhandler defaultdbalias engine django db backends dummy with self assertraisesmessageconnectiondoesnotexist msg connsnonexistent class databaseerrorwrapperteststestcase unittest skipunlessconnection vendor postgresql postgresql test def testreraisingbackendspecificdatabaseexceptionself from django db backends postgresql psycopgany import ispsycopg3 with connection cursor as cursor msg table x does not exist with self assertraisesmessageprogrammingerror msg as cm cursor execute drop table x self assertnotequaltypecm exception typecm exception cause self assertisnotnonecm exception cause if ispsycopg3 self assertisnotnonecm exception cause diag sqlstate self assertisnotnonecm exception cause diag messageprimary else self assertisnotnonecm exception cause pgcode self assertisnotnonecm exception cause pgerror class loadbackendtestssimpletestcase def testloadbackendinvalidnameself msg foo isn t an available database backend or couldn t be imported check the above exception to use one of the builtin backends use django db backends xxx where xxx is one of n mysql oracle postgresql sqlite3 with self assertraisesmessageimproperlyconfigured msg as cm loadbackendfoo self assertequalstrcm exception cause no module named foo empty databases and empty default settings default to the dummy backend empty databases setting empty default database the databases property is maintained for backwards compatibility with 3rd party packages it should be an alias of the settings property
import unittest

from django.core.exceptions import ImproperlyConfigured
from django.db import DEFAULT_DB_ALIAS, ProgrammingError, connection
from django.db.utils import ConnectionHandler, load_backend
from django.test import SimpleTestCase, TestCase
from django.utils.connection import ConnectionDoesNotExist


class ConnectionHandlerTests(SimpleTestCase):
    def test_connection_handler_no_databases(self):
        
        for DATABASES in (
            {},  
            {"default": {}},  
        ):
            with self.subTest(DATABASES=DATABASES):
                self.assertImproperlyConfigured(DATABASES)

    def assertImproperlyConfigured(self, DATABASES):
        conns = ConnectionHandler(DATABASES)
        self.assertEqual(
            conns[DEFAULT_DB_ALIAS].settings_dict["ENGINE"], "django.db.backends.dummy"
        )
        msg = (
            "settings.DATABASES is improperly configured. Please supply the "
            "ENGINE value. Check settings documentation for more details."
        )
        with self.assertRaisesMessage(ImproperlyConfigured, msg):
            conns[DEFAULT_DB_ALIAS].ensure_connection()

    def test_no_default_database(self):
        DATABASES = {"other": {}}
        conns = ConnectionHandler(DATABASES)
        msg = "You must define a 'default' database."
        with self.assertRaisesMessage(ImproperlyConfigured, msg):
            conns["other"].ensure_connection()

    def test_databases_property(self):
        
        
        
        conn = ConnectionHandler({})
        self.assertNotEqual(conn.settings, {})
        self.assertEqual(conn.settings, conn.databases)

    def test_nonexistent_alias(self):
        msg = "The connection 'nonexistent' doesn't exist."
        conns = ConnectionHandler(
            {
                DEFAULT_DB_ALIAS: {"ENGINE": "django.db.backends.dummy"},
            }
        )
        with self.assertRaisesMessage(ConnectionDoesNotExist, msg):
            conns["nonexistent"]


class DatabaseErrorWrapperTests(TestCase):
    @unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL test")
    def test_reraising_backend_specific_database_exception(self):
        from django.db.backends.postgresql.psycopg_any import is_psycopg3

        with connection.cursor() as cursor:
            msg = 'table "X" does not exist'
            with self.assertRaisesMessage(ProgrammingError, msg) as cm:
                cursor.execute('DROP TABLE "X"')
        self.assertNotEqual(type(cm.exception), type(cm.exception.__cause__))
        self.assertIsNotNone(cm.exception.__cause__)
        if is_psycopg3:
            self.assertIsNotNone(cm.exception.__cause__.diag.sqlstate)
            self.assertIsNotNone(cm.exception.__cause__.diag.message_primary)
        else:
            self.assertIsNotNone(cm.exception.__cause__.pgcode)
            self.assertIsNotNone(cm.exception.__cause__.pgerror)


class LoadBackendTests(SimpleTestCase):
    def test_load_backend_invalid_name(self):
        msg = (
            "'foo' isn't an available database backend or couldn't be "
            "imported. Check the above exception. To use one of the built-in "
            "backends, use 'django.db.backends.XXX', where XXX is one of:\n"
            "    'mysql', 'oracle', 'postgresql', 'sqlite3'"
        )
        with self.assertRaisesMessage(ImproperlyConfigured, msg) as cm:
            load_backend("foo")
        self.assertEqual(str(cm.exception.__cause__), "No module named 'foo'")