Repository: translate/pootle

Issue:
Add --host --database --username and --password flags to pootle init
To make it easier when setting up mysql/postgresql for the first time



Discussion:

Resolving patch:
diff --git a/pootle/runner.py b/pootle/runner.py
--- a/pootle/runner.py
+++ b/pootle/runner.py
@@ -23,14 +23,16 @@
 DEFAULT_SETTINGS_PATH = '~/.pootle/pootle.conf'
 
 #: Template that will be used to initialize settings from
-SETTINGS_TEMPLATE_FILENAME = 'settings/90-local.conf.sample'
+SETTINGS_TEMPLATE_FILENAME = 'settings/90-local.conf.template'
 
 # Python 2+3 support for input()
 if sys.version_info[0] < 3:
     input = raw_input
 
 
-def init_settings(settings_filepath, template_filename, db="sqlite"):
+def init_settings(settings_filepath, template_filename,
+                  db="sqlite", db_name="dbs/pootle.db", db_user="",
+                  db_password="", db_host="", db_port=""):
     """Initializes a sample settings file for new installations.
 
     :param settings_filepath: The target file path where the initial settings
@@ -38,6 +40,13 @@ def init_settings(settings_filepath, template_filename, db="sqlite"):
     :param template_filename: Template file used to initialize settings from.
     :param db: Database engine to use
         (default=sqlite, choices=[mysql, postgresql]).
+    :param db_name: Database name (default: pootledb) or path to database file
+        if using sqlite (default: dbs/pootle.db)
+    :param db_user: Name of the database user. Not used with sqlite.
+    :param db_password: Password for the database user. Not used with sqlite.
+    :param db_host: Database host. Defaults to localhost. Not used with sqlite.
+    :param db_port: Database port. Defaults to backend default. Not used with
+        sqlite.
     """
     from base64 import b64encode
 
@@ -45,12 +54,15 @@ def init_settings(settings_filepath, template_filename, db="sqlite"):
     if dirname and not os.path.exists(dirname):
         os.makedirs(dirname)
 
-    fp = open(settings_filepath, 'w')
-
-    output = open(template_filename).read()
-    # We can't use regular python string formatting here.
-    output = output.replace("${default_key}",
-                            b64encode(os.urandom(KEY_LENGTH)).decode("utf-8"))
+    if db == "sqlite":
+        db_name = "working_path('%s')" % (db_name or "dbs/pootle.db")
+        db_user = db_password = db_host = db_port = "''"
+    else:
+        db_name = "'%s'" % (db_name or "pootledb")
+        db_user = "'%s'" % (db_user or "pootle")
+        db_password = "'%s'" % db_password
+        db_host = "'%s'" % db_host
+        db_port = "'%s'" % db_port
 
     db_module = {
         'sqlite': 'sqlite3',
@@ -58,15 +70,20 @@ def init_settings(settings_filepath, template_filename, db="sqlite"):
         'postgresql': 'postgresql_psycopg2',
         }[db]
 
-    output = output.replace("'ENGINE': 'transaction_hooks.backends.sqlite3'",
-                            "'ENGINE': 'transaction_hooks.backends.%s'" % db_module)
-
-    if db != "sqlite":
-        output = output.replace("'NAME': working_path('dbs/pootle.db')",
-                                "'NAME': ''")
+    context = {
+        "default_key": ("'%s'"
+                        % b64encode(os.urandom(KEY_LENGTH)).decode("utf-8")),
+        "db_engine": "'transaction_hooks.backends.%s'" % db_module,
+        "db_name": db_name,
+        "db_user": db_user,
+        "db_password": db_password,
+        "db_host": db_host,
+        "db_port": db_port,
+    }
 
-    fp.write(output)
-    fp.close()
+    with open(settings_filepath, 'w') as settings:
+        with open(template_filename) as template:
+            settings.write(template.read() % context)
 
 
 def configure_app(project, config_path, django_settings_module, runner_name):
@@ -113,6 +130,7 @@ def run_app(project, default_settings_path, settings_template,
         will be set to.
     """
     runner_name = os.path.basename(sys.argv[0])
+    src_dir = os.path.abspath(os.path.dirname(__file__))
 
     parser = ArgumentParser()
 
@@ -122,8 +140,27 @@ def run_app(project, default_settings_path, settings_template,
     parser.add_argument("--noinput", action="store_true", default=False,
                         help=u"Never prompt for input")
     parser.add_argument("--version", action="version", version=get_version())
+
     parser.add_argument("--db", default="sqlite",
-                        help=u"Use the specified database backend")
+                        help=(u"Use the specified database backend (default: "
+                              "'sqlite'; other options: 'mysql', "
+                              "'postgresql')."))
+    parser.add_argument("--db-name", default="",
+                        help=(u"Database name (default: 'pootledb') or path "
+                              "to database file if using sqlite (default: "
+                              "'%s/dbs/pootle.db')" % src_dir))
+    parser.add_argument("--db-user", default="",
+                        help=(u"Name of the database user. Not used with "
+                              "sqlite."))
+    parser.add_argument("--db-password", default="",
+                        help=(u"Password for the database user. Not used with "
+                              "sqlite."))
+    parser.add_argument("--db-host", default="",
+                        help=(u"Database host. Defaults to localhost. Not "
+                              "used with sqlite."))
+    parser.add_argument("--db-port", default="",
+                        help=(u"Database port. Defaults to backend default. "
+                              "Not used with sqlite."))
 
     args, remainder = parser.parse_known_args(sys.argv[1:])
 
@@ -148,14 +185,17 @@ def run_app(project, default_settings_path, settings_template,
                                           "'postgresql'" % args.db)
 
         try:
-            init_settings(config_path, settings_template, args.db)
+            init_settings(config_path, settings_template,
+                          args.db, args.db_name, args.db_user,
+                          args.db_password, args.db_host, args.db_port)
         except (IOError, OSError) as e:
             raise e.__class__('Unable to write default settings file to %r'
                 % config_path)
 
-        if args.db in ["mysql", "postgresql"]:
-            print("Configuration file created at %r: you must now update "
-                  "the settings for %s database" % (config_path, args.db))
+        if args.db in ['mysql', 'postgresql'] and not args.db_password:
+            print("Configuration file created at %r. You have not specified a "
+                  "password for your database. You may want to update the "
+                  "database settings now" % config_path)
         else:
             print("Configuration file created at %r" % config_path)
         exit(0)


Test patch: