view piecrust/commands/builtin/serving.py @ 371:c2ca72fb7f0b 2.0.0a8

caching: Use separate caches for config variants and other contexts. * The `_cache` directory is now organized in multiple "sub-caches" for different contexts. * A new context is created when config variants or overrides are applied. * `serve` context uses a different context that the other commends, to prevent the `bake` command's output from messing up the preview server (e.g. with how asset URLs are generated differently between the two). * Fix a few places where the cache directory was referenced directly.
author Ludovic Chabant <ludovic@chabant.com>
date Sun, 03 May 2015 23:59:46 -0700
parents 4f00bb99400e
children fa3ee8a8ee2d
line wrap: on
line source

import logging
from piecrust.serving import Server, _sse_abort
from piecrust.commands.base import ChefCommand


logger = logging.getLogger(__name__)


class ServeCommand(ChefCommand):
    def __init__(self):
        super(ServeCommand, self).__init__()
        self.name = 'serve'
        self.description = "Runs a local web server to serve your website."
        self.cache_name = 'server'

    def setupParser(self, parser, app):
        parser.add_argument(
                '-p', '--port',
                help="The port for the web server",
                default=8080)
        parser.add_argument(
                '-a', '--address',
                help="The host for the web server",
                default='localhost')
        parser.add_argument(
                '--use-reloader',
                help="Restart the server when PieCrust code changes",
                action='store_true')
        parser.add_argument(
                '--use-debugger',
                help="Show the debugger when an error occurs",
                action='store_true')
        parser.add_argument(
                '--wsgi',
                help="The WSGI server implementation to use",
                choices=['werkzeug', 'gunicorn'],
                default='werkzeug')

    def run(self, ctx):
        host = ctx.args.address
        port = int(ctx.args.port)
        debug = ctx.args.debug or ctx.args.use_debugger

        server = Server(
                ctx.app.root_dir,
                debug=debug,
                sub_cache_dir=ctx.app.sub_cache_dir,
                use_reloader=ctx.args.use_reloader)
        app = server.getWsgiApp()

        if ctx.args.wsgi == 'werkzeug':
            from werkzeug.serving import run_simple
            try:
                run_simple(host, port, app,
                           threaded=True,
                           use_debugger=debug,
                           use_reloader=ctx.args.use_reloader)
            finally:
                _sse_abort.set()

        elif ctx.args.wsgi == 'gunicorn':
            from gunicorn.app.base import BaseApplication

            class PieCrustGunicornApplication(BaseApplication):
                def __init__(self, app, options):
                    self.app = app
                    self.options = options
                    super(PieCrustGunicornApplication, self).__init__()

                def load_config(self):
                    for k, v in self.options.items():
                        if k in self.cfg.settings and v is not None:
                            self.cfg.set(k, v)

                def load(self):
                    return self.app

            options = {
                    'bind': '%s:%s' % (host, port),
                    'accesslog': '-',
                    'worker_class': 'gaiohttp',
                    'workers': 2,
                    'timeout': 999999}
            if debug:
                options['loglevel'] = 'debug'
            if ctx.args.use_reloader:
                options['reload'] = True
            app_wrapper = PieCrustGunicornApplication(app, options)
            app_wrapper.run()