add dev run command

This commit is contained in:
Izalia Mae 2024-03-20 10:59:50 -04:00
parent a579c5f145
commit 8e00caff4c

98
dev.py
View file

@ -4,7 +4,9 @@ import shlex
import shutil
import subprocess
import sys
import time
from datetime import datetime
from gemi import __version__
from pathlib import Path
from tempfile import TemporaryDirectory
@ -12,15 +14,23 @@ from tempfile import TemporaryDirectory
try:
import click
except ImportError:
proc = subprocess.run([sys.executable, "-m", "pip", "install", "click"], check = False)
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
if proc.returncode != 0:
except ImportError:
CMD = f"{sys.executable} -m pip install watchdog click"
PROC = subprocess.run(shlex.split(CMD), check = False)
if PROC.returncode != 0:
sys.exit()
print("Successfully installed click")
print("Successfully installed click and watchdog")
import click
from watchdog.observers import Observer
from watchdog.events import PatternMatchingEventHandler
REPO = Path(__file__).resolve().parent
@ -93,5 +103,85 @@ def cli_install():
subprocess.run(shlex.split(f"{sys.executable} -m pip install -e .[dev,doc]"), check = False)
@cli.command("run")
def cli_run():
print("Starting process watcher")
handler = WatchHandler()
handler.run_proc()
watcher = Observer()
watcher.schedule(handler, str(REPO.joinpath("gemi")), recursive=True)
watcher.start()
try:
while True:
handler.proc.stdin.write(sys.stdin.read().encode("UTF-8")) # type: ignore
handler.proc.stdin.flush() # type: ignore
except KeyboardInterrupt:
pass
handler.kill_proc()
watcher.stop()
watcher.join()
class WatchHandler(PatternMatchingEventHandler):
patterns = ["*.py"]
cmd = [sys.executable, "-m", "gemi.server"]
def __init__(self):
PatternMatchingEventHandler.__init__(self)
self.proc: subprocess.Popen | None = None
self.last_restart: datetime | None = None
def kill_proc(self):
if not self.proc or self.proc.poll() is not None:
return
print(f"Terminating process {self.proc.pid}")
self.proc.terminate()
sec = 0.0
while self.proc.poll() is None:
time.sleep(0.1)
sec += 0.1
if sec >= 5:
print("Failed to terminate. Killing process...")
self.proc.kill()
break
print("Process terminated")
def run_proc(self, restart=False):
timestamp = datetime.timestamp(datetime.now())
self.last_restart = timestamp if not self.last_restart else 0
if restart:
if timestamp - 3 < self.last_restart:
return
self.kill_proc()
self.proc = subprocess.Popen(self.cmd, stdin = subprocess.PIPE)
self.last_restart = timestamp
print(f"Started process with PID {self.proc.pid}", self.proc.pid)
print("Command:", " ".join(self.cmd))
def on_any_event(self, event):
if event.event_type not in ["modified", "created", "deleted"]:
return
self.run_proc(restart = True)
if __name__ == "__main__":
cli()