Plain is headed towards 1.0! Subscribe for development updates →

 1import signal
 2
 3from plain.models.backends.base.client import BaseDatabaseClient
 4
 5
 6class DatabaseClient(BaseDatabaseClient):
 7    executable_name = "mysql"
 8
 9    @classmethod
10    def settings_to_cmd_args_env(cls, settings_dict, parameters):
11        args = [cls.executable_name]
12        env = None
13        database = settings_dict["OPTIONS"].get(
14            "database",
15            settings_dict["OPTIONS"].get("db", settings_dict["NAME"]),
16        )
17        user = settings_dict["OPTIONS"].get("user", settings_dict["USER"])
18        password = settings_dict["OPTIONS"].get(
19            "password",
20            settings_dict["OPTIONS"].get("passwd", settings_dict["PASSWORD"]),
21        )
22        host = settings_dict["OPTIONS"].get("host", settings_dict["HOST"])
23        port = settings_dict["OPTIONS"].get("port", settings_dict["PORT"])
24        server_ca = settings_dict["OPTIONS"].get("ssl", {}).get("ca")
25        client_cert = settings_dict["OPTIONS"].get("ssl", {}).get("cert")
26        client_key = settings_dict["OPTIONS"].get("ssl", {}).get("key")
27        defaults_file = settings_dict["OPTIONS"].get("read_default_file")
28        charset = settings_dict["OPTIONS"].get("charset")
29        # Seems to be no good way to set sql_mode with CLI.
30
31        if defaults_file:
32            args += ["--defaults-file=%s" % defaults_file]
33        if user:
34            args += ["--user=%s" % user]
35        if password:
36            # The MYSQL_PWD environment variable usage is discouraged per
37            # MySQL's documentation due to the possibility of exposure through
38            # `ps` on old Unix flavors but --password suffers from the same
39            # flaw on even more systems. Usage of an environment variable also
40            # prevents password exposure if the subprocess.run(check=True) call
41            # raises a CalledProcessError since the string representation of
42            # the latter includes all of the provided `args`.
43            env = {"MYSQL_PWD": password}
44        if host:
45            if "/" in host:
46                args += ["--socket=%s" % host]
47            else:
48                args += ["--host=%s" % host]
49        if port:
50            args += ["--port=%s" % port]
51        if server_ca:
52            args += ["--ssl-ca=%s" % server_ca]
53        if client_cert:
54            args += ["--ssl-cert=%s" % client_cert]
55        if client_key:
56            args += ["--ssl-key=%s" % client_key]
57        if charset:
58            args += ["--default-character-set=%s" % charset]
59        if database:
60            args += [database]
61        args.extend(parameters)
62        return args, env
63
64    def runshell(self, parameters):
65        sigint_handler = signal.getsignal(signal.SIGINT)
66        try:
67            # Allow SIGINT to pass to mysql to abort queries.
68            signal.signal(signal.SIGINT, signal.SIG_IGN)
69            super().runshell(parameters)
70        finally:
71            # Restore the original SIGINT handler.
72            signal.signal(signal.SIGINT, sigint_handler)