Plain is headed towards 1.0! Subscribe for development updates →

 1from __future__ import annotations
 2
 3import sys
 4from typing import Any
 5
 6from psycopg import errors  # type: ignore[import-untyped]
 7
 8from plain.exceptions import ImproperlyConfigured
 9from plain.models.backends.base.creation import BaseDatabaseCreation
10
11
12class DatabaseCreation(BaseDatabaseCreation):
13    def _quote_name(self, name: str) -> str:
14        return self.connection.ops.quote_name(name)
15
16    def _get_database_create_suffix(
17        self, encoding: str | None = None, template: str | None = None
18    ) -> str:
19        suffix = ""
20        if encoding:
21            suffix += f" ENCODING '{encoding}'"
22        if template:
23            suffix += f" TEMPLATE {self._quote_name(template)}"
24        return suffix and "WITH" + suffix
25
26    def sql_table_creation_suffix(self) -> str:
27        test_settings = self.connection.settings_dict["TEST"]
28        if test_settings.get("COLLATION") is not None:
29            raise ImproperlyConfigured(
30                "PostgreSQL does not support collation setting at database "
31                "creation time."
32            )
33        return self._get_database_create_suffix(
34            encoding=test_settings["CHARSET"],
35            template=test_settings.get("TEMPLATE"),
36        )
37
38    def _execute_create_test_db(self, cursor: Any, parameters: dict[str, Any]) -> None:
39        try:
40            super()._execute_create_test_db(cursor, parameters)
41        except Exception as e:
42            cause = e.__cause__
43            if cause and not isinstance(cause, errors.DuplicateDatabase):
44                # All errors except "database already exists" cancel tests.
45                self.log(f"Got an error creating the test database: {e}")
46                sys.exit(2)
47            else:
48                raise