File: base_impl.py

package info (click to toggle)
python-django-postgres-extra 2.0.9-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,096 kB
  • sloc: python: 9,057; makefile: 17; sh: 7; sql: 1
file content (112 lines) | stat: -rw-r--r-- 3,563 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import importlib

from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.db import DEFAULT_DB_ALIAS, connections
from django.db.backends.postgresql.base import DatabaseWrapper
from django.db.backends.postgresql.introspection import (  # type: ignore[import]
    DatabaseIntrospection,
)
from django.db.backends.postgresql.operations import DatabaseOperations
from django.db.backends.postgresql.schema import (  # type: ignore[import]
    DatabaseSchemaEditor,
)

from django.db.backends.postgresql.base import (  # isort:skip
    DatabaseWrapper as Psycopg2DatabaseWrapper,
)


def base_backend_instance():
    """Gets an instance of the base class for the custom database back-end.

    This should be the Django PostgreSQL back-end. However,
    some people are already using a custom back-end from
    another package. We are nice people and expose an option
    that allows them to configure the back-end we base upon.

    As long as the specified base eventually also has
    the PostgreSQL back-end as a base, then everything should
    work as intended.

    We create an instance to inspect what classes to subclass
    because not all back-ends set properties such as `ops_class`
    properly. The PostGIS back-end is a good example.
    """
    base_class_name = getattr(
        settings,
        "POSTGRES_EXTRA_DB_BACKEND_BASE",
        "django.db.backends.postgresql",
    )

    base_class_module = importlib.import_module(base_class_name + ".base")
    base_class = getattr(base_class_module, "DatabaseWrapper", None)

    if not base_class:
        raise ImproperlyConfigured(
            (
                "'%s' is not a valid database back-end."
                " The module does not define a DatabaseWrapper class."
                " Check the value of POSTGRES_EXTRA_DB_BACKEND_BASE."
            )
            % base_class_name
        )

    if isinstance(base_class, Psycopg2DatabaseWrapper):
        raise ImproperlyConfigured(
            (
                "'%s' is not a valid database back-end."
                " It does inherit from the PostgreSQL back-end."
                " Check the value of POSTGRES_EXTRA_DB_BACKEND_BASE."
            )
            % base_class_name
        )

    base_instance = base_class(connections.databases[DEFAULT_DB_ALIAS])
    if base_instance.connection:
        raise ImproperlyConfigured(
            (
                "'%s' establishes a connection during initialization."
                " This is not expected and can lead to more connections"
                " being established than neccesarry."
            )
            % base_class_name
        )

    return base_instance


def backend() -> DatabaseWrapper:
    """Gets the base class for the database back-end."""

    return base_backend_instance().__class__


def schema_editor() -> DatabaseSchemaEditor:
    """Gets the base class for the schema editor.

    We have to use the configured base back-end's schema editor for
    this.
    """

    return base_backend_instance().SchemaEditorClass


def introspection() -> DatabaseIntrospection:
    """Gets the base class for the introspection class.

    We have to use the configured base back-end's introspection class
    for this.
    """

    return base_backend_instance().introspection.__class__


def operations() -> DatabaseOperations:
    """Gets the base class for the operations class.

    We have to use the configured base back-end's operations class for
    this.
    """

    return base_backend_instance().ops.__class__