Beispiel #1
0
 def test_None_conjunction(self):
     assert bus.nice_join(["one"], conjuction=None) == "one"
     assert bus.nice_join(["one", "two"], conjuction=None) == "one, two"
     assert bus.nice_join(["one", "two", "three"],
                          conjuction=None) == "one, two, three"
     assert bus.nice_join(["one", "two", "three", "four"],
                          conjuction=None) == "one, two, three, four"
Beispiel #2
0
 def test_string_conjunction(self):
     assert bus.nice_join(["one"], conjuction="and") == "one"
     assert bus.nice_join(["one", "two"], conjuction="and") == "one and two"
     assert bus.nice_join(["one", "two", "three"],
                          conjuction="and") == "one, two and three"
     assert bus.nice_join(["one", "two", "three", "four"],
                          conjuction="and") == "one, two, three and four"
Beispiel #3
0
 def test_sep(self):
     assert bus.nice_join(["one"], sep='; ') == "one"
     assert bus.nice_join(["one", "two"], sep='; ') == "one or two"
     assert bus.nice_join(["one", "two", "three"],
                          sep='; ') == "one; two or three"
     assert bus.nice_join(["one", "two", "three", "four"],
                          sep="; ") == "one; two; three or four"
Beispiel #4
0
def main(argv):
    ''' Execute the Bokeh command.

    Args:
        argv (seq[str]) : a list of command line arguments to process

    Returns:
        None

    '''
    if len(argv) == 1:
        die("ERROR: Must specify subcommand, one of: %s" % nice_join(x.name for x in subcommands.all))

    parser = argparse.ArgumentParser(prog=argv[0])

    # we don't use settings.version() because the point of this option
    # is to report the actual version of Bokeh, while settings.version()
    # lets people change the version used for CDN for example.
    parser.add_argument('-v', '--version', action='version', version=__version__)

    subs = parser.add_subparsers(help="Sub-commands")

    for cls in subcommands.all:
        subparser = subs.add_parser(cls.name, help=cls.help)
        subcommand = cls(parser=subparser)
        subparser.set_defaults(invoke=subcommand.invoke)

    args = parser.parse_args(argv[1:])
    try:
        args.invoke(args)
    except Exception as e:
        die(str(e))
Beispiel #5
0
def main(argv):
    ''' Execute the Bokeh command.

    Args:
        argv (seq[str]) : a list of command line arguments to process

    Returns:
        None

    '''
    if len(argv) == 1:
        die("ERROR: Must specify subcommand, one of: %s" % nice_join(x.name for x in subcommands.all))

    parser = argparse.ArgumentParser(prog=argv[0])

    # does this get set by anything other than BOKEH_VERSION env var?
    version = settings.version()
    if not version:
        version = "unknown version"
    parser.add_argument('-v', '--version', action='version', version=version)

    subs = parser.add_subparsers(help="Sub-commands")

    for cls in subcommands.all:
        subparser = subs.add_parser(cls.name, help=cls.help)
        subcommand = cls(parser=subparser)
        subparser.set_defaults(invoke=subcommand.invoke)

    args = parser.parse_args(argv[1:])
    try:
        args.invoke(args)
    except Exception as e:
        die(str(e))
Beispiel #6
0
def main(argv):
    ''' Exectute the Bokeh command.

    Args:
        argv (seq[str]) : a list of command line arguments to process

    Returns:
        None

    '''
    if len(argv) == 1:
        die("ERROR: Must specify subcommand, one of: %s" %
            nice_join(x.name for x in subcommands.all))

    parser = argparse.ArgumentParser(prog=argv[0])

    # does this get set by anything other than BOKEH_VERSION env var?
    version = settings.version()
    if not version:
        version = "unknown version"
    parser.add_argument('-v', '--version', action='version', version=version)

    subs = parser.add_subparsers(help="Sub-commands")

    for cls in subcommands.all:
        subparser = subs.add_parser(cls.name, help=cls.help)
        subcommand = cls(parser=subparser)
        subparser.set_defaults(invoke=subcommand.invoke)

    args = parser.parse_args(argv[1:])
    try:
        args.invoke(args)
    except Exception as e:
        die(str(e))
Beispiel #7
0
def main(argv):
    ''' Execute the Bokeh command.

    Args:
        argv (seq[str]) : a list of command line arguments to process

    Returns:
        None

    The first item in ``argv`` is typically "bokeh", and the second should
    be the name of one of the available subcommands:

    * :ref:`html <bokeh.command.subcommands.html>`
    * :ref:`info <bokeh.command.subcommands.info>`
    * :ref:`json <bokeh.command.subcommands.json>`
    * :ref:`png <bokeh.command.subcommands.png>`
    * :ref:`sampledata <bokeh.command.subcommands.sampledata>`
    * :ref:`secret <bokeh.command.subcommands.secret>`
    * :ref:`serve <bokeh.command.subcommands.serve>`
    * :ref:`static <bokeh.command.subcommands.static>`
    * :ref:`svg <bokeh.command.subcommands.svg>`

    '''
    if len(argv) == 1:
        die("ERROR: Must specify subcommand, one of: %s" %
            nice_join(x.name for x in subcommands.all))

    parser = argparse.ArgumentParser(
        prog=argv[0],
        epilog="See '<command> --help' to read about a specific subcommand.")

    # we don't use settings.version() because the point of this option
    # is to report the actual version of Bokeh, while settings.version()
    # lets people change the version used for CDN for example.
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=__version__)

    subs = parser.add_subparsers(help="Sub-commands")

    for cls in subcommands.all:
        subparser = subs.add_parser(cls.name, help=cls.help)
        subcommand = cls(parser=subparser)
        subparser.set_defaults(invoke=subcommand.invoke)

    args = parser.parse_args(argv[1:])
    try:
        ret = args.invoke(args)
    except Exception as e:
        if settings.dev:
            raise
        else:
            die("ERROR: " + str(e))

    if ret is False:
        sys.exit(1)
    elif ret is not True and isinstance(ret, int) and ret != 0:
        sys.exit(ret)
Beispiel #8
0
def main(args=None):
    """Merges commands offered by pyct and bokeh and provides help for both"""
    from bokeh.command.subcommands import all as bokeh_commands

    try:
        import pyct.cmd
        pyct_commands = ['copy-examples', 'examples']
    except Exception:
        pass

    parser = argparse.ArgumentParser(
        prog="panel",
        epilog="See '<command> --help' to read about a specific subcommand.")

    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=__version__)

    subs = parser.add_subparsers(help="Sub-commands")

    for cmd in pyct_commands:
        cmd = cmd.replace('-', '_')
        fn = getattr(pyct.cmd, cmd)
        subs.add_parser(cmd, help=fn.__doc__)

    for cls in bokeh_commands:
        subs.add_parser(cls.name, help=cls.help)

    if len(sys.argv) == 1:
        all_commands = sorted([c.name for c in bokeh_commands] + pyct_commands)
        die("ERROR: Must specify subcommand, one of: %s" %
            nice_join(all_commands))

    if sys.argv[1] in ('--help', '-h'):
        args = parser.parse_args(sys.argv[1:])
        args.invoke(args)
        sys.exit()

    if len(sys.argv) > 1 and any(sys.argv[1] == c.name
                                 for c in bokeh_commands):
        if sys.argv[1] == 'serve' and not any(
                arg.startswith('--index') for arg in sys.argv):
            sys.argv = sys.argv + ['--index=%s' % INDEX_HTML]
        sys.argv = transform_cmds(sys.argv)
        bokeh_entry_point()
    elif sys.argv[1] in pyct_commands:
        try:
            import pyct.cmd
        except ImportError:
            print(
                "install pyct to enable this command (e.g. `conda install -c pyviz pyct` or `pip install pyct[cmd]`)"
            )
            sys.exit(1)
        pyct.cmd.substitute_main('panel', cmds=pyct_commands, args=args)
    else:
        parser.parse_args(sys.argv[1:])
        sys.exit(1)
Beispiel #9
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (

        ('files', dict(
            metavar='DIRECTORY-OR-SCRIPT',
            nargs='*',
            help="The app directories or scripts to serve (serve empty document if not specified)",
            default=None,
        )),

        ('--develop', dict(
            action='store_true',
            help="Enable develop-time features that should not be used in production",
        )),

        ('--show', dict(
            action='store_true',
            help="Open server app(s) in a browser",
        )),

        ('--port', dict(
            metavar='PORT',
            type=int,
            help="Port to listen on",
            default=None
        )),

        ('--address', dict(
            metavar='ADDRESS',
            type=str,
            help="Address to listen on",
            default=None,
        )),

        ('--keep-alive', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to send a keep-alive ping to clients, 0 to disable.",
            default=None,
        )),

        ('--log-level', dict(
            metavar='LOG-LEVEL',
            action  = 'store',
            default = 'debug',
            choices = scserve.LOGLEVELS,
            help    = "One of: %s" % nice_join(scserve.LOGLEVELS),
        )),

    )
Beispiel #10
0
def main(argv):
    ''' Execute the Bokeh command.

    Args:
        argv (seq[str]) : a list of command line arguments to process

    Returns:
        None

    The first item in ``argv`` is typically "bokeh", and the second should
    be the name of one of the available subcommands:

    * :ref:`html <bokeh.command.subcommands.html>`
    * :ref:`info <bokeh.command.subcommands.info>`
    * :ref:`json <bokeh.command.subcommands.json>`
    * :ref:`png <bokeh.command.subcommands.png>`
    * :ref:`sampledata <bokeh.command.subcommands.sampledata>`
    * :ref:`secret <bokeh.command.subcommands.secret>`
    * :ref:`serve <bokeh.command.subcommands.serve>`
    * :ref:`static <bokeh.command.subcommands.static>`
    * :ref:`svg <bokeh.command.subcommands.svg>`

    '''
    if len(argv) == 1:
        die("ERROR: Must specify subcommand, one of: %s" % nice_join(x.name for x in subcommands.all))

    parser = argparse.ArgumentParser(
        prog=argv[0],
        epilog="See '<command> --help' to read about a specific subcommand.")

    # we don't use settings.version() because the point of this option
    # is to report the actual version of Bokeh, while settings.version()
    # lets people change the version used for CDN for example.
    parser.add_argument('-v', '--version', action='version', version=__version__)

    subs = parser.add_subparsers(help="Sub-commands")

    for cls in subcommands.all:
        subparser = subs.add_parser(cls.name, help=cls.help)
        subcommand = cls(parser=subparser)
        subparser.set_defaults(invoke=subcommand.invoke)

    args = parser.parse_args(argv[1:])
    try:
        args.invoke(args)
    except Exception as e:
        die("ERROR: " + str(e))
