about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/uvicorn/main.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/uvicorn/main.py')
-rw-r--r--.venv/lib/python3.12/site-packages/uvicorn/main.py596
1 files changed, 596 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/uvicorn/main.py b/.venv/lib/python3.12/site-packages/uvicorn/main.py
new file mode 100644
index 00000000..fee6c5b4
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/uvicorn/main.py
@@ -0,0 +1,596 @@
+from __future__ import annotations
+
+import asyncio
+import logging
+import os
+import platform
+import ssl
+import sys
+from typing import Any, Callable
+
+import click
+
+import uvicorn
+from uvicorn._types import ASGIApplication
+from uvicorn.config import (
+    HTTP_PROTOCOLS,
+    INTERFACES,
+    LIFESPAN,
+    LOG_LEVELS,
+    LOGGING_CONFIG,
+    LOOP_SETUPS,
+    SSL_PROTOCOL_VERSION,
+    WS_PROTOCOLS,
+    Config,
+    HTTPProtocolType,
+    InterfaceType,
+    LifespanType,
+    LoopSetupType,
+    WSProtocolType,
+)
+from uvicorn.server import Server, ServerState  # noqa: F401  # Used to be defined here.
+from uvicorn.supervisors import ChangeReload, Multiprocess
+
+LEVEL_CHOICES = click.Choice(list(LOG_LEVELS.keys()))
+HTTP_CHOICES = click.Choice(list(HTTP_PROTOCOLS.keys()))
+WS_CHOICES = click.Choice(list(WS_PROTOCOLS.keys()))
+LIFESPAN_CHOICES = click.Choice(list(LIFESPAN.keys()))
+LOOP_CHOICES = click.Choice([key for key in LOOP_SETUPS.keys() if key != "none"])
+INTERFACE_CHOICES = click.Choice(INTERFACES)
+
+STARTUP_FAILURE = 3
+
+logger = logging.getLogger("uvicorn.error")
+
+
+def print_version(ctx: click.Context, param: click.Parameter, value: bool) -> None:
+    if not value or ctx.resilient_parsing:
+        return
+    click.echo(
+        "Running uvicorn %s with %s %s on %s"
+        % (
+            uvicorn.__version__,
+            platform.python_implementation(),
+            platform.python_version(),
+            platform.system(),
+        )
+    )
+    ctx.exit()
+
+
+@click.command(context_settings={"auto_envvar_prefix": "UVICORN"})
+@click.argument("app", envvar="UVICORN_APP")
+@click.option(
+    "--host",
+    type=str,
+    default="127.0.0.1",
+    help="Bind socket to this host.",
+    show_default=True,
+)
+@click.option(
+    "--port",
+    type=int,
+    default=8000,
+    help="Bind socket to this port. If 0, an available port will be picked.",
+    show_default=True,
+)
+@click.option("--uds", type=str, default=None, help="Bind to a UNIX domain socket.")
+@click.option(
+    "--fd", type=int, default=None, help="Bind to socket from this file descriptor."
+)
+@click.option("--reload", is_flag=True, default=False, help="Enable auto-reload.")
+@click.option(
+    "--reload-dir",
+    "reload_dirs",
+    multiple=True,
+    help="Set reload directories explicitly, instead of using the current working"
+    " directory.",
+    type=click.Path(exists=True),
+)
+@click.option(
+    "--reload-include",
+    "reload_includes",
+    multiple=True,
+    help="Set glob patterns to include while watching for files. Includes '*.py' "
+    "by default; these defaults can be overridden with `--reload-exclude`. "
+    "This option has no effect unless watchfiles is installed.",
+)
+@click.option(
+    "--reload-exclude",
+    "reload_excludes",
+    multiple=True,
+    help="Set glob patterns to exclude while watching for files. Includes "
+    "'.*, .py[cod], .sw.*, ~*' by default; these defaults can be overridden "
+    "with `--reload-include`. This option has no effect unless watchfiles is "
+    "installed.",
+)
+@click.option(
+    "--reload-delay",
+    type=float,
+    default=0.25,
+    show_default=True,
+    help="Delay between previous and next check if application needs to be."
+    " Defaults to 0.25s.",
+)
+@click.option(
+    "--workers",
+    default=None,
+    type=int,
+    help="Number of worker processes. Defaults to the $WEB_CONCURRENCY environment"
+    " variable if available, or 1. Not valid with --reload.",
+)
+@click.option(
+    "--loop",
+    type=LOOP_CHOICES,
+    default="auto",
+    help="Event loop implementation.",
+    show_default=True,
+)
+@click.option(
+    "--http",
+    type=HTTP_CHOICES,
+    default="auto",
+    help="HTTP protocol implementation.",
+    show_default=True,
+)
+@click.option(
+    "--ws",
+    type=WS_CHOICES,
+    default="auto",
+    help="WebSocket protocol implementation.",
+    show_default=True,
+)
+@click.option(
+    "--ws-max-size",
+    type=int,
+    default=16777216,
+    help="WebSocket max size message in bytes",
+    show_default=True,
+)
+@click.option(
+    "--ws-max-queue",
+    type=int,
+    default=32,
+    help="The maximum length of the WebSocket message queue.",
+    show_default=True,
+)
+@click.option(
+    "--ws-ping-interval",
+    type=float,
+    default=20.0,
+    help="WebSocket ping interval in seconds.",
+    show_default=True,
+)
+@click.option(
+    "--ws-ping-timeout",
+    type=float,
+    default=20.0,
+    help="WebSocket ping timeout in seconds.",
+    show_default=True,
+)
+@click.option(
+    "--ws-per-message-deflate",
+    type=bool,
+    default=True,
+    help="WebSocket per-message-deflate compression",
+    show_default=True,
+)
+@click.option(
+    "--lifespan",
+    type=LIFESPAN_CHOICES,
+    default="auto",
+    help="Lifespan implementation.",
+    show_default=True,
+)
+@click.option(
+    "--interface",
+    type=INTERFACE_CHOICES,
+    default="auto",
+    help="Select ASGI3, ASGI2, or WSGI as the application interface.",
+    show_default=True,
+)
+@click.option(
+    "--env-file",
+    type=click.Path(exists=True),
+    default=None,
+    help="Environment configuration file.",
+    show_default=True,
+)
+@click.option(
+    "--log-config",
+    type=click.Path(exists=True),
+    default=None,
+    help="Logging configuration file. Supported formats: .ini, .json, .yaml.",
+    show_default=True,
+)
+@click.option(
+    "--log-level",
+    type=LEVEL_CHOICES,
+    default=None,
+    help="Log level. [default: info]",
+    show_default=True,
+)
+@click.option(
+    "--access-log/--no-access-log",
+    is_flag=True,
+    default=True,
+    help="Enable/Disable access log.",
+)
+@click.option(
+    "--use-colors/--no-use-colors",
+    is_flag=True,
+    default=None,
+    help="Enable/Disable colorized logging.",
+)
+@click.option(
+    "--proxy-headers/--no-proxy-headers",
+    is_flag=True,
+    default=True,
+    help="Enable/Disable X-Forwarded-Proto, X-Forwarded-For, X-Forwarded-Port to "
+    "populate remote address info.",
+)
+@click.option(
+    "--server-header/--no-server-header",
+    is_flag=True,
+    default=True,
+    help="Enable/Disable default Server header.",
+)
+@click.option(
+    "--date-header/--no-date-header",
+    is_flag=True,
+    default=True,
+    help="Enable/Disable default Date header.",
+)
+@click.option(
+    "--forwarded-allow-ips",
+    type=str,
+    default=None,
+    help="Comma separated list of IPs to trust with proxy headers. Defaults to"
+    " the $FORWARDED_ALLOW_IPS environment variable if available, or '127.0.0.1'.",
+)
+@click.option(
+    "--root-path",
+    type=str,
+    default="",
+    help="Set the ASGI 'root_path' for applications submounted below a given URL path.",
+)
+@click.option(
+    "--limit-concurrency",
+    type=int,
+    default=None,
+    help="Maximum number of concurrent connections or tasks to allow, before issuing"
+    " HTTP 503 responses.",
+)
+@click.option(
+    "--backlog",
+    type=int,
+    default=2048,
+    help="Maximum number of connections to hold in backlog",
+)
+@click.option(
+    "--limit-max-requests",
+    type=int,
+    default=None,
+    help="Maximum number of requests to service before terminating the process.",
+)
+@click.option(
+    "--timeout-keep-alive",
+    type=int,
+    default=5,
+    help="Close Keep-Alive connections if no new data is received within this timeout.",
+    show_default=True,
+)
+@click.option(
+    "--timeout-graceful-shutdown",
+    type=int,
+    default=None,
+    help="Maximum number of seconds to wait for graceful shutdown.",
+)
+@click.option(
+    "--ssl-keyfile", type=str, default=None, help="SSL key file", show_default=True
+)
+@click.option(
+    "--ssl-certfile",
+    type=str,
+    default=None,
+    help="SSL certificate file",
+    show_default=True,
+)
+@click.option(
+    "--ssl-keyfile-password",
+    type=str,
+    default=None,
+    help="SSL keyfile password",
+    show_default=True,
+)
+@click.option(
+    "--ssl-version",
+    type=int,
+    default=int(SSL_PROTOCOL_VERSION),
+    help="SSL version to use (see stdlib ssl module's)",
+    show_default=True,
+)
+@click.option(
+    "--ssl-cert-reqs",
+    type=int,
+    default=int(ssl.CERT_NONE),
+    help="Whether client certificate is required (see stdlib ssl module's)",
+    show_default=True,
+)
+@click.option(
+    "--ssl-ca-certs",
+    type=str,
+    default=None,
+    help="CA certificates file",
+    show_default=True,
+)
+@click.option(
+    "--ssl-ciphers",
+    type=str,
+    default="TLSv1",
+    help="Ciphers to use (see stdlib ssl module's)",
+    show_default=True,
+)
+@click.option(
+    "--header",
+    "headers",
+    multiple=True,
+    help="Specify custom default HTTP response headers as a Name:Value pair",
+)
+@click.option(
+    "--version",
+    is_flag=True,
+    callback=print_version,
+    expose_value=False,
+    is_eager=True,
+    help="Display the uvicorn version and exit.",
+)
+@click.option(
+    "--app-dir",
+    default="",
+    show_default=True,
+    help="Look for APP in the specified directory, by adding this to the PYTHONPATH."
+    " Defaults to the current working directory.",
+)
+@click.option(
+    "--h11-max-incomplete-event-size",
+    "h11_max_incomplete_event_size",
+    type=int,
+    default=None,
+    help="For h11, the maximum number of bytes to buffer of an incomplete event.",
+)
+@click.option(
+    "--factory",
+    is_flag=True,
+    default=False,
+    help="Treat APP as an application factory, i.e. a () -> <ASGI app> callable.",
+    show_default=True,
+)
+def main(
+    app: str,
+    host: str,
+    port: int,
+    uds: str,
+    fd: int,
+    loop: LoopSetupType,
+    http: HTTPProtocolType,
+    ws: WSProtocolType,
+    ws_max_size: int,
+    ws_max_queue: int,
+    ws_ping_interval: float,
+    ws_ping_timeout: float,
+    ws_per_message_deflate: bool,
+    lifespan: LifespanType,
+    interface: InterfaceType,
+    reload: bool,
+    reload_dirs: list[str],
+    reload_includes: list[str],
+    reload_excludes: list[str],
+    reload_delay: float,
+    workers: int,
+    env_file: str,
+    log_config: str,
+    log_level: str,
+    access_log: bool,
+    proxy_headers: bool,
+    server_header: bool,
+    date_header: bool,
+    forwarded_allow_ips: str,
+    root_path: str,
+    limit_concurrency: int,
+    backlog: int,
+    limit_max_requests: int,
+    timeout_keep_alive: int,
+    timeout_graceful_shutdown: int | None,
+    ssl_keyfile: str,
+    ssl_certfile: str,
+    ssl_keyfile_password: str,
+    ssl_version: int,
+    ssl_cert_reqs: int,
+    ssl_ca_certs: str,
+    ssl_ciphers: str,
+    headers: list[str],
+    use_colors: bool,
+    app_dir: str,
+    h11_max_incomplete_event_size: int | None,
+    factory: bool,
+) -> None:
+    run(
+        app,
+        host=host,
+        port=port,
+        uds=uds,
+        fd=fd,
+        loop=loop,
+        http=http,
+        ws=ws,
+        ws_max_size=ws_max_size,
+        ws_max_queue=ws_max_queue,
+        ws_ping_interval=ws_ping_interval,
+        ws_ping_timeout=ws_ping_timeout,
+        ws_per_message_deflate=ws_per_message_deflate,
+        lifespan=lifespan,
+        env_file=env_file,
+        log_config=LOGGING_CONFIG if log_config is None else log_config,
+        log_level=log_level,
+        access_log=access_log,
+        interface=interface,
+        reload=reload,
+        reload_dirs=reload_dirs or None,
+        reload_includes=reload_includes or None,
+        reload_excludes=reload_excludes or None,
+        reload_delay=reload_delay,
+        workers=workers,
+        proxy_headers=proxy_headers,
+        server_header=server_header,
+        date_header=date_header,
+        forwarded_allow_ips=forwarded_allow_ips,
+        root_path=root_path,
+        limit_concurrency=limit_concurrency,
+        backlog=backlog,
+        limit_max_requests=limit_max_requests,
+        timeout_keep_alive=timeout_keep_alive,
+        timeout_graceful_shutdown=timeout_graceful_shutdown,
+        ssl_keyfile=ssl_keyfile,
+        ssl_certfile=ssl_certfile,
+        ssl_keyfile_password=ssl_keyfile_password,
+        ssl_version=ssl_version,
+        ssl_cert_reqs=ssl_cert_reqs,
+        ssl_ca_certs=ssl_ca_certs,
+        ssl_ciphers=ssl_ciphers,
+        headers=[header.split(":", 1) for header in headers],  # type: ignore[misc]
+        use_colors=use_colors,
+        factory=factory,
+        app_dir=app_dir,
+        h11_max_incomplete_event_size=h11_max_incomplete_event_size,
+    )
+
+
+def run(
+    app: ASGIApplication | Callable[..., Any] | str,
+    *,
+    host: str = "127.0.0.1",
+    port: int = 8000,
+    uds: str | None = None,
+    fd: int | None = None,
+    loop: LoopSetupType = "auto",
+    http: type[asyncio.Protocol] | HTTPProtocolType = "auto",
+    ws: type[asyncio.Protocol] | WSProtocolType = "auto",
+    ws_max_size: int = 16777216,
+    ws_max_queue: int = 32,
+    ws_ping_interval: float | None = 20.0,
+    ws_ping_timeout: float | None = 20.0,
+    ws_per_message_deflate: bool = True,
+    lifespan: LifespanType = "auto",
+    interface: InterfaceType = "auto",
+    reload: bool = False,
+    reload_dirs: list[str] | str | None = None,
+    reload_includes: list[str] | str | None = None,
+    reload_excludes: list[str] | str | None = None,
+    reload_delay: float = 0.25,
+    workers: int | None = None,
+    env_file: str | os.PathLike[str] | None = None,
+    log_config: dict[str, Any] | str | None = LOGGING_CONFIG,
+    log_level: str | int | None = None,
+    access_log: bool = True,
+    proxy_headers: bool = True,
+    server_header: bool = True,
+    date_header: bool = True,
+    forwarded_allow_ips: list[str] | str | None = None,
+    root_path: str = "",
+    limit_concurrency: int | None = None,
+    backlog: int = 2048,
+    limit_max_requests: int | None = None,
+    timeout_keep_alive: int = 5,
+    timeout_graceful_shutdown: int | None = None,
+    ssl_keyfile: str | None = None,
+    ssl_certfile: str | os.PathLike[str] | None = None,
+    ssl_keyfile_password: str | None = None,
+    ssl_version: int = SSL_PROTOCOL_VERSION,
+    ssl_cert_reqs: int = ssl.CERT_NONE,
+    ssl_ca_certs: str | None = None,
+    ssl_ciphers: str = "TLSv1",
+    headers: list[tuple[str, str]] | None = None,
+    use_colors: bool | None = None,
+    app_dir: str | None = None,
+    factory: bool = False,
+    h11_max_incomplete_event_size: int | None = None,
+) -> None:
+    if app_dir is not None:
+        sys.path.insert(0, app_dir)
+
+    config = Config(
+        app,
+        host=host,
+        port=port,
+        uds=uds,
+        fd=fd,
+        loop=loop,
+        http=http,
+        ws=ws,
+        ws_max_size=ws_max_size,
+        ws_max_queue=ws_max_queue,
+        ws_ping_interval=ws_ping_interval,
+        ws_ping_timeout=ws_ping_timeout,
+        ws_per_message_deflate=ws_per_message_deflate,
+        lifespan=lifespan,
+        interface=interface,
+        reload=reload,
+        reload_dirs=reload_dirs,
+        reload_includes=reload_includes,
+        reload_excludes=reload_excludes,
+        reload_delay=reload_delay,
+        workers=workers,
+        env_file=env_file,
+        log_config=log_config,
+        log_level=log_level,
+        access_log=access_log,
+        proxy_headers=proxy_headers,
+        server_header=server_header,
+        date_header=date_header,
+        forwarded_allow_ips=forwarded_allow_ips,
+        root_path=root_path,
+        limit_concurrency=limit_concurrency,
+        backlog=backlog,
+        limit_max_requests=limit_max_requests,
+        timeout_keep_alive=timeout_keep_alive,
+        timeout_graceful_shutdown=timeout_graceful_shutdown,
+        ssl_keyfile=ssl_keyfile,
+        ssl_certfile=ssl_certfile,
+        ssl_keyfile_password=ssl_keyfile_password,
+        ssl_version=ssl_version,
+        ssl_cert_reqs=ssl_cert_reqs,
+        ssl_ca_certs=ssl_ca_certs,
+        ssl_ciphers=ssl_ciphers,
+        headers=headers,
+        use_colors=use_colors,
+        factory=factory,
+        h11_max_incomplete_event_size=h11_max_incomplete_event_size,
+    )
+    server = Server(config=config)
+
+    if (config.reload or config.workers > 1) and not isinstance(app, str):
+        logger = logging.getLogger("uvicorn.error")
+        logger.warning(
+            "You must pass the application as an import string to enable 'reload' or "
+            "'workers'."
+        )
+        sys.exit(1)
+
+    if config.should_reload:
+        sock = config.bind_socket()
+        ChangeReload(config, target=server.run, sockets=[sock]).run()
+    elif config.workers > 1:
+        sock = config.bind_socket()
+        Multiprocess(config, target=server.run, sockets=[sock]).run()
+    else:
+        server.run()
+    if config.uds and os.path.exists(config.uds):
+        os.remove(config.uds)  # pragma: py-win32
+
+    if not server.started and not config.should_reload and config.workers == 1:
+        sys.exit(STARTUP_FAILURE)
+
+
+if __name__ == "__main__":
+    main()  # pragma: no cover