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 logging
import os
import sys
import warnings

import click
import dotenv
import trio
from flockwave.app_framework.hacks import install_unraisable_hook
from flockwave.app_framework.instrumentation import get_enabled_instruments

from flockwave import logger

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: int | None = 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"))