Beispiel #11
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--develop',
         dict(
             action='store_true',
             help=
             "Enable develop-time features that should not be used in production",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--port',
         dict(
             metavar='PORT',
             type=int,
             help="Port to listen on",
             default=scserve.DEFAULT_PORT,
         )),
        ('--address',
         dict(
             metavar='ADDRESS',
             type=str,
             help="Address to listen on",
             default=None,
         )),
        ('--log-level',
         dict(
             metavar='LOG-LEVEL',
             action='store',
             default='debug',
             choices=scserve.LOGLEVELS,
             help="One of: %s" % nice_join(scserve.LOGLEVELS),
         )),
    )
Beispiel #12
0
def main(argv):
    ''' Execute the Bokeh command.

    Args:
        argv (seq[str]) : a list of command line arguments to process

    Returns:
        None

    The first item in ``argv`` is typically "bokeh", and the second should
    be the name of one of the available subcommands:

    * {subcmds}

    '''
    if len(argv) == 1:
        die("ERROR: Must specify subcommand, one of: %s" %
            nice_join(x.name for x in subcommands.all))

    parser = argparse.ArgumentParser(prog=argv[0])

    # we don't use settings.version() because the point of this option
    # is to report the actual version of Bokeh, while settings.version()
    # lets people change the version used for CDN for example.
    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=__version__)

    subs = parser.add_subparsers(help="Sub-commands")

    for cls in subcommands.all:
        subparser = subs.add_parser(cls.name, help=cls.help)
        subcommand = cls(parser=subparser)
        subparser.set_defaults(invoke=subcommand.invoke)

    args = parser.parse_args(argv[1:])
    try:
        args.invoke(args)
    except Exception as e:
        die("ERROR:" + str(e))
Beispiel #13
0
from bokeh.server.server import Server
from bokeh.util.string import nice_join
from bokeh.settings import settings

from os import getpid

from ..subcommand import Subcommand
from ..util import build_single_handler_applications, die

LOGLEVELS = ('debug', 'info', 'warning', 'error', 'critical')
SESSION_ID_MODES = ('unsigned', 'signed', 'external-signed')
DEFAULT_LOG_FORMAT = "%(asctime)s %(message)s"

__doc__ = __doc__.format(
    DEFAULT_PORT=DEFAULT_SERVER_PORT,
    LOGLEVELS=nice_join(LOGLEVELS),
    SESSION_ID_MODES=nice_join(SESSION_ID_MODES),
    DEFAULT_LOG_FORMAT=DEFAULT_LOG_FORMAT
)

base_serve_args = (
    ('--port', dict(
        metavar = 'PORT',
        type    = int,
        help    = "Port to listen on",
        default = None
    )),

    ('--address', dict(
        metavar = 'ADDRESS',
        type    = str,
Beispiel #14
0
class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = base_serve_args + (
        ('files', dict(
            metavar='DIRECTORY-OR-SCRIPT',
            nargs='*',
            help="The app directories or scripts to serve (serve empty document if not specified)",
            default=None,
        )),

        ('--args', dict(
            metavar='COMMAND-LINE-ARGS',
            nargs=argparse.REMAINDER,
            help="Any command line arguments remaining are passed on to the application handler",
        )),

        ('--develop', dict(
            action='store_true',
            help="Enable develop-time features that should not be used in production",
        )),

        ('--show', dict(
            action='store_true',
            help="Open server app(s) in a browser",
        )),

        ('--allow-websocket-origin', dict(
            metavar='HOST[:PORT]',
            action='append',
            type=str,
            help="Public hostnames which may connect to the Bokeh websocket",
        )),

        ('--host', dict(
            metavar='HOST[:PORT]',
            action='append',
            type=str,
            help="Public hostnames to allow in requests",
        )),

        ('--prefix', dict(
            metavar='PREFIX',
            type=str,
            help="URL prefix for Bokeh server URLs",
            default=None,
        )),

        ('--keep-alive', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to send a keep-alive ping to clients, 0 to disable.",
            default=None,
        )),

        ('--check-unused-sessions', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to check for unused sessions",
            default=None,
        )),

        ('--unused-session-lifetime', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How long unused sessions last",
            default=None,
        )),

        ('--stats-log-frequency', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to log stats",
            default=None,
        )),

        ('--use-xheaders', dict(
            action='store_true',
            help="Prefer X-headers for IP/protocol information",
        )),

        ('--session-ids', dict(
            metavar='MODE',
            action  = 'store',
            default = None,
            choices = SESSION_ID_MODES,
            help    = "One of: %s" % nice_join(SESSION_ID_MODES),
        )),
    )

    def invoke(self, args):
        argvs = { f : args.args for f in args.files}
        applications = build_single_handler_applications(args.files, argvs)

        log_level = getattr(logging, args.log_level.upper())
        logging.basicConfig(level=log_level, format=args.log_format)

        if len(applications) == 0:
            # create an empty application by default, typically used with output_server
            applications['/'] = Application()

        if args.keep_alive is not None:
            if args.keep_alive == 0:
                log.info("Keep-alive ping disabled")
            else:
                log.info("Keep-alive ping configured every %d milliseconds", args.keep_alive)
            # rename to be compatible with Server
            args.keep_alive_milliseconds = args.keep_alive

        if args.check_unused_sessions is not None:
            log.info("Check for unused sessions every %d milliseconds", args.check_unused_sessions)
            # rename to be compatible with Server
            args.check_unused_sessions_milliseconds = args.check_unused_sessions

        if args.unused_session_lifetime is not None:
            log.info("Unused sessions last for %d milliseconds", args.unused_session_lifetime)
            # rename to be compatible with Server
            args.unused_session_lifetime_milliseconds = args.unused_session_lifetime

        if args.stats_log_frequency is not None:
            log.info("Log statistics every %d milliseconds", args.stats_log_frequency)
            # rename to be compatible with Server
            args.stats_log_frequency_milliseconds = args.stats_log_frequency

        server_kwargs = { key: getattr(args, key) for key in ['port',
                                                              'address',
                                                              'allow_websocket_origin',
                                                              'host',
                                                              'prefix',
                                                              'develop',
                                                              'keep_alive_milliseconds',
                                                              'check_unused_sessions_milliseconds',
                                                              'unused_session_lifetime_milliseconds',
                                                              'stats_log_frequency_milliseconds',
                                                              'use_xheaders',
                                                            ]
                          if getattr(args, key, None) is not None }

        server_kwargs['sign_sessions'] = settings.sign_sessions()
        server_kwargs['secret_key'] = settings.secret_key_bytes()
        server_kwargs['generate_session_ids'] = True
        if args.session_ids is None:
            # no --session-ids means use the env vars
            pass
        elif args.session_ids == 'unsigned':
            server_kwargs['sign_sessions'] = False
        elif args.session_ids == 'signed':
            server_kwargs['sign_sessions'] = True
        elif args.session_ids == 'external-signed':
            server_kwargs['sign_sessions'] = True
            server_kwargs['generate_session_ids'] = False
        else:
            raise RuntimeError("argparse should have filtered out --session-ids mode " +
                               args.session_ids)

        if server_kwargs['sign_sessions'] and not server_kwargs['secret_key']:
            die("To sign sessions, the BOKEH_SECRET_KEY environment variable must be set; " +
                "the `bokeh secret` command can be used to generate a new key.")

        server = Server(applications, **server_kwargs)

        if args.show:
            # we have to defer opening in browser until we start up the server
            def show_callback():
                for route in applications.keys():
                    server.show(route)
            server.io_loop.add_callback(show_callback)

        if args.develop:
            log.info("Using develop mode (do not enable --develop in production)")

        address_string = ''
        if server.address is not None and server.address != '':
            address_string = ' address ' + server.address

        log.info("Starting Bokeh server on port %d%s with applications at paths %r",
                 server.port,
                 address_string,
                 sorted(applications.keys()))

        log.info("Starting Bokeh server with process id: %d" % getpid())

        server.start()
Beispiel #15
0
from bokeh.application import Application
from bokeh.resources import DEFAULT_SERVER_PORT
from bokeh.server.server import Server
from bokeh.util.string import nice_join
from bokeh.settings import settings

from ..subcommand import Subcommand
from ..util import build_single_handler_applications, die

LOGLEVELS = ('debug', 'info', 'warning', 'error', 'critical')
SESSION_ID_MODES = ('unsigned', 'signed', 'external-signed')
DEFAULT_LOG_FORMAT = "%(asctime)s %(message)s"

__doc__ = __doc__.format(DEFAULT_PORT=DEFAULT_SERVER_PORT,
                         LOGLEVELS=nice_join(LOGLEVELS),
                         SESSION_ID_MODES=nice_join(SESSION_ID_MODES),
                         DEFAULT_LOG_FORMAT=DEFAULT_LOG_FORMAT)


