diff --git a/src/aare/daq/server.py b/src/aare/daq/server.py index 8735924b..3e4d39fe 100644 --- a/src/aare/daq/server.py +++ b/src/aare/daq/server.py @@ -1,5 +1,6 @@ import asyncio import hmac +import importlib import io import json import os @@ -47,6 +48,7 @@ from fastapi import status as api_status from fastapi.concurrency import run_in_threadpool from fastapi.security import OAuth2PasswordBearer from starlette.responses import StreamingResponse +from uvicorn.workers import UvicornWorker # deprecated shim, present in pinned 0.34.2 from aare.daq import auth from aare.daq.config import BeamlineConfig @@ -80,6 +82,12 @@ _automation_progress_state: dict = {"seq": 0, "progress": None} _automation_progress_state_lock = asyncio.Lock() +class AareUvicornWorker(UvicornWorker): + # CONFIG_KWARGS merged last into uvicorn Config (uvicorn/workers.py:69) → + # keeps our access-log filter + proxy_headers under gunicorn. + CONFIG_KWARGS = {"log_config": get_uvicorn_logging_config(), "proxy_headers": False} + + @asynccontextmanager async def lifespan(application: FastAPI): """ @@ -722,6 +730,16 @@ def initialise_detector(self): raise +@app.get("/about/installed_version") +async def running_version() -> str: + return importlib.metadata.version("aare") + + +@app.get("/about/server_file_path") +async def server_file() -> str: + return __file__ + + @app.get("/local_contact/simulation_state") async def local_contact_simulation_state(token: str = Depends(oauth2_scheme)) -> dict: """ diff --git a/src/aare/gui/about.py b/src/aare/gui/about.py index 4db38cb4..0119fa04 100644 --- a/src/aare/gui/about.py +++ b/src/aare/gui/about.py @@ -1,18 +1,29 @@ +from __future__ import annotations + import importlib import sys +from typing import TYPE_CHECKING + +if TYPE_CHECKING: + from aare.gui.threads.daq_worker import DAQWorker -def about_text(): +def about_text(client: "DAQWorker"): from aare.gui import gui try: version = importlib.metadata.version("aaredaq") except Exception: version = "Not found - package is not installed into the environment." + + server_version, server_file_path = client.server_about_info() + return f"""Aare Macromolecular Crystallography GUI Copyright: Paul Scherrer Institute 2023-2026 --- Version: {version} GUI file: {gui.__file__} Interpreter: {sys.executable} +Server version: {server_version} +Server file: {server_file_path} """ diff --git a/src/aare/gui/main_window.py b/src/aare/gui/main_window.py index 06cb4220..2dc40a1b 100644 --- a/src/aare/gui/main_window.py +++ b/src/aare/gui/main_window.py @@ -1606,7 +1606,7 @@ class MainWindow(QMainWindow): self.video_tab.setCurrentIndex(0) def show_about_dialog(self): - QMessageBox.about(self, "About", about_text()) + QMessageBox.about(self, "About", about_text(self.daq)) def show_controls_help(self) -> None: if self._controls_help_dialog is None: diff --git a/src/aare/gui/scan_logic/rotation_scan_manager.py b/src/aare/gui/scan_logic/rotation_scan_manager.py index 2d9c41d7..ec17b8e1 100644 --- a/src/aare/gui/scan_logic/rotation_scan_manager.py +++ b/src/aare/gui/scan_logic/rotation_scan_manager.py @@ -10,10 +10,8 @@ class RotationScanManager(QObject): super().__init__(parent) self.__beamline = mx_beamline() self.__detector_url = get_jfjoch_url(self.__beamline) - self.__detector_url = None @Slot(CompletedRotationScan) def scan_completed(self, r: CompletedRotationScan): if r.result.file_prefix is not None: - # self.file_ready.emit(r.result.file_prefix, 0) self.file_ready.emit(self.__detector_url, 0) diff --git a/src/aare/gui/threads/daq_worker.py b/src/aare/gui/threads/daq_worker.py index 29831a8c..882b18eb 100644 --- a/src/aare/gui/threads/daq_worker.py +++ b/src/aare/gui/threads/daq_worker.py @@ -356,6 +356,17 @@ class DAQWorker(QObject): reply = self.__net_manager.get(request) reply.finished.connect(lambda: self.handle_status_response(reply)) + def server_about_info(self) -> tuple[str, str]: + version_request = QNetworkRequest(QUrl(f"{self.__base_url}/about/running_version")) + version_reply = self.__net_manager.get(version_request) + file_request = QNetworkRequest(QUrl(f"{self.__base_url}/about/server_file_path")) + file_reply = self.__net_manager.get(file_request) + version = ( + str(version_reply.readAll()) if version_reply.waitForReadyRead(500) else "Not connected" + ) + file = str(file_reply.readAll()) if file_reply.waitForReadyRead(500) else "Not connected" + return version, file + _SELF_SIGNED_ERRORS = { QSslError.SslError.SelfSignedCertificate, QSslError.SslError.SelfSignedCertificateInChain,