def start(server, host, port, workers, config, daemon): """Starts a production ready wsgi server. TODO: Figure out a way how to forward additional args to gunicorn without causing any errors. """ 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 FlaskBBCLIError( "Cannot import gunicorn. " "Make sure it is installed.", fg="red") elif server == "gevent": try: from gevent import __version__ from gevent.pywsgi import WSGIServer click.secho("* Starting gevent {}".format(__version__)) click.secho("* Listening on http://{}:{}/".format(host, port)) http_server = WSGIServer((host, port), create_app(config=config)) http_server.serve_forever() except ImportError: raise FlaskBBCLIError( "Cannot import gevent. " "Make sure it is installed.", fg="red")
def upgrade(all_latest, fixture, force): """Updates the migrations and fixtures.""" if all_latest: click.secho("[+] Upgrading migrations to the latest version...", fg="cyan") alembic.upgrade() if fixture or all_latest: try: settings = import_string("flaskbb.fixtures.{}".format(fixture)) settings = settings.fixture except ImportError: raise FlaskBBCLIError( "{} fixture is not available".format(fixture), fg="red") click.secho("[+] Updating fixtures...", fg="cyan") count = update_settings_from_fixture(fixture=settings, overwrite_group=force, overwrite_setting=force) click.secho("[+] {settings} settings in {groups} setting groups " "updated.".format(groups=len(count), settings=sum( len(settings) for settings in count.values())), fg="green")
def download_emoji(): """Downloads emojis from emoji-cheat-sheet.com. This command is probably going to be removed in future version. """ click.secho("[+] Downloading emojis...", fg="cyan") HOSTNAME = "https://api.github.com" REPO = "/repos/arvida/emoji-cheat-sheet.com/contents/public/graphics/emojis" # noqa FULL_URL = "{}{}".format(HOSTNAME, REPO) DOWNLOAD_PATH = os.path.join(current_app.static_folder, "emoji") response = requests.get(FULL_URL) cached_count = 0 count = 0 for image in response.json(): if not os.path.exists(os.path.abspath(DOWNLOAD_PATH)): raise FlaskBBCLIError("{} does not exist.".format( os.path.abspath(DOWNLOAD_PATH)), fg="red") full_path = os.path.join(DOWNLOAD_PATH, image["name"]) if not os.path.exists(full_path): count += 1 f = open(full_path, 'wb') f.write(requests.get(image["download_url"]).content) f.close() if count == cached_count + 50: cached_count = count click.secho("[+] {} out of {} Emojis downloaded...".format( cached_count, len(response.json())), fg="cyan") click.secho("[+] Finished downloading {} Emojis.".format(count), fg="green")
def change_user(username, email, password, group): """Updates an user. Omit any options to use the interactive mode.""" user = prompt_save_user(username, email, password, group, only_update=True) if user is None: raise FlaskBBCLIError("The user with username {} does not exist." .format(username), fg="red") click.secho("[+] User {} updated.".format(user.username), fg="cyan")
def new_user(username, email, password, group): """Creates a new user. Omit any options to use the interactive mode.""" try: user = prompt_save_user(username, email, password, group) click.secho("[+] User {} with Email {} in Group {} created.".format( user.username, user.email, user.primary_group.name), fg="cyan" ) except IntegrityError: raise FlaskBBCLIError("Couldn't create the user because the " "username or email address is already taken.", fg="red")
def delete_user(username, force): """Deletes an user.""" if not username: username = click.prompt( click.style("Username", fg="magenta"), type=str, default=os.environ.get("USER", "") ) user = User.query.filter_by(username=username).first() if user is None: raise FlaskBBCLIError("The user with username {} does not exist." .format(username), fg="red") if not force and not \ click.confirm(click.style("Are you sure?", fg="magenta")): sys.exit(0) user.delete() click.secho("[+] User {} deleted.".format(user.username), fg="cyan")
def stop(info, pid, force): """Stops the gunicorn process.""" app = info.load_app() pid = get_gunicorn_pid(pid, app.instance_path) if pid is None: raise FlaskBBCLIError( "Neither a valid PID File nor a PID that exist " "was provided.", fg="red") try: if force: os.kill(pid, signal.SIGKILL) else: os.kill(pid, signal.SIGTERM) except ProcessLookupError: click.secho("Process with PID '{}' not found. Are you sure that " "Gunicorn/FlaskBB is running?".format(pid), fg="yellow")
def start(info, host, port, workers, daemon, pid): """Starts a preconfigured gunicorn instance.""" try: from gunicorn.app.base import Application except ImportError: raise FlaskBBCLIError( "Cannot import gunicorn. " "Make sure it is installed.", fg="red") class FlaskBBApplication(Application): def __init__(self, app, options=None, args=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): print(key, value) self.cfg.set(key.lower(), value) def load(self): return self.application flaskbb_app = info.load_app() default_pid = None if os.path.exists(flaskbb_app.instance_path): default_pid = os.path.join(flaskbb_app.instance_path, "flaskbb.pid") options = { "bind": "{}:{}".format(host, port), "workers": workers, "daemon": daemon, "pidfile": pid or default_pid } FlaskBBApplication(flaskbb_app, options).run()