fix: satisfy basedpyright on the Optional subscriber and socket
CI / lint (push) Skipped
CI / test (3.12) (push) Skipped
CI / test (3.13) (push) Skipped
CI / test-with-beamline-plugins (pxi_bec) (push) Skipped
CI / test-with-beamline-plugins (pxii_bec) (push) Skipped
CI / test-with-beamline-plugins (pxiii_bec) (push) Skipped
CI / lint (pull_request) Successful in 47s
CI / test (3.12) (pull_request) Successful in 1m5s
CI / test (3.13) (pull_request) Successful in 1m5s
CI / test (3.14) (pull_request) Successful in 1m5s
CI / test-with-beamline-plugins (pxi_bec) (pull_request) Successful in 1m8s
CI / test-with-beamline-plugins (pxii_bec) (pull_request) Successful in 1m11s
CI / test-with-beamline-plugins (pxiii_bec) (pull_request) Successful in 1m27s
CI / test-with-coverage (pull_request) Successful in 1m37s
CI / coverage-analysis (pull_request) Failing after 3s

CI lint failed on reportOptionalMemberAccess: prediction_thread is None
when the GUI runs without a sample feed, and _sock is nulled by run()'s
cleanup, so both attributes are Optional to the checker even though the
flagged call sites cannot see None at runtime. Guard the slot and bind
the socket to a local asserted non-None in _recv_latest.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
2026-09-08 14:16:16 +02:00
co-authored by Claude Fable 5.1
parent 7c1efe4384
commit c0b0994fed
2 changed files with 10 additions and 3 deletions
+4 -1
View File
@@ -1631,7 +1631,10 @@ class MainWindow(QMainWindow):
if view.isVisible():
view.update_pixmap(pixmap)
finally:
self.prediction_thread.notify_frame_displayed()
# The slot is only connected once the subscriber exists, but the
# attribute is Optional so the guard is what the type checker needs.
if self.prediction_thread is not None:
self.prediction_thread.notify_frame_displayed()
@Slot(bool)
def _on_sample_camera_availability_changed(self, available: bool) -> None:
@@ -201,10 +201,14 @@ class PredictionSubscriber(QThread):
backlog that piled up while we were busy, and the stream is always
consumed at line rate no matter how long a frame takes to decode.
"""
parts = self._sock.recv_multipart() # honours RCVTIMEO, may raise zmq.Again
# Bind locally: run() nulls the attribute on cleanup, so it is Optional
# to the type checker even though it cannot be None while run() loops.
sock = self._sock
assert sock is not None, "_recv_latest called after the socket was closed"
parts = sock.recv_multipart() # honours RCVTIMEO, may raise zmq.Again
while True:
try:
parts = self._sock.recv_multipart(zmq.NOBLOCK)
parts = sock.recv_multipart(zmq.NOBLOCK)
except zmq.Again:
return parts
self._dropped += 1