Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
flockwave-server / server / launcher.py
Size: Mime:
"""Command line launcher for the Skybrush server."""

import click
import dotenv
import logging
import os
import sys
import trio
import warnings

from typing import Optional

from flockwave import logger
from flockwave.app_framework.hacks import install_unraisable_hook
from flockwave.app_framework.instrumentation import get_enabled_instruments

from .logger import log
from .utils.packaging import is_packaged
from .version import __version__


@click.command()
@click.option(
    "-c",
    "--config",
    type=click.Path(resolve_path=True),
    help="Name of the configuration file to load",
)
@click.option(
    "-d", "--debug/--no-debug", default=False, help="Start the server in debug mode"
)
@click.option(
    "-p",
    "--port",
    metavar="PORT",
    default=None,
    help="Override the base port number of the server. Takes precedence over the PORT environment variable.",
)
@click.option(
    "-q", "--quiet/--no-quiet", default=False, help="Start the server in quiet mode"
)
@click.option(
    "--log-style",
    type=click.Choice(["fancy", "plain", "json"]),
    default="fancy",
    help="Specify the style of the logging output",
)
@click.version_option(version=__version__)
def start(
    config: str,
    port: Optional[int] = None,
    debug: bool = False,
    quiet: bool = False,
    log_style: str = "fancy",
):
    """Start the Skybrush server."""
    # Silence some irrelevant exceptions when exiting the app
    install_unraisable_hook()

    # Set up the logging format
    logger.install(
        level=logging.DEBUG if debug else logging.WARN if quiet else logging.INFO,
        style=log_style,
    )

    # Silence Engine.IO and Socket.IO debug messages, debug messages from
    # Paramiko and warnings from urllib3.connectionpool
    for logger_name in (
        "engineio",
        "engineio.server",
        "socketio",
        "socketio.server",
        "paramiko",
        "urllib3.connectionpool",
    ):
        log_handler = logging.getLogger(logger_name)
        log_handler.setLevel(logging.ERROR)

    # Also silence informational messages from charset_normalizer and httpx
    for logger_name in ("charset_normalizer", "httpcore", "httpx"):
        log_handler = logging.getLogger(logger_name)
        log_handler.setLevel(logging.WARN)

    # Silence deprecation warnings from Trio if we are packaged until AnyIO
    # migrates to to_thread.run_sync(..., abandon_on_cancel=...)
    if is_packaged():
        warnings.filterwarnings(action="ignore", category=trio.TrioDeprecationWarning)

    # Load environment variables from .env
    dotenv.load_dotenv(verbose=debug)

    # Override port number from command line if needed
    if port is not None:
        os.environ["PORT"] = str(port)

    # Note the lazy import; this is to ensure that the logging is set up by the
    # time we start configuring the app.
    from flockwave.server.app import app

    # Log what we are doing
    log.info(f"Starting Skybrush server {__version__}")

    # Configure the application
    retval = app.prepare(config, debug=debug)
    if retval is not None:
        return retval

    # Add instrumentation if needed
    instruments = get_enabled_instruments(env_var="SKYBRUSH_INSTRUMENTS")

    # Now start the server
    trio.run(app.run, instruments=instruments)

    # Log that we have stopped cleanly.
    log.info("Shutdown finished")


if __name__ == "__main__":
    sys.exit(start(prog_name="skybrushd"))