Resulable besim handof so recompiling model does not give second besim window

This commit is contained in:
Joppe Blondel
2026-08-02 12:05:08 +02:00
parent 4b565edb5c
commit c8373c3423
6 changed files with 150 additions and 1 deletions
@@ -0,0 +1,72 @@
from __future__ import annotations
import json
from pathlib import Path
from PySide6.QtCore import QObject, Signal
from PySide6.QtNetwork import QLocalServer, QLocalSocket
from bedit_gui.simulation_models import CompiledModel
SERVER_NAME = "bedit-besim-handoff-v1"
def send_simulation_handoff(path: str | Path, compiled_model: CompiledModel, *, server_name: str = SERVER_NAME, timeout_ms: int = 500) -> bool:
socket = QLocalSocket()
socket.connectToServer(server_name)
if not socket.waitForConnected(timeout_ms):
return False
payload = json.dumps({"path": str(Path(path).resolve()), "compiled_model": compiled_model.to_data()}, separators=(",", ":")).encode("utf-8") + b"\n"
if socket.write(payload) != len(payload) or not socket.waitForBytesWritten(timeout_ms):
socket.abort()
return False
socket.disconnectFromServer()
return True
class SimulationHandoffServer(QObject):
handoff_received = Signal(object, object)
def __init__(self, parent: QObject | None = None, *, server_name: str = SERVER_NAME) -> None:
super().__init__(parent)
self.server = QLocalServer(self)
self._buffers: dict[QLocalSocket, bytearray] = {}
self.server.newConnection.connect(self._accept_connections)
if not self.server.listen(server_name):
probe = QLocalSocket()
probe.connectToServer(server_name)
if probe.waitForConnected(200):
probe.disconnectFromServer()
return
QLocalServer.removeServer(server_name)
if not self.server.listen(server_name):
raise RuntimeError(f"could not listen for BEsim handoffs: {self.server.errorString()}")
def _accept_connections(self) -> None:
while self.server.hasPendingConnections():
socket = self.server.nextPendingConnection()
if socket is None:
continue
self._buffers[socket] = bytearray()
socket.readyRead.connect(lambda active=socket: self._read(active))
socket.disconnected.connect(lambda active=socket: self._discard(active))
self._read(socket)
def _read(self, socket: QLocalSocket) -> None:
buffer = self._buffers.get(socket)
if buffer is None:
return
buffer.extend(socket.readAll().data())
while b"\n" in buffer:
raw_message, _, remaining = buffer.partition(b"\n")
buffer[:] = remaining
try:
message = json.loads(raw_message.decode("utf-8"))
path = Path(str(message["path"]))
compiled_model = CompiledModel.from_data(message["compiled_model"])
except (KeyError, TypeError, ValueError, json.JSONDecodeError, UnicodeDecodeError):
continue
self.handoff_received.emit(path, compiled_model)
def _discard(self, socket: QLocalSocket) -> None:
self._buffers.pop(socket, None)