class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = (
        ('files',
Beispiel #16
0
from bokeh.util.logconfig import basicConfig
from bokeh.util.string import nice_join, format_docstring
from bokeh.settings import settings

from os import getpid

from ..subcommand import Subcommand
from ..util import build_single_handler_applications, die, report_server_init_errors

LOGLEVELS = ('debug', 'info', 'warning', 'error', 'critical')
SESSION_ID_MODES = ('unsigned', 'signed', 'external-signed')
DEFAULT_LOG_FORMAT = "%(asctime)s %(message)s"

__doc__ = format_docstring(__doc__,
                           DEFAULT_PORT=DEFAULT_SERVER_PORT,
                           LOGLEVELS=nice_join(LOGLEVELS),
                           SESSION_ID_MODES=nice_join(SESSION_ID_MODES),
                           DEFAULT_LOG_FORMAT=DEFAULT_LOG_FORMAT)


def _fixup_deprecated_host_args(args):
    if args.host is not None and len(args.host) > 0:
        if args.allow_websocket_origin is None:
            args.allow_websocket_origin = []
        args.allow_websocket_origin += args.host
        args.allow_websocket_origin = list(set(args.allow_websocket_origin))
        warnings.warn(
            "The --host parameter is deprecated because it is no longer needed. "
            "It will be removed and trigger an error in a future release. "
            "Values set now will be copied to --allow-websocket-origin. "
            "Depending on your use case, you may need to set current --host "
Beispiel #17
0
from bokeh.application import Application
from bokeh.resources import DEFAULT_SERVER_PORT
from bokeh.server.server import Server
from bokeh.util.string import nice_join
from bokeh.settings import settings

from ..subcommand import Subcommand
from ..util import build_single_handler_applications, die

LOGLEVELS = ('debug', 'info', 'warning', 'error', 'critical')
SESSION_ID_MODES = ('unsigned', 'signed', 'external-signed')

__doc__ = __doc__.format(
    DEFAULT_PORT=DEFAULT_SERVER_PORT,
    LOGLEVELS=nice_join(LOGLEVELS),
    SESSION_ID_MODES=nice_join(SESSION_ID_MODES)
)

class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = (

        ('files', dict(
Beispiel #18
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--develop',
         dict(
             action='store_true',
             help=
             "Enable develop-time features that should not be used in production",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--port',
         dict(metavar='PORT', type=int, help="Port to listen on",
              default=None)),
        ('--address',
         dict(
             metavar='ADDRESS',
             type=str,
             help="Address to listen on",
             default=None,
         )),
        ('--allow-websocket-origin',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames which may connect to the Bokeh websocket",
         )),
        ('--host',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames to allow in requests",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--log-level',
         dict(
             metavar='LOG-LEVEL',
             action='store',
             default='debug',
             choices=scserve.LOGLEVELS,
             help="One of: %s" % nice_join(scserve.LOGLEVELS),
         )),
        ('--session-ids',
         dict(
             metavar='MODE',
             action='store',
             default=None,
             choices=scserve.SESSION_ID_MODES,
             help="One of: %s" % nice_join(scserve.SESSION_ID_MODES),
         )),
    )
Beispiel #19
0
import logging
log = logging.getLogger(__name__)

from bokeh.application import Application
from bokeh.resources import DEFAULT_SERVER_PORT
from bokeh.server.server import Server
from bokeh.util.string import nice_join

from ..subcommand import Subcommand
from ..util import build_single_handler_applications

LOGLEVELS = ('debug', 'info', 'warning', 'error', 'critical')

__doc__ = __doc__.format(DEFAULT_PORT=DEFAULT_SERVER_PORT,
                         LOGLEVELS=nice_join(LOGLEVELS))


class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
Beispiel #20
0
import logging
log = logging.getLogger(__name__)

from bokeh.application import Application
from bokeh.resources import DEFAULT_SERVER_PORT
from bokeh.server.server import Server
from bokeh.util.string import nice_join

from ..subcommand import Subcommand
from ..util import build_single_handler_applications

LOGLEVELS = ('debug', 'info', 'warning', 'error', 'critical')

__doc__ = __doc__.format(
    DEFAULT_PORT=DEFAULT_SERVER_PORT,
    LOGLEVELS=nice_join(LOGLEVELS)
)

class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = (

        ('files', dict(
            metavar='DIRECTORY-OR-SCRIPT',
Beispiel #21
0
class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    #: name for this subcommand
    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = base_serve_args + (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--args',
         dict(
             metavar='COMMAND-LINE-ARGS',
             nargs=argparse.REMAINDER,
             help=
             "Any command line arguments remaining are passed on to the application handler",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--allow-websocket-origin',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames which may connect to the Bokeh websocket",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--check-unused-sessions',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to check for unused sessions",
             default=None,
         )),
        ('--unused-session-lifetime',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How long unused sessions last",
             default=None,
         )),
        ('--stats-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log stats",
             default=None,
         )),
        ('--mem-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log memory usage information",
             default=None,
         )),
        ('--use-xheaders',
         dict(
             action='store_true',
             help="Prefer X-headers for IP/protocol information",
         )),
        ('--session-ids',
         dict(
             metavar='MODE',
             action='store',
             default=None,
             choices=SESSION_ID_MODES,
             help="One of: %s" % nice_join(SESSION_ID_MODES),
         )),
        ('--index',
         dict(
             metavar='INDEX',
             action='store',
             default=None,
             help='Path to a template to use for the site index',
         )),
        ('--disable-index',
         dict(
             action='store_true',
             help='Do not use the default index on the root path',
         )),
        ('--disable-index-redirect',
         dict(
             action='store_true',
             help='Do not redirect to running app from root path',
         )),
        ('--num-procs',
         dict(
             metavar='N',
             action='store',
             help="Number of worker processes for an app. Using "
             "0 will autodetect number of cores (defaults to 1)",
             default=1,
             type=int,
         )),
        ('--websocket-max-message-size',
         dict(
             metavar='BYTES',
             action='store',
             help="Set the Tornado websocket_max_message_size value (defaults "
             "to 20MB) NOTE: This setting has effect ONLY for Tornado>=4.5",
             default=DEFAULT_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES,
             type=int,
         )),
        ('--dev',
         dict(
             metavar='FILES-TO-WATCH',
             action='store',
             default=None,
             type=str,
             nargs='*',
             help="Enable live reloading during app development."
             "By default it watches all *.py *.html *.css *.yaml files"
             "in the app directory tree. Additional files can be passed"
             "as arguments."
             "NOTE: This setting only works with a single app."
             "It also restricts the number of processes to 1.",
         )),
    )

    def invoke(self, args):
        '''

        '''

        # protect this import inside a function so that "bokeh info" can work
        # even if Tornado is not installed
        from bokeh.server.server import Server

        argvs = {f: args.args for f in args.files}
        applications = build_single_handler_applications(args.files, argvs)

        log_level = getattr(logging, args.log_level.upper())
        basicConfig(level=log_level,
                    format=args.log_format,
                    filename=args.log_file)

        if len(applications) == 0:
            # create an empty application by default
            applications['/'] = Application()

        # rename args to be compatible with Server
        if args.keep_alive is not None:
            args.keep_alive_milliseconds = args.keep_alive

        if args.check_unused_sessions is not None:
            args.check_unused_sessions_milliseconds = args.check_unused_sessions

        if args.unused_session_lifetime is not None:
            args.unused_session_lifetime_milliseconds = args.unused_session_lifetime

        if args.stats_log_frequency is not None:
            args.stats_log_frequency_milliseconds = args.stats_log_frequency

        if args.mem_log_frequency is not None:
            args.mem_log_frequency_milliseconds = args.mem_log_frequency

        server_kwargs = {
            key: getattr(args, key)
            for key in [
                'port',
                'address',
                'allow_websocket_origin',
                'num_procs',
                'prefix',
                'index',
                'keep_alive_milliseconds',
                'check_unused_sessions_milliseconds',
                'unused_session_lifetime_milliseconds',
                'stats_log_frequency_milliseconds',
                'mem_log_frequency_milliseconds',
                'use_xheaders',
                'websocket_max_message_size',
            ] if getattr(args, key, None) is not None
        }

        server_kwargs['sign_sessions'] = settings.sign_sessions()
        server_kwargs['secret_key'] = settings.secret_key_bytes()
        server_kwargs['generate_session_ids'] = True
        if args.session_ids is None:
            # no --session-ids means use the env vars
            pass
        elif args.session_ids == 'unsigned':
            server_kwargs['sign_sessions'] = False
        elif args.session_ids == 'signed':
            server_kwargs['sign_sessions'] = True
        elif args.session_ids == 'external-signed':
            server_kwargs['sign_sessions'] = True
            server_kwargs['generate_session_ids'] = False
        else:
            raise RuntimeError(
                "argparse should have filtered out --session-ids mode " +
                args.session_ids)

        if server_kwargs['sign_sessions'] and not server_kwargs['secret_key']:
            die("To sign sessions, the BOKEH_SECRET_KEY environment variable must be set; "
                +
                "the `bokeh secret` command can be used to generate a new key."
                )

        server_kwargs['use_index'] = not args.disable_index
        server_kwargs['redirect_root'] = not args.disable_index_redirect
        server_kwargs['autoreload'] = args.dev is not None

        def find_autoreload_targets(app_path):
            path = os.path.abspath(app_path)
            if not os.path.isdir(path):
                return

            for path, subdirs, files in os.walk(path):
                for name in files:
                    if (fnmatch(name, '*.html') or fnmatch(name, '*.css')
                            or fnmatch(name, '*.yaml')):
                        log.info("Watching: " + os.path.join(path, name))
                        watch(os.path.join(path, name))

        def add_optional_autoreload_files(file_list):
            for filen in file_list:
                if os.path.isdir(filen):
                    log.warning("Cannot watch directory " + filen)
                    continue
                log.info("Watching: " + filen)
                watch(filen)

        if server_kwargs['autoreload']:
            if len(applications.keys()) != 1:
                die("--dev can only support a single app.")
            if server_kwargs['num_procs'] != 1:
                log.info("Running in --dev mode. --num-procs is limited to 1.")
                server_kwargs['num_procs'] = 1

            find_autoreload_targets(args.files[0])
            add_optional_autoreload_files(args.dev)

        with report_server_init_errors(**server_kwargs):
            server = Server(applications, **server_kwargs)

            if args.show:
                # we have to defer opening in browser until we start up the server
                def show_callback():
                    for route in applications.keys():
                        server.show(route)

                server.io_loop.add_callback(show_callback)

            address_string = 'localhost'
            if server.address is not None and server.address != '':
                address_string = server.address

            for route in sorted(applications.keys()):
                url = "http://%s:%d%s%s" % (address_string, server.port,
                                            server.prefix, route)
                log.info("Bokeh app running at: %s" % url)

            log.info("Starting Bokeh server with process id: %d" % os.getpid())
            server.run_until_shutdown()
Beispiel #22
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ("--port", dict(metavar="PORT", type=int, help="Port to listen on", default=None)),
        ("--address", dict(metavar="ADDRESS", type=str, help="Address to listen on", default=None)),
        (
            "--log-level",
            dict(
                metavar="LOG-LEVEL",
                action="store",
                default="info",
                choices=scserve.LOGLEVELS,
                help="One of: %s" % nice_join(scserve.LOGLEVELS),
            ),
        ),
        (
            "--log-format",
            dict(
                metavar="LOG-FORMAT",
                action="store",
                default=scserve.DEFAULT_LOG_FORMAT,
                help="A standard Python logging format string (default: %r)"
                % scserve.DEFAULT_LOG_FORMAT.replace("%", "%%"),
            ),
        ),
        (
            "files",
            dict(
                metavar="DIRECTORY-OR-SCRIPT",
                nargs="*",
                help="The app directories or scripts to serve (serve empty document if not specified)",
                default=None,
            ),
        ),
        (
            "--args",
            dict(
                metavar="COMMAND-LINE-ARGS",
                nargs=argparse.REMAINDER,
                help="Any command line arguments remaining are passed on to the application handler",
            ),
        ),
        (
            "--develop",
            dict(action="store_true", help="Enable develop-time features that should not be used in production"),
        ),
        ("--show", dict(action="store_true", help="Open server app(s) in a browser")),
        (
            "--allow-websocket-origin",
            dict(
                metavar="HOST[:PORT]",
                action="append",
                type=str,
                help="Public hostnames which may connect to the Bokeh websocket",
            ),
        ),
        (
            "--host",
            dict(metavar="HOST[:PORT]", action="append", type=str, help="Public hostnames to allow in requests"),
        ),
        ("--prefix", dict(metavar="PREFIX", type=str, help="URL prefix for Bokeh server URLs", default=None)),
        (
            "--keep-alive",
            dict(
                metavar="MILLISECONDS",
                type=int,
                help="How often to send a keep-alive ping to clients, 0 to disable.",
                default=None,
            ),
        ),
        (
            "--check-unused-sessions",
            dict(metavar="MILLISECONDS", type=int, help="How often to check for unused sessions", default=None),
        ),
        (
            "--unused-session-lifetime",
            dict(metavar="MILLISECONDS", type=int, help="How long unused sessions last", default=None),
        ),
        ("--stats-log-frequency", dict(metavar="MILLISECONDS", type=int, help="How often to log stats", default=None)),
        ("--use-xheaders", dict(action="store_true", help="Prefer X-headers for IP/protocol information")),
        (
            "--session-ids",
            dict(
                metavar="MODE",
                action="store",
                default=None,
                choices=scserve.SESSION_ID_MODES,
                help="One of: %s" % nice_join(scserve.SESSION_ID_MODES),
            ),
        ),
    )
Beispiel #23
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--args',
         dict(
             metavar='COMMAND-LINE-ARGS',
             nargs=argparse.REMAINDER,
             help=
             "Any command line arguments remaining are passed on to the application handler",
         )),
        ('--develop',
         dict(
             action='store_true',
             help=
             "Enable develop-time features that should not be used in production",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--port',
         dict(metavar='PORT', type=int, help="Port to listen on",
              default=None)),
        ('--address',
         dict(
             metavar='ADDRESS',
             type=str,
             help="Address to listen on",
             default=None,
         )),
        ('--allow-websocket-origin',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames which may connect to the Bokeh websocket",
         )),
        ('--host',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames to allow in requests",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--check-unused-sessions',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to check for unused sessions",
             default=None,
         )),
        ('--unused-session-lifetime',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How long unused sessions last",
             default=None,
         )),
        ('--stats-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log stats",
             default=None,
         )),
        ('--use-xheaders',
         dict(
             action='store_true',
             help="Prefer X-headers for IP/protocol information",
         )),
        ('--log-level',
         dict(
             metavar='LOG-LEVEL',
             action='store',
             default='debug',
             choices=scserve.LOGLEVELS,
             help="One of: %s" % nice_join(scserve.LOGLEVELS),
         )),
        ('--log-format',
         dict(
             metavar='LOG-FORMAT',
             action='store',
             default=scserve.DEFAULT_LOG_FORMAT,
             help="A standard Python logging format string (default: %r)" %
             scserve.DEFAULT_LOG_FORMAT.replace("%", "%%"),
         )),
        ('--session-ids',
         dict(
             metavar='MODE',
             action='store',
             default=None,
             choices=scserve.SESSION_ID_MODES,
             help="One of: %s" % nice_join(scserve.SESSION_ID_MODES),
         )),
    )
