WCNegentropy commited on
Commit
35c1128
·
verified ·
1 Parent(s): b31ca06

🚀 Refined BitTransformerLM: Organized codebase with best practices

Browse files
Files changed (1) hide show
  1. scripts/tools/watcher.py +80 -0
scripts/tools/watcher.py ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import argparse
2
+ import subprocess
3
+ import sys
4
+ import time
5
+ from pathlib import Path
6
+ from watchdog.events import FileSystemEventHandler
7
+ from watchdog.observers import Observer
8
+
9
+
10
+ class RestartOnChange(FileSystemEventHandler):
11
+ """Restart a subprocess when watched files change."""
12
+
13
+ def __init__(self, command: list[str], watch_paths: list[str]) -> None:
14
+ self.command = command
15
+ self.watch_paths = [Path(p).resolve() for p in watch_paths]
16
+ self.process: subprocess.Popen | None = None
17
+ self.restart()
18
+
19
+ def restart(self) -> None:
20
+ if self.process and self.process.poll() is None:
21
+ self.process.terminate()
22
+ try:
23
+ self.process.wait(timeout=5)
24
+ except subprocess.TimeoutExpired:
25
+ self.process.kill()
26
+ self.process.wait()
27
+ self.process = subprocess.Popen(self.command)
28
+
29
+ def on_any_event(self, event) -> None: # pragma: no cover - runtime utility
30
+ if event.is_directory:
31
+ return
32
+ path = Path(event.src_path)
33
+ if path.suffix != ".py":
34
+ return
35
+ if any(str(path).startswith(str(p)) for p in self.watch_paths):
36
+ print(f"[watcher] {path} changed, running tests...")
37
+ subprocess.run([sys.executable, "-m", "pytest", "-q"])
38
+ print("[watcher] restarting process...")
39
+ self.restart()
40
+
41
+
42
+ def main() -> None: # pragma: no cover - CLI entry
43
+ parser = argparse.ArgumentParser(
44
+ description="Watch files and restart a command on changes",
45
+ )
46
+ parser.add_argument(
47
+ "--command",
48
+ nargs="+",
49
+ default=[sys.executable, "mcp_server.py"],
50
+ help="Command to run",
51
+ )
52
+ parser.add_argument(
53
+ "--paths",
54
+ nargs="+",
55
+ default=["bit_transformer", "mcp_server.py"],
56
+ help="Paths to watch for changes",
57
+ )
58
+ args = parser.parse_args()
59
+
60
+ observer = Observer()
61
+ handler = RestartOnChange(args.command, args.paths)
62
+ for p in args.paths:
63
+ observer.schedule(handler, p, recursive=True)
64
+ observer.start()
65
+ try:
66
+ while True:
67
+ time.sleep(1)
68
+ except KeyboardInterrupt:
69
+ pass
70
+ finally:
71
+ observer.stop()
72
+ handler.restart()
73
+ if handler.process and handler.process.poll() is None:
74
+ handler.process.terminate()
75
+ handler.process.wait()
76
+ observer.join()
77
+
78
+
79
+ if __name__ == "__main__": # pragma: no cover - CLI entry
80
+ main()