|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | 3 | import json |
| 4 | +import logging |
4 | 5 | import os |
5 | 6 | from pathlib import Path |
6 | 7 | import shutil |
|
13 | 14 | from ..demo import demo |
14 | 15 | from ..standalone import _resolve_view, build_standalone0_html |
15 | 16 |
|
| 17 | + |
| 18 | +logger = logging.getLogger(__name__) |
| 19 | + |
16 | 20 | QT_IMPORT_ERROR = ( |
17 | 21 | "PySide6_uibcdf with Qt WebEngine is required for the standalone Qt prototype. " |
18 | 22 | "Install the UIBCDF conda stack from the uibcdf channel:\n" |
@@ -103,6 +107,7 @@ def _load_qt_shell_state() -> dict[str, Any]: |
103 | 107 | try: |
104 | 108 | data = json.loads(path.read_text(encoding="utf-8")) |
105 | 109 | except Exception: |
| 110 | + # Shell state is optional; malformed or unreadable state starts a clean shell. |
106 | 111 | return {"recent_sources": [], "last_source": None, "window_size": None} |
107 | 112 | if not isinstance(data, dict): |
108 | 113 | return {"recent_sources": [], "last_source": None, "window_size": None} |
@@ -140,11 +145,13 @@ def _capture_window_size(window) -> dict[str, int] | None: |
140 | 145 | try: |
141 | 146 | width = int(window.width()) |
142 | 147 | except Exception: |
| 148 | + # Some Qt/fake windows expose a failing getter; the tuple fallback below remains available. |
143 | 149 | width = None |
144 | 150 | if hasattr(window, "height") and callable(window.height): |
145 | 151 | try: |
146 | 152 | height = int(window.height()) |
147 | 153 | except Exception: |
| 154 | + # Some Qt/fake windows expose a failing getter; the tuple fallback below remains available. |
148 | 155 | height = None |
149 | 156 | size = getattr(window, "size", None) |
150 | 157 | if (width is None or height is None) and isinstance(size, tuple) and len(size) == 2: |
@@ -285,6 +292,7 @@ def _persist_shell_state(current_state: dict[str, Any], window=None) -> None: |
285 | 292 | try: |
286 | 293 | _get_helper("_save_qt_shell_state")(current_state) |
287 | 294 | except Exception: |
| 295 | + # Persistence is best-effort and must not interrupt closing or loading the viewer. |
288 | 296 | return |
289 | 297 |
|
290 | 298 |
|
@@ -367,7 +375,7 @@ def _forward_to_view(self, event: dict[str, Any]) -> None: |
367 | 375 | try: |
368 | 376 | self.event_sink(event) |
369 | 377 | except Exception: |
370 | | - pass |
| 378 | + logger.exception("Qt view event failed: %r", event) |
371 | 379 |
|
372 | 380 | def _make_entry(self, message: dict[str, Any]) -> dict[str, Any]: |
373 | 381 | self.next_id += 1 |
@@ -595,6 +603,7 @@ def _decode_qt_bridge_event(url: str) -> dict[str, Any] | None: |
595 | 603 | try: |
596 | 604 | event = json.loads(payload_values[0]) |
597 | 605 | except Exception: |
| 606 | + # Invalid custom-scheme input is rejected at this untrusted transport boundary. |
598 | 607 | return None |
599 | 608 | if not isinstance(event, dict) or not isinstance(event.get("event"), str): |
600 | 609 | return None |
|
0 commit comments