Beispiel #24
0
class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--develop',
         dict(
             action='store_true',
             help=
             "Enable develop-time features that should not be used in production",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--port',
         dict(
             metavar='PORT',
             type=int,
             help="Port to listen on",
             default=DEFAULT_PORT,
         )),
        ('--address',
         dict(
             metavar='ADDRESS',
             type=str,
             help="Address to listen on",
             default=None,
         )),
        ('--log-level',
         dict(
             metavar='LOG-LEVEL',
             action='store',
             default='debug',
             choices=LOGLEVELS,
             help="One of: %s" % nice_join(LOGLEVELS),
         )),
    )

    def invoke(self, args):
        applications = build_single_handler_applications(args.files)

        log_level = getattr(logging, args.log_level.upper())
        logging.basicConfig(level=log_level)

        if len(applications) == 0:
            # create an empty application by default, typically used with output_server
            applications['/'] = Application()

        server = Server(applications, port=args.port, address=args.address)

        if args.show:
            # we have to defer opening in browser until we start up the server
            def show_callback():
                for route in applications.keys():
                    server.show(route)

            server.io_loop.add_callback(show_callback)

        if args.develop:
            log.info(
                "Using develop mode (do not enable --develop in production)")

        address_string = ''
        if server.address is not None and server.address != '':
            address_string = ' address ' + server.address

        log.info(
            "Starting Bokeh server on port %d%s with applications at paths %r",
            server.port, address_string, sorted(applications.keys()))

        server.start()
Beispiel #25
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ('--port',
         dict(metavar='PORT',
              type=int,
              help="Port to listen on",
              default=DEFAULT_SERVER_PORT)),
        ('--address',
         dict(
             metavar='ADDRESS',
             type=str,
             help="Address to listen on",
             default=None,
         )),
        ('--log-level',
         dict(
             metavar='LOG-LEVEL',
             action='store',
             default='info',
             choices=scserve.LOGLEVELS,
             help="One of: %s" % nice_join(scserve.LOGLEVELS),
         )),
        ('--log-format',
         dict(
             metavar='LOG-FORMAT',
             action='store',
             default=scserve.DEFAULT_LOG_FORMAT,
             help="A standard Python logging format string (default: %r)" %
             scserve.DEFAULT_LOG_FORMAT.replace("%", "%%"),
         )),
        ('--log-file',
         dict(
             metavar='LOG-FILE',
             action='store',
             default=None,
             help=
             "A filename to write logs to, or None to write to the standard stream (default: None)",
         )),
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--args',
         dict(
             metavar='COMMAND-LINE-ARGS',
             nargs=argparse.REMAINDER,
             help=
             "Any command line arguments remaining are passed on to the application handler",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--allow-websocket-origin',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames which may connect to the Bokeh websocket",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--check-unused-sessions',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to check for unused sessions",
             default=None,
         )),
        ('--unused-session-lifetime',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How long unused sessions last",
             default=None,
         )),
        ('--stats-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log stats",
             default=None,
         )),
        ('--mem-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log memory usage information",
             default=None,
         )),
        ('--use-xheaders',
         dict(
             action='store_true',
             help="Prefer X-headers for IP/protocol information",
         )),
        ('--session-ids',
         dict(
             metavar='MODE',
             action='store',
             default=None,
             choices=scserve.SESSION_ID_MODES,
             help="One of: %s" % nice_join(scserve.SESSION_ID_MODES),
         )),
        ('--index',
         dict(
             metavar='INDEX',
             action='store',
             default=None,
             help='Path to a template to use for the site index',
         )),
        ('--disable-index',
         dict(
             action='store_true',
             help='Do not use the default index on the root path',
         )),
        ('--disable-index-redirect',
         dict(
             action='store_true',
             help='Do not redirect to running app from root path',
         )),
        ('--num-procs',
         dict(
             metavar='N',
             action='store',
             help="Number of worker processes for an app. Using "
             "0 will autodetect number of cores (defaults to 1)",
             default=1,
             type=int,
         )),
        ('--websocket-max-message-size',
         dict(
             metavar='BYTES',
             action='store',
             help="Set the Tornado websocket_max_message_size value (defaults "
             "to 20MB) NOTE: This setting has effect ONLY for Tornado>=4.5",
             default=20 * 1024 * 1024,
             type=int,
         )),
        ('--dev',
         dict(
             metavar='FILES-TO-WATCH',
             action='store',
             default=None,
             type=str,
             nargs='*',
             help="Enable live reloading during app development."
             "By default it watches all *.py *.html *.css *.yaml files"
             "in the app directory tree. Additional files can be passed"
             "as arguments."
             "NOTE: This setting only works with a single app."
             "It also restricts the number of processes to 1.",
         )),
    )
Beispiel #26
0
log = logging.getLogger(__name__)

from bokeh.application import Application
from bokeh.resources import DEFAULT_SERVER_PORT
from bokeh.server.server import Server
from bokeh.util.string import nice_join
from bokeh.settings import settings

from ..subcommand import Subcommand
from ..util import build_single_handler_applications, die

LOGLEVELS = ("debug", "info", "warning", "error", "critical")
SESSION_ID_MODES = ("unsigned", "signed", "external-signed")

__doc__ = __doc__.format(
    DEFAULT_PORT=DEFAULT_SERVER_PORT, LOGLEVELS=nice_join(LOGLEVELS), SESSION_ID_MODES=nice_join(SESSION_ID_MODES)
)


class Serve(Subcommand):
    """ Subcommand to launch the Bokeh server.

    """

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = (
        (
            "files",
Beispiel #27
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ('--port',
         dict(metavar='PORT',
              type=int,
              help="Port to listen on",
              default=DEFAULT_SERVER_PORT)),
        ('--address',
         dict(
             metavar='ADDRESS',
             type=str,
             help="Address to listen on",
             default=None,
         )),
        ('--log-level',
         dict(
             metavar='LOG-LEVEL',
             action='store',
             default='info',
             choices=scserve.LOGLEVELS,
             help="One of: %s" % nice_join(scserve.LOGLEVELS),
         )),
        ('--log-format',
         dict(
             metavar='LOG-FORMAT',
             action='store',
             default=scserve.DEFAULT_LOG_FORMAT,
             help="A standard Python logging format string (default: %r)" %
             scserve.DEFAULT_LOG_FORMAT.replace("%", "%%"),
         )),
        ('--log-file',
         dict(
             metavar='LOG-FILE',
             action='store',
             default=None,
             help=
             "A filename to write logs to, or None to write to the standard stream (default: None)",
         )),
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--args',
         dict(
             metavar='COMMAND-LINE-ARGS',
             nargs=argparse.REMAINDER,
             help=
             "Any command line arguments remaining are passed on to the application handler",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--allow-websocket-origin',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames which may connect to the Bokeh websocket",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--check-unused-sessions',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to check for unused sessions",
             default=None,
         )),
        ('--unused-session-lifetime',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How long unused sessions last",
             default=None,
         )),
        ('--stats-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log stats",
             default=None,
         )),
        ('--mem-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log memory usage information",
             default=None,
         )),
        ('--use-xheaders',
         dict(
             action='store_true',
             help="Prefer X-headers for IP/protocol information",
         )),
        ('--session-ids',
         dict(
             metavar='MODE',
             action='store',
             default=None,
             choices=scserve.SESSION_ID_MODES,
             help="One of: %s" % nice_join(scserve.SESSION_ID_MODES),
         )),
        ('--disable-index',
         dict(
             action='store_true',
             help='Do not use the default index on the root path',
         )),
        ('--disable-index-redirect',
         dict(
             action='store_true',
             help='Do not redirect to running app from root path',
         )),
        ('--num-procs',
         dict(
             metavar='N',
             action='store',
             help="Number of worker processes for an app. Default to one. Using "
             "0 will autodetect number of cores",
             default=1,
             type=int,
         )),
    )
Beispiel #28
0
def test_args() -> None:
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ('--port', dict(
            metavar = 'PORT',
            type    = int,
            help    = "Port to listen on",
            default = DEFAULT_SERVER_PORT
        )),

        ('--address', dict(
            metavar = 'ADDRESS',
            type    = str,
            help    = "Address to listen on",
            default = None,
        )),

        ('--log-level', dict(
            metavar = 'LOG-LEVEL',
            action  = 'store',
            default = None,
            choices = scserve.LOGLEVELS + ("None", ),
            help    = "One of: %s" % nice_join(scserve.LOGLEVELS),
        )),

        ('--log-format', dict(
            metavar ='LOG-FORMAT',
            action  = 'store',
            default = scserve.DEFAULT_LOG_FORMAT,
            help    = "A standard Python logging format string (default: %r)" % scserve.DEFAULT_LOG_FORMAT.replace("%", "%%"),
        )),

        ('--log-file', dict(
            metavar ='LOG-FILE',
            action  = 'store',
            default = None,
            help    = "A filename to write logs to, or None to write to the standard stream (default: None)",
        )),

        ('--use-config', dict(
            metavar = 'CONFIG',
            type    = str,
            help    = "Use a YAML config file for settings",
            default = None,
        )),

        ('files', dict(
            metavar = 'DIRECTORY-OR-SCRIPT',
            nargs   = '*',
            help    = "The app directories or scripts to serve (serve empty document if not specified)",
            default = None,
        )),

        ('--args', dict(
            metavar = 'COMMAND-LINE-ARGS',
            nargs   = argparse.REMAINDER,
            help    = "Command line arguments remaining to passed on to the application handler. "
                      "NOTE: if this argument precedes DIRECTORY-OR-SCRIPT then some other argument, e.g. "
                      "--show, must be placed before the directory or script. ",
        )),

        ('--dev', dict(
            metavar ='FILES-TO-WATCH',
            action  ='store',
            default = None,
            type    = str,
            nargs   = '*',
            help    = "Enable live reloading during app development. "
                      "By default it watches all *.py *.html *.css *.yaml files "
                      "in the app directory tree. Additional files can be passed "
                      "as arguments. "
                      "NOTE: if this argument precedes DIRECTORY-OR-SCRIPT then some other argument, e.g "
                      "--show, must be placed before the directory or script. "
                      "NOTE: This setting only works with a single app. "
                      "It also restricts the number of processes to 1. "
                      "NOTE FOR WINDOWS USERS : this option must be invoked using "
                      "'python -m bokeh'. If not Tornado will fail to restart the "
                      "server",
        )),

        ('--show', dict(
            action = 'store_true',
            help   = "Open server app(s) in a browser",
        )),

        ('--allow-websocket-origin', dict(
            metavar = 'HOST[:PORT]',
            action  = 'append',
            type    = str,
            help    = "Public hostnames which may connect to the Bokeh websocket",
        )),

        ('--prefix', dict(
            metavar = 'PREFIX',
            type    = str,
            help    = "URL prefix for Bokeh server URLs",
            default = None,
        )),

        ('--keep-alive', dict(
            metavar = 'MILLISECONDS',
            type    = int,
            help    = "How often to send a keep-alive ping to clients, 0 to disable.",
            default = None,
        )),

        ('--check-unused-sessions', dict(
            metavar = 'MILLISECONDS',
            type    = int,
            help    = "How often to check for unused sessions",
            default = None,
        )),

        ('--unused-session-lifetime', dict(
            metavar = 'MILLISECONDS',
            type    = int,
            help    = "How long unused sessions last",
            default = None,
        )),

        ('--stats-log-frequency', dict(
            metavar = 'MILLISECONDS',
            type    = int,
            help    = "How often to log stats",
            default = None,
        )),

        ('--mem-log-frequency', dict(
            metavar = 'MILLISECONDS',
            type    = int,
            help    = "How often to log memory usage information",
            default = None,
        )),

        ('--use-xheaders', dict(
            action = 'store_true',
            help   = "Prefer X-headers for IP/protocol information",
        )),

        ('--ssl-certfile', dict(
            metavar = 'CERTFILE',
            action  = 'store',
            default = None,
            help    = 'Absolute path to a certificate file for SSL termination',
        )),

        ('--ssl-keyfile', dict(
            metavar = 'KEYFILE',
            action  = 'store',
            default = None,
            help    = 'Absolute path to a private key file for SSL termination',
        )),

        ('--session-ids', dict(
            metavar = 'MODE',
            action  = 'store',
            default = None,
            choices = scserve.SESSION_ID_MODES,
            help    = "One of: %s" % nice_join(scserve.SESSION_ID_MODES),
        )),

        ('--auth-module', dict(
            metavar = 'AUTH_MODULE',
            action  = 'store',
            default = None,
            help    = 'Absolute path to a Python module that implements auth hooks',
        )),

        ('--enable-xsrf-cookies', dict(
            action  = 'store_true',
            default = False,
            help    = 'Whether to enable Tornado support for XSRF cookies. All '
                      'PUT, POST, or DELETE handlers must be properly instrumented '
                      'when this setting is enabled.'
        )),

        ('--exclude-headers', dict(
            action  = 'store',
            default = None,
            nargs='+',
            help    = 'A list of request headers to exclude from the session '
                      'context (by default all headers are included).'
        )),

        ('--exclude-cookies', dict(
            action  = 'store',
            default = None,
            nargs='+',
            help    = 'A list of request cookies to exclude from the session '
                      'context (by default all cookies are included).'
        )),

        ('--include-headers', dict(
            action  = 'store',
            default = None,
            nargs='+',
            help    = 'A list of request headers to make available in the session '
                      'context (by default all headers are included).'
        )),

        ('--include-cookies', dict(
            action  = 'store',
            default = None,
            nargs='+',
            help    = 'A list of request cookies to make available in the session '
                      'context (by default all cookies are included).'
        )),

        ('--cookie-secret', dict(
            metavar = 'COOKIE_SECRET',
            action  = 'store',
            default = None,
            help    = 'Configure to enable getting/setting secure cookies',
        )),

        ('--index', dict(
            metavar = 'INDEX',
            action  = 'store',
            default = None,
            help    = 'Path to a template to use for the site index',
        )),

        ('--disable-index', dict(
            action = 'store_true',
            help   = 'Do not use the default index on the root path',
        )),

        ('--disable-index-redirect', dict(
            action = 'store_true',
            help   = 'Do not redirect to running app from root path',
        )),

        ('--num-procs', dict(
             metavar = 'N',
             action  = 'store',
             help    = "Number of worker processes for an app. Using "
                       "0 will autodetect number of cores (defaults to 1)",
             default = 1,
             type    =int,
         )),

        ('--session-token-expiration', dict(
            metavar = 'N',
            action  = 'store',
            help    = "Duration in seconds that a new session token "
                      "is valid for session creation. After the expiry "
                      "time has elapsed, the token will not be able "
                      "create a new session (defaults to  seconds).",
            default = 300,
            type    = int,
        )),

         ('--websocket-max-message-size', dict(
            metavar = 'BYTES',
            action  = 'store',
            help    = "Set the Tornado websocket_max_message_size value "
                      "(default: 20MB)",
            default = 20*1024*1024,
            type    = int,
        )),

        ('--glob', dict(
            action='store_true',
            help='Process all filename arguments as globs',
        )),
    )
Beispiel #29
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (

        ('files', dict(
            metavar='DIRECTORY-OR-SCRIPT',
            nargs='*',
            help="The app directories or scripts to serve (serve empty document if not specified)",
            default=None,
        )),

        ('--develop', dict(
            action='store_true',
            help="Enable develop-time features that should not be used in production",
        )),

        ('--show', dict(
            action='store_true',
            help="Open server app(s) in a browser",
        )),

        ('--port', dict(
            metavar='PORT',
            type=int,
            help="Port to listen on",
            default=None
        )),

        ('--address', dict(
            metavar='ADDRESS',
            type=str,
            help="Address to listen on",
            default=None,
        )),

        ('--allow-websocket-origin', dict(
            metavar='HOST[:PORT]',
            action='append',
            type=str,
            help="Public hostnames which may connect to the Bokeh websocket",
        )),

        ('--host', dict(
            metavar='HOST[:PORT]',
            action='append',
            type=str,
            help="Public hostnames to allow in requests",
        )),

        ('--prefix', dict(
            metavar='PREFIX',
            type=str,
            help="URL prefix for Bokeh server URLs",
            default=None,
        )),

        ('--keep-alive', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to send a keep-alive ping to clients, 0 to disable.",
            default=None,
        )),

        ('--log-level', dict(
            metavar='LOG-LEVEL',
            action  = 'store',
            default = 'debug',
            choices = scserve.LOGLEVELS,
            help    = "One of: %s" % nice_join(scserve.LOGLEVELS),
        )),

        ('--session-ids', dict(
            metavar='MODE',
            action  = 'store',
            default = None,
            choices = scserve.SESSION_ID_MODES,
            help    = "One of: %s" % nice_join(scserve.SESSION_ID_MODES),
        )),
    )
Beispiel #30
0
 def test_default(self):
     assert bus.nice_join(["one"]) == "one"
     assert bus.nice_join(["one", "two"]) == "one or two"
     assert bus.nice_join(["one", "two", "three"]) == "one, two or three"
     assert bus.nice_join(["one", "two", "three",
                           "four"]) == "one, two, three or four"
Beispiel #31
0
class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    #: name for this subcommand
    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = base_serve_args + (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--args',
         dict(
             metavar='COMMAND-LINE-ARGS',
             nargs=argparse.REMAINDER,
             help=
             "Command line arguments remaining to passed on to the application handler. "
             "NOTE: if this argument precedes DIRECTORY-OR-SCRIPT then some other argument, e.g. "
             "--show, must be placed before the directory or script. ",
         )),
        ('--dev',
         dict(
             metavar='FILES-TO-WATCH',
             action='store',
             default=None,
             type=str,
             nargs='*',
             help="Enable live reloading during app development. "
             "By default it watches all *.py *.html *.css *.yaml files "
             "in the app directory tree. Additional files can be passed "
             "as arguments. "
             "NOTE: if this argument precedes DIRECTORY-OR-SCRIPT then some other argument, e.g "
             "--show, must be placed before the directory or script. "
             "NOTE: This setting only works with a single app. "
             "It also restricts the number of processes to 1. "
             "NOTE FOR WINDOWS USERS : this option must be invoked using "
             "'python -m bokeh'. If not Tornado will fail to restart the "
             "server",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--allow-websocket-origin',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames which may connect to the Bokeh websocket",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--check-unused-sessions',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to check for unused sessions",
             default=None,
         )),
        ('--unused-session-lifetime',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How long unused sessions last",
             default=None,
         )),
        ('--stats-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log stats",
             default=None,
         )),
        ('--mem-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log memory usage information",
             default=None,
         )),
        ('--use-xheaders',
         dict(
             action='store_true',
             help="Prefer X-headers for IP/protocol information",
         )),
        ('--ssl-certfile',
         dict(
             metavar='CERTFILE',
             action='store',
             default=None,
             help='Absolute path to a certificate file for SSL termination',
         )),
        ('--ssl-keyfile',
         dict(
             metavar='KEYFILE',
             action='store',
             default=None,
             help='Absolute path to a private key file for SSL termination',
         )),
        ('--session-ids',
         dict(
             metavar='MODE',
             action='store',
             default=None,
             choices=SESSION_ID_MODES,
             help="One of: %s" % nice_join(SESSION_ID_MODES),
         )),
        ('--auth-module',
         dict(
             metavar='AUTH_MODULE',
             action='store',
             default=None,
             help='Absolute path to a Python module that implements auth hooks',
         )),
        ('--enable-xsrf-cookies',
         dict(action='store_true',
              default=False,
              help='Whether to enable Tornado support for XSRF cookies. All '
              'PUT, POST, or DELETE handlers must be properly instrumented '
              'when this setting is enabled.')),
        ('--exclude-headers',
         dict(action='store',
              default=None,
              nargs='+',
              help='A list of request headers to exclude from the session '
              'context (by default all headers are included).')),
        ('--exclude-cookies',
         dict(action='store',
              default=None,
              nargs='+',
              help='A list of request cookies to exclude from the session '
              'context (by default all cookies are included).')),
        ('--include-headers',
         dict(
             action='store',
             default=None,
             nargs='+',
             help='A list of request headers to make available in the session '
             'context (by default all headers are included).')),
        ('--include-cookies',
         dict(
             action='store',
             default=None,
             nargs='+',
             help='A list of request cookies to make available in the session '
             'context (by default all cookies are included).')),
        ('--cookie-secret',
         dict(
             metavar='COOKIE_SECRET',
             action='store',
             default=None,
             help='Configure to enable getting/setting secure cookies',
         )),
        ('--index',
         dict(
             metavar='INDEX',
             action='store',
             default=None,
             help='Path to a template to use for the site index',
         )),
        ('--disable-index',
         dict(
             action='store_true',
             help='Do not use the default index on the root path',
         )),
        ('--disable-index-redirect',
         dict(
             action='store_true',
             help='Do not redirect to running app from root path',
         )),
        ('--num-procs',
         dict(
             metavar='N',
             action='store',
             help="Number of worker processes for an app. Using "
             "0 will autodetect number of cores (defaults to 1)",
             default=1,
             type=int,
         )),
        ('--session-token-expiration',
         dict(
             metavar='N',
             action='store',
             help="Duration in seconds that a new session token "
             "is valid for session creation. After the expiry "
             "time has elapsed, the token will not be able "
             "create a new session (defaults to  seconds).",
             default=DEFAULT_SESSION_TOKEN_EXPIRATION,
             type=int,
         )),
        ('--websocket-max-message-size',
         dict(
             metavar='BYTES',
             action='store',
             help="Set the Tornado websocket_max_message_size value "
             "(default: 20MB)",
             default=DEFAULT_WEBSOCKET_MAX_MESSAGE_SIZE_BYTES,
             type=int,
         )),
        ('--glob',
         dict(
             action='store_true',
             help='Process all filename arguments as globs',
         )),
    )

    def invoke(self, args: argparse.Namespace) -> None:
        '''

        '''
        basicConfig(format=args.log_format, filename=args.log_file)

        # This is a bit of a fudge. We want the default log level for non-server
        # cases to be None, i.e. we don't set a log level. But for the server we
        # do want to set the log level to INFO if nothing else overrides that.
        log_level = settings.py_log_level(args.log_level)
        if log_level is None:
            log_level = logging.INFO
        logging.getLogger('bokeh').setLevel(log_level)

        if args.use_config is not None:
            log.info("Using override config file: {}".format(args.use_config))
            settings.load_config(args.use_config)

        # protect this import inside a function so that "bokeh info" can work
        # even if Tornado is not installed
        from bokeh.server.server import Server

        files = []
        for f in args.files:
            if args.glob:
                files.extend(glob(f))
            else:
                files.append(f)

        argvs = {f: args.args for f in files}
        applications = build_single_handler_applications(files, argvs)

        if len(applications) == 0:
            # create an empty application by default
            applications['/'] = Application()

        # rename args to be compatible with Server
        if args.keep_alive is not None:
            args.keep_alive_milliseconds = args.keep_alive

        if args.check_unused_sessions is not None:
            args.check_unused_sessions_milliseconds = args.check_unused_sessions

        if args.unused_session_lifetime is not None:
            args.unused_session_lifetime_milliseconds = args.unused_session_lifetime

        if args.stats_log_frequency is not None:
            args.stats_log_frequency_milliseconds = args.stats_log_frequency

        if args.mem_log_frequency is not None:
            args.mem_log_frequency_milliseconds = args.mem_log_frequency

        server_kwargs = {
            key: getattr(args, key)
            for key in [
                'port',
                'address',
                'allow_websocket_origin',
                'num_procs',
                'prefix',
                'index',
                'keep_alive_milliseconds',
                'check_unused_sessions_milliseconds',
                'unused_session_lifetime_milliseconds',
                'stats_log_frequency_milliseconds',
                'mem_log_frequency_milliseconds',
                'use_xheaders',
                'websocket_max_message_size',
                'include_cookies',
                'include_headers',
                'exclude_cookies',
                'exclude_headers',
                'session_token_expiration',
            ] if getattr(args, key, None) is not None
        }

        server_kwargs['sign_sessions'] = settings.sign_sessions()
        server_kwargs['secret_key'] = settings.secret_key_bytes()
        server_kwargs['ssl_certfile'] = settings.ssl_certfile(
            getattr(args, 'ssl_certfile', None))
        server_kwargs['ssl_keyfile'] = settings.ssl_keyfile(
            getattr(args, 'ssl_keyfile', None))
        server_kwargs['ssl_password'] = settings.ssl_password()
        server_kwargs['generate_session_ids'] = True
        if args.session_ids is None:
            # no --session-ids means use the env vars
            pass
        elif args.session_ids == 'unsigned':
            server_kwargs['sign_sessions'] = False
        elif args.session_ids == 'signed':
            server_kwargs['sign_sessions'] = True
        elif args.session_ids == 'external-signed':
            server_kwargs['sign_sessions'] = True
            server_kwargs['generate_session_ids'] = False
        else:
            raise RuntimeError(
                "argparse should have filtered out --session-ids mode " +
                args.session_ids)

        if server_kwargs['sign_sessions'] and not server_kwargs['secret_key']:
            die("To sign sessions, the BOKEH_SECRET_KEY environment variable must be set; "
                +
                "the `bokeh secret` command can be used to generate a new key."
                )

        auth_module_path = settings.auth_module(
            getattr(args, 'auth_module', None))
        if auth_module_path:
            server_kwargs['auth_provider'] = AuthModule(auth_module_path)
        else:
            server_kwargs['auth_provider'] = NullAuth()

        server_kwargs['xsrf_cookies'] = settings.xsrf_cookies(
            getattr(args, 'enable_xsrf_cookies', False))
        server_kwargs['cookie_secret'] = settings.cookie_secret(
            getattr(args, 'cookie_secret', None))
        server_kwargs['use_index'] = not args.disable_index
        server_kwargs['redirect_root'] = not args.disable_index_redirect
        server_kwargs['autoreload'] = args.dev is not None

        def find_autoreload_targets(app_path: str) -> None:
            path = os.path.abspath(app_path)
            if not os.path.isdir(path):
                return

            for path, subdirs, files in os.walk(path):
                for name in files:
                    if (fnmatch(name, '*.html') or fnmatch(name, '*.css')
                            or fnmatch(name, '*.yaml')):
                        log.info("Watching: " + os.path.join(path, name))
                        watch(os.path.join(path, name))

        def add_optional_autoreload_files(file_list: List[str]) -> None:
            for filen in file_list:
                if os.path.isdir(filen):
                    log.warning("Cannot watch directory " + filen)
                    continue
                log.info("Watching: " + filen)
                watch(filen)

        if server_kwargs['autoreload']:
            if len(applications.keys()) != 1:
                die("--dev can only support a single app.")
            if server_kwargs['num_procs'] != 1:
                log.info("Running in --dev mode. --num-procs is limited to 1.")
                server_kwargs['num_procs'] = 1

            find_autoreload_targets(args.files[0])
            add_optional_autoreload_files(args.dev)

        with report_server_init_errors(**server_kwargs):
            server = Server(applications, **server_kwargs)

            if args.show:

                # we have to defer opening in browser until we start up the server
                def show_callback() -> None:
                    for route in applications.keys():
                        server.show(route)

                server.io_loop.add_callback(show_callback)

            address_string = 'localhost'
            if server.address is not None and server.address != '':
                address_string = server.address

            for route in sorted(applications.keys()):
                url = "http://%s:%d%s%s" % (address_string, server.port,
                                            server.prefix, route)
                log.info("Bokeh app running at: %s" % url)

            log.info("Starting Bokeh server with process id: %d" % os.getpid())
            server.run_until_shutdown()
Beispiel #32
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (

        ('files', dict(
            metavar='DIRECTORY-OR-SCRIPT',
            nargs='*',
            help="The app directories or scripts to serve (serve empty document if not specified)",
            default=None,
        )),

        ('--develop', dict(
            action='store_true',
            help="Enable develop-time features that should not be used in production",
        )),

        ('--show', dict(
            action='store_true',
            help="Open server app(s) in a browser",
        )),

        ('--port', dict(
            metavar='PORT',
            type=int,
            help="Port to listen on",
            default=None
        )),

        ('--address', dict(
            metavar='ADDRESS',
            type=str,
            help="Address to listen on",
            default=None,
        )),

        ('--allow-websocket-origin', dict(
            metavar='HOST[:PORT]',
            action='append',
            type=str,
            help="Public hostnames which may connect to the Bokeh websocket",
        )),

        ('--host', dict(
            metavar='HOST[:PORT]',
            action='append',
            type=str,
            help="Public hostnames to allow in requests",
        )),

        ('--prefix', dict(
            metavar='PREFIX',
            type=str,
            help="URL prefix for Bokeh server URLs",
            default=None,
        )),

        ('--keep-alive', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to send a keep-alive ping to clients, 0 to disable.",
            default=None,
        )),

        ('--check-unused-sessions', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to check for unused sessions",
            default=None,
        )),

        ('--unused-session-lifetime', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How long unused sessions last",
            default=None,
        )),

        ('--stats-log-frequency', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to log stats",
            default=None,
        )),

        ('--use-xheaders', dict(
            action='store_true',
            help="Prefer X-headers for IP/protocol information",
        )),

        ('--log-level', dict(
            metavar='LOG-LEVEL',
            action  = 'store',
            default = 'debug',
            choices = scserve.LOGLEVELS,
            help    = "One of: %s" % nice_join(scserve.LOGLEVELS),
        )),

        ('--log-format', dict(
            metavar='LOG-FORMAT',
            action  = 'store',
            default = scserve.DEFAULT_LOG_FORMAT,
            help    = "A standard Python logging format string (default: %r)" % scserve.DEFAULT_LOG_FORMAT.replace("%", "%%"),
        )),

        ('--session-ids', dict(
            metavar='MODE',
            action  = 'store',
            default = None,
            choices = scserve.SESSION_ID_MODES,
            help    = "One of: %s" % nice_join(scserve.SESSION_ID_MODES),
        )),
    )
Beispiel #33
0
def test_args():
    from bokeh.util.string import nice_join

    assert scserve.Serve.args == (
        ('--port', dict(
            metavar = 'PORT',
            type    = int,
            help    = "Port to listen on",
            default = DEFAULT_SERVER_PORT
        )),

        ('--address', dict(
            metavar = 'ADDRESS',
            type    = str,
            help    = "Address to listen on",
            default = None,
        )),

        ('--log-level', dict(
            metavar = 'LOG-LEVEL',
            action  = 'store',
            default = 'info',
            choices = scserve.LOGLEVELS,
            help    = "One of: %s" % nice_join(scserve.LOGLEVELS),
        )),

        ('--log-format', dict(
            metavar ='LOG-FORMAT',
            action  = 'store',
            default = scserve.DEFAULT_LOG_FORMAT,
            help    = "A standard Python logging format string (default: %r)" % scserve.DEFAULT_LOG_FORMAT.replace("%", "%%"),
        )),

        ('--log-file', dict(
            metavar ='LOG-FILE',
            action  = 'store',
            default = None,
            help    = "A filename to write logs to, or None to write to the standard stream (default: None)",
        )),

        ('files', dict(
            metavar='DIRECTORY-OR-SCRIPT',
            nargs='*',
            help="The app directories or scripts to serve (serve empty document if not specified)",
            default=None,
        )),

        ('--args', dict(
            metavar='COMMAND-LINE-ARGS',
            nargs=argparse.REMAINDER,
            help="Any command line arguments remaining are passed on to the application handler",
        )),

        ('--show', dict(
            action='store_true',
            help="Open server app(s) in a browser",
        )),

        ('--allow-websocket-origin', dict(
            metavar='HOST[:PORT]',
            action='append',
            type=str,
            help="Public hostnames which may connect to the Bokeh websocket",
        )),

        ('--prefix', dict(
            metavar='PREFIX',
            type=str,
            help="URL prefix for Bokeh server URLs",
            default=None,
        )),

        ('--keep-alive', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to send a keep-alive ping to clients, 0 to disable.",
            default=None,
        )),

        ('--check-unused-sessions', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to check for unused sessions",
            default=None,
        )),

        ('--unused-session-lifetime', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How long unused sessions last",
            default=None,
        )),

        ('--stats-log-frequency', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to log stats",
            default=None,
        )),

        ('--mem-log-frequency', dict(
            metavar='MILLISECONDS',
            type=int,
            help="How often to log memory usage information",
            default=None,
        )),

        ('--use-xheaders', dict(
            action='store_true',
            help="Prefer X-headers for IP/protocol information",
        )),

        ('--session-ids', dict(
            metavar='MODE',
            action  = 'store',
            default = None,
            choices = scserve.SESSION_ID_MODES,
            help    = "One of: %s" % nice_join(scserve.SESSION_ID_MODES),
        )),

        ('--disable-index', dict(
            action = 'store_true',
            help    = 'Do not use the default index on the root path',
        )),

        ('--disable-index-redirect', dict(
            action = 'store_true',
            help    = 'Do not redirect to running app from root path',
        )),

        ('--num-procs', dict(
             metavar='N',
             action='store',
             help="Number of worker processes for an app. Using "
                  "0 will autodetect number of cores (defaults to 1)",
             default=1,
             type=int,
         )),

         ('--websocket-max-message-size', dict(
            metavar='BYTES',
            action='store',
            help="Set the Tornado websocket_max_message_size value (defaults "
                 "to 20MB) NOTE: This setting has effect ONLY for Tornado>=4.5",
            default=20*1024*1024,
            type=int,
        )),
    )
Beispiel #34
0
class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"

    args = (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--develop',
         dict(
             action='store_true',
             help=
             "Enable develop-time features that should not be used in production",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--port',
         dict(metavar='PORT', type=int, help="Port to listen on",
              default=None)),
        ('--address',
         dict(
             metavar='ADDRESS',
             type=str,
             help="Address to listen on",
             default=None,
         )),
        ('--host',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames to allow in requests",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--log-level',
         dict(
             metavar='LOG-LEVEL',
             action='store',
             default='debug',
             choices=LOGLEVELS,
             help="One of: %s" % nice_join(LOGLEVELS),
         )),
    )

    def invoke(self, args):
        applications = build_single_handler_applications(args.files)

        log_level = getattr(logging, args.log_level.upper())
        logging.basicConfig(level=log_level)

        if len(applications) == 0:
            # create an empty application by default, typically used with output_server
            applications['/'] = Application()

        if args.keep_alive is not None:
            if args.keep_alive == 0:
                log.info("Keep-alive ping disabled")
            else:
                log.info("Keep-alive ping configured every %d milliseconds",
                         args.keep_alive)
            # rename to be compatible with Server
            args.keep_alive_milliseconds = args.keep_alive

        server_kwargs = {
            key: getattr(args, key)
            for key in
            ['port', 'address', 'host', 'prefix', 'keep_alive_milliseconds']
            if getattr(args, key, None) is not None
        }

        server = Server(applications, **server_kwargs)

        if args.show:
            # we have to defer opening in browser until we start up the server
            def show_callback():
                for route in applications.keys():
                    server.show(route)

            server.io_loop.add_callback(show_callback)

        if args.develop:
            log.info(
                "Using develop mode (do not enable --develop in production)")

        address_string = ''
        if server.address is not None and server.address != '':
            address_string = ' address ' + server.address

        log.info(
            "Starting Bokeh server on port %d%s with applications at paths %r",
            server.port, address_string, sorted(applications.keys()))

        server.start()
Beispiel #35
0
class Serve(Subcommand):
    ''' Subcommand to launch the Bokeh server.

    '''

    name = "serve"

    help = "Run a Bokeh server hosting one or more applications"
    args = base_serve_args + (
        ('files',
         dict(
             metavar='DIRECTORY-OR-SCRIPT',
             nargs='*',
             help=
             "The app directories or scripts to serve (serve empty document if not specified)",
             default=None,
         )),
        ('--args',
         dict(
             metavar='COMMAND-LINE-ARGS',
             nargs=argparse.REMAINDER,
             help=
             "Any command line arguments remaining are passed on to the application handler",
         )),
        ('--show',
         dict(
             action='store_true',
             help="Open server app(s) in a browser",
         )),
        ('--allow-websocket-origin',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="Public hostnames which may connect to the Bokeh websocket",
         )),
        ('--host',
         dict(
             metavar='HOST[:PORT]',
             action='append',
             type=str,
             help="*** DEPRECATED ***",
         )),
        ('--prefix',
         dict(
             metavar='PREFIX',
             type=str,
             help="URL prefix for Bokeh server URLs",
             default=None,
         )),
        ('--keep-alive',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help=
             "How often to send a keep-alive ping to clients, 0 to disable.",
             default=None,
         )),
        ('--check-unused-sessions',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to check for unused sessions",
             default=None,
         )),
        ('--unused-session-lifetime',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How long unused sessions last",
             default=None,
         )),
        ('--stats-log-frequency',
         dict(
             metavar='MILLISECONDS',
             type=int,
             help="How often to log stats",
             default=None,
         )),
        ('--use-xheaders',
         dict(
             action='store_true',
             help="Prefer X-headers for IP/protocol information",
         )),
        ('--session-ids',
         dict(
             metavar='MODE',
             action='store',
             default=None,
             choices=SESSION_ID_MODES,
             help="One of: %s" % nice_join(SESSION_ID_MODES),
         )),
        ('--disable-index',
         dict(
             action='store_true',
             help='Do not use the default index on the root path',
         )),
        ('--disable-index-redirect',
         dict(
             action='store_true',
             help='Do not redirect to running app from root path',
         )),
        ('--num-procs',
         dict(
             metavar='N',
             action='store',
             help="Number of worker processes for an app. Default to one. Using "
             "0 will autodetect number of cores",
             default=1,
             type=int,
         )),
    )

    def invoke(self, args):
        argvs = {f: args.args for f in args.files}
        applications = build_single_handler_applications(args.files, argvs)

        log_level = getattr(logging, args.log_level.upper())
        basicConfig(level=log_level, format=args.log_format)

        # This should remain here until --host is removed entirely
        _fixup_deprecated_host_args(args)

        if len(applications) == 0:
            # create an empty application by default
            applications['/'] = Application()

        if args.keep_alive is not None:
            if args.keep_alive == 0:
                log.info("Keep-alive ping disabled")
            else:
                log.info("Keep-alive ping configured every %d milliseconds",
                         args.keep_alive)
            # rename to be compatible with Server
            args.keep_alive_milliseconds = args.keep_alive

        if args.check_unused_sessions is not None:
            log.info("Check for unused sessions every %d milliseconds",
                     args.check_unused_sessions)
            # rename to be compatible with Server
            args.check_unused_sessions_milliseconds = args.check_unused_sessions

        if args.unused_session_lifetime is not None:
            log.info("Unused sessions last for %d milliseconds",
                     args.unused_session_lifetime)
            # rename to be compatible with Server
            args.unused_session_lifetime_milliseconds = args.unused_session_lifetime

        if args.stats_log_frequency is not None:
            log.info("Log statistics every %d milliseconds",
                     args.stats_log_frequency)
            # rename to be compatible with Server
            args.stats_log_frequency_milliseconds = args.stats_log_frequency

        server_kwargs = {
            key: getattr(args, key)
            for key in [
                'port',
                'address',
                'allow_websocket_origin',
                'num_procs',
                'prefix',
                'keep_alive_milliseconds',
                'check_unused_sessions_milliseconds',
                'unused_session_lifetime_milliseconds',
                'stats_log_frequency_milliseconds',
                'use_xheaders',
            ] if getattr(args, key, None) is not None
        }

        server_kwargs['sign_sessions'] = settings.sign_sessions()
        server_kwargs['secret_key'] = settings.secret_key_bytes()
        server_kwargs['generate_session_ids'] = True
        if args.session_ids is None:
            # no --session-ids means use the env vars
            pass
        elif args.session_ids == 'unsigned':
            server_kwargs['sign_sessions'] = False
        elif args.session_ids == 'signed':
            server_kwargs['sign_sessions'] = True
        elif args.session_ids == 'external-signed':
            server_kwargs['sign_sessions'] = True
            server_kwargs['generate_session_ids'] = False
        else:
            raise RuntimeError(
                "argparse should have filtered out --session-ids mode " +
                args.session_ids)

        if server_kwargs['sign_sessions'] and not server_kwargs['secret_key']:
            die("To sign sessions, the BOKEH_SECRET_KEY environment variable must be set; "
                +
                "the `bokeh secret` command can be used to generate a new key."
                )

        server_kwargs['use_index'] = not args.disable_index
        server_kwargs['redirect_root'] = not args.disable_index_redirect

        with report_server_init_errors(**server_kwargs):
            server = Server(applications, **server_kwargs)

            if args.show:
                # we have to defer opening in browser until we start up the server
                def show_callback():
                    for route in applications.keys():
                        server.show(route)

                server.io_loop.add_callback(show_callback)

            address_string = 'localhost'
            if server.address is not None and server.address != '':
                address_string = server.address

            for route in sorted(applications.keys()):
                url = "http://%s:%d%s%s" % (address_string, server.port,
                                            server.prefix, route)
                log.info("Bokeh app running at: %s" % url)

            log.info("Starting Bokeh server with process id: %d" % getpid())
            server.run_until_shutdown()
Beispiel #36
0
def main(args=None):
    """Merges commands offered by pyct and bokeh and provides help for both"""
    from bokeh.command.subcommands import all as bokeh_commands
    bokeh_commands = bokeh_commands + [OAuthSecret]

    try:
        import pyct.cmd
        pyct_commands = ['copy-examples', 'examples']
    except Exception:
        pass

    parser = argparse.ArgumentParser(
        prog="panel",
        epilog="See '<command> --help' to read about a specific subcommand.")

    parser.add_argument('-v',
                        '--version',
                        action='version',
                        version=__version__)

    subs = parser.add_subparsers(help="Sub-commands")

    for cmd in pyct_commands:
        cmd = cmd.replace('-', '_')
        fn = getattr(pyct.cmd, cmd)
        subs.add_parser(cmd, help=fn.__doc__)

    for cls in bokeh_commands:
        if cls is BkServe:
            subparser = subs.add_parser(Serve.name, help=Serve.help)
            subcommand = Serve(parser=subparser)
            subparser.set_defaults(invoke=subcommand.invoke)
        else:
            subs.add_parser(cls.name, help=cls.help)

    if len(sys.argv) == 1:
        all_commands = sorted([c.name for c in bokeh_commands] + pyct_commands)
        die("ERROR: Must specify subcommand, one of: %s" %
            nice_join(all_commands))

    if sys.argv[1] in ('--help', '-h'):
        args = parser.parse_args(sys.argv[1:])
        args.invoke(args)
        sys.exit()

    if len(sys.argv) > 1 and any(sys.argv[1] == c.name
                                 for c in bokeh_commands):
        sys.argv = transform_cmds(sys.argv)
        if sys.argv[1] == 'serve':
            args = parser.parse_args(sys.argv[1:])
            try:
                ret = args.invoke(args)
            except Exception as e:
                die("ERROR: " + str(e))
        elif sys.argv[1] == 'oauth-secret':
            ret = OAuthSecret(parser).invoke(args)
        else:
            ret = bokeh_entry_point()
    elif sys.argv[1] in pyct_commands:
        try:
            import pyct.cmd
        except ImportError:
            print(
                "install pyct to enable this command (e.g. `conda install -c pyviz pyct` or `pip install pyct[cmd]`)"
            )
            sys.exit(1)
        pyct.cmd.substitute_main('panel', cmds=pyct_commands, args=args)
    else:
        parser.parse_args(sys.argv[1:])
        sys.exit(1)

    if ret is False:
        sys.exit(1)
    elif ret is not True and isinstance(ret, int) and ret != 0:
        sys.exit(ret)