Просмотр исходного кода

Add functionality to start gunicorn from within flaskbb

sh4nks 8 лет назад
Родитель
Сommit
b3bcae0e73
1 измененных файлов с 60 добавлено и 5 удалено
  1. 60 5
      flaskbb/cli.py

+ 60 - 5
flaskbb/cli.py

@@ -21,6 +21,7 @@ from sqlalchemy_utils.functions import database_exists, drop_database
 from flask_migrate import upgrade as upgrade_database
 
 from flaskbb import create_app
+from flaskbb._compat import iteritems
 from flaskbb.extensions import db, plugin_manager, whooshee
 from flaskbb.utils.populate import (create_test_data, create_welcome_forum,
                                     create_user, create_default_groups,
@@ -210,12 +211,66 @@ def upgrade(all, fixture, force_fixture):
 
 
 @cli.command()
-@click.option("--server", "-s", type=click.Choice(["gunicorn"]))
-def start(server):
+@click.option("--server", "-s", default="gunicorn",
+              type=click.Choice(["gunicorn", "gevent"]),
+              help="The WSGI Server to run FlaskBB on.")
+@click.option("--host", "-h", default="127.0.0.1",
+              help="The interface to bind FlaskBB to.")
+@click.option("--port", "-p", default="8000", type=int,
+              help="The port to bind FlaskBB to.")
+@click.option("--workers", "-w", default=4,
+              help="The number of worker processes for handling requests.")
+@click.option("--daemon", "-d", default=False, is_flag=True,
+              help="Starts gunicorn as daemon.")
+@click.option("--config", "-c",
+              help="The configuration file to use for FlaskBB.")
+def start(server, host, port, workers, config, daemon):
     """Starts a production ready wsgi server.
-    TODO: Unsure about this command, would "serve" or "server" be better?
+    TODO: Figure out a way how to forward additional args to gunicorn
+          without causing any errors.
     """
-    click.echo("start()")
+    if server == "gunicorn":
+        try:
+            from gunicorn.app.base import Application
+
+            class FlaskBBApplication(Application):
+                def __init__(self, app, options=None):
+                    self.options = options or {}
+                    self.application = app
+                    super(FlaskBBApplication, self).__init__()
+
+                def load_config(self):
+                    config = dict([
+                        (key, value) for key, value in iteritems(self.options)
+                        if key in self.cfg.settings and value is not None
+                    ])
+                    for key, value in iteritems(config):
+                        self.cfg.set(key.lower(), value)
+
+                def load(self):
+                    return self.application
+
+            options = {
+                "bind": "{}:{}".format(host, port),
+                "workers": workers,
+                "daemon": daemon,
+            }
+            FlaskBBApplication(create_app(config=config), options).run()
+        except ImportError:
+            raise click.ClickException("Cannot import gunicorn. "
+                                       "Make sure it is installed.")
+
+    elif server == "gevent":
+        try:
+            from gevent import __version__
+            from gevent.pywsgi import WSGIServer
+            click.echo("* Starting gevent {}".format(__version__))
+            click.echo("* Listening on http://{}:{}/".format(host, port))
+            http_server = WSGIServer((host, port), create_app(config=config))
+            http_server.serve_forever()
+        except ImportError:
+            raise click.ClickException("Cannot import gevent. "
+                                       "Make sure it is installed.")
 
 
 @cli.command("shell", short_help="Runs a shell in the app context.")
@@ -241,7 +296,7 @@ def shell_command():
         app.debug and " [debug]" or "",
         app.instance_path,
     )
-    ctx = {}
+    ctx = {"db": db}
 
     # Support the regular Python interpreter startup script if someone
     # is using it.