about summary refs log tree commit diff
path: root/.venv/lib/python3.12/site-packages/uvicorn/supervisors/basereload.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/uvicorn/supervisors/basereload.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are here HEAD master
Diffstat (limited to '.venv/lib/python3.12/site-packages/uvicorn/supervisors/basereload.py')
-rw-r--r--.venv/lib/python3.12/site-packages/uvicorn/supervisors/basereload.py127
1 files changed, 127 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/uvicorn/supervisors/basereload.py b/.venv/lib/python3.12/site-packages/uvicorn/supervisors/basereload.py
new file mode 100644
index 00000000..6e2e0c35
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/uvicorn/supervisors/basereload.py
@@ -0,0 +1,127 @@
+from __future__ import annotations
+
+import logging
+import os
+import signal
+import sys
+import threading
+from pathlib import Path
+from socket import socket
+from types import FrameType
+from typing import Callable, Iterator
+
+import click
+
+from uvicorn._subprocess import get_subprocess
+from uvicorn.config import Config
+
+HANDLED_SIGNALS = (
+    signal.SIGINT,  # Unix signal 2. Sent by Ctrl+C.
+    signal.SIGTERM,  # Unix signal 15. Sent by `kill <pid>`.
+)
+
+logger = logging.getLogger("uvicorn.error")
+
+
+class BaseReload:
+    def __init__(
+        self,
+        config: Config,
+        target: Callable[[list[socket] | None], None],
+        sockets: list[socket],
+    ) -> None:
+        self.config = config
+        self.target = target
+        self.sockets = sockets
+        self.should_exit = threading.Event()
+        self.pid = os.getpid()
+        self.is_restarting = False
+        self.reloader_name: str | None = None
+
+    def signal_handler(self, sig: int, frame: FrameType | None) -> None:
+        """
+        A signal handler that is registered with the parent process.
+        """
+        if sys.platform == "win32" and self.is_restarting:
+            self.is_restarting = False  # pragma: py-not-win32
+        else:
+            self.should_exit.set()  # pragma: py-win32
+
+    def run(self) -> None:
+        self.startup()
+        for changes in self:
+            if changes:
+                logger.warning(
+                    "%s detected changes in %s. Reloading...",
+                    self.reloader_name,
+                    ", ".join(map(_display_path, changes)),
+                )
+                self.restart()
+
+        self.shutdown()
+
+    def pause(self) -> None:
+        if self.should_exit.wait(self.config.reload_delay):
+            raise StopIteration()
+
+    def __iter__(self) -> Iterator[list[Path] | None]:
+        return self
+
+    def __next__(self) -> list[Path] | None:
+        return self.should_restart()
+
+    def startup(self) -> None:
+        message = f"Started reloader process [{self.pid}] using {self.reloader_name}"
+        color_message = "Started reloader process [{}] using {}".format(
+            click.style(str(self.pid), fg="cyan", bold=True),
+            click.style(str(self.reloader_name), fg="cyan", bold=True),
+        )
+        logger.info(message, extra={"color_message": color_message})
+
+        for sig in HANDLED_SIGNALS:
+            signal.signal(sig, self.signal_handler)
+
+        self.process = get_subprocess(
+            config=self.config, target=self.target, sockets=self.sockets
+        )
+        self.process.start()
+
+    def restart(self) -> None:
+        if sys.platform == "win32":  # pragma: py-not-win32
+            self.is_restarting = True
+            assert self.process.pid is not None
+            os.kill(self.process.pid, signal.CTRL_C_EVENT)
+        else:  # pragma: py-win32
+            self.process.terminate()
+        self.process.join()
+
+        self.process = get_subprocess(
+            config=self.config, target=self.target, sockets=self.sockets
+        )
+        self.process.start()
+
+    def shutdown(self) -> None:
+        if sys.platform == "win32":
+            self.should_exit.set()  # pragma: py-not-win32
+        else:
+            self.process.terminate()  # pragma: py-win32
+        self.process.join()
+
+        for sock in self.sockets:
+            sock.close()
+
+        message = "Stopping reloader process [{}]".format(str(self.pid))
+        color_message = "Stopping reloader process [{}]".format(
+            click.style(str(self.pid), fg="cyan", bold=True)
+        )
+        logger.info(message, extra={"color_message": color_message})
+
+    def should_restart(self) -> list[Path] | None:
+        raise NotImplementedError("Reload strategies should override should_restart()")
+
+
+def _display_path(path: Path) -> str:
+    try:
+        return f"'{path.relative_to(Path.cwd())}'"
+    except ValueError:
+        return f"'{path}'"