Skip to content

fix: Resolve test segfaults / hang + Qt compatibility update + .pre-commit-config - #391

Merged
hongquanli merged 4 commits into
masterfrom
fix/test-segfaults-and-qt-compatibility
Dec 28, 2025
Merged

fix: Resolve test segfaults / hang + Qt compatibility update + .pre-commit-config#391
hongquanli merged 4 commits into
masterfrom
fix/test-segfaults-and-qt-compatibility

Conversation

@hongquanli

@hongquanli hongquanli commented Dec 28, 2025

Copy link
Copy Markdown
Contributor
  • Add tests/control/conftest.py with autouse fixture to clean up Microcontroller threads after each test, preventing segfaults
  • Fix QVariant usage in widgets.py (not available in PySide6)
  • Fix PyQt5 imports in laser_auto_focus_controller.py, NL5Widget.py, and test_HighContentScreeningGui.py - use qtpy for compatibility
  • Fix deprecated QDesktopWidget in core.py - use QScreen instead
  • Re-enable test_preferences_dialog.py in CI (thread cleanup fixes it)
  • Skip test_HighContentScreeningGui.py in CI due to separate PySide6 QObject double-init bug that needs separate fix

This pull request introduces several improvements and fixes across the codebase, focusing on modernizing Qt imports, improving test reliability, and refining signal usage for wellplate settings. The most notable changes include migrating from PyQt5 to qtpy for better compatibility, adding automated cleanup for background threads in tests to prevent segfaults, and updating signal definitions to use native Python types instead of QVariant.

Qt import modernization:

  • Migrated all PyQt5 imports to use qtpy in files such as NL5Widget.py, laser_auto_focus_controller.py, and test modules, improving compatibility with multiple Qt bindings. [1] [2] [3] [4]

Testing reliability and infrastructure:

  • Added a new pytest fixture in tests/control/conftest.py to automatically clean up Microcontroller instances after each test, preventing background threads from causing segfaults in subsequent tests.
  • Updated the GitHub Actions workflow to skip test_HighContentScreeningGui.py during CI runs due to a known PySide6 bug, allowing other tests to run uninterrupted.
  • Improved a test in test_preferences_dialog.py by mocking QMessageBox.warning to avoid blocking during error handling, ensuring tests remain non-interactive.

Signal and data type improvements:

  • Changed the signalWellplateSettings signal in widgets.py to use native Python types (e.g., str) instead of QVariant, simplifying signal emission and usage. [1] [2]

Code formatting and style:

  • Added a .pre-commit-config.yaml to enable automatic code formatting with black for the software/ directory, ensuring consistent Python style.

UI and usability fixes:

  • Updated window sizing logic in core.py to use QApplication.primaryScreen().availableGeometry() instead of QDesktopWidget, improving compatibility and future-proofing the code.

- Add tests/control/conftest.py with autouse fixture to clean up
  Microcontroller threads after each test, preventing segfaults
- Fix QVariant usage in widgets.py (not available in PySide6)
- Fix PyQt5 imports in laser_auto_focus_controller.py, NL5Widget.py,
  and test_HighContentScreeningGui.py - use qtpy for compatibility
- Fix deprecated QDesktopWidget in core.py - use QScreen instead
- Re-enable test_preferences_dialog.py in CI (thread cleanup fixes it)
- Skip test_HighContentScreeningGui.py in CI due to separate PySide6
  QObject double-init bug that needs separate fix

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@hongquanli hongquanli changed the title fix: Add Microcontroller thread cleanup and fix Qt compatibility issues fix: CI - add Microcontroller thread cleanup and fix Qt compatibility issues Dec 28, 2025
hongquanli and others added 3 commits December 27, 2025 23:12
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
…y_file

The test was blocking on an unmocked QMessageBox.warning dialog when testing
file permission errors.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR addresses CI test failures by fixing thread cleanup issues and Qt compatibility problems. The main fix adds a pytest autouse fixture that automatically cleans up Microcontroller background threads after each test, preventing segfaults. Additionally, the PR updates Qt-related code to work with PySide6 by removing QVariant usage, fixing deprecated QDesktopWidget, and standardizing on qtpy imports.

Key changes:

  • Added automatic Microcontroller thread cleanup fixture to prevent test segfaults
  • Removed QVariant usage for PySide6 compatibility in Signal definitions
  • Migrated from direct PyQt5 imports to qtpy for cross-compatibility
  • Replaced deprecated QDesktopWidget with QScreen API

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
software/tests/control/conftest.py New autouse fixture to track and clean up Microcontroller instances after each test
software/control/widgets.py Replaced QVariant with str in Signal definition for PySide6 compatibility
software/control/core/laser_auto_focus_controller.py Consolidated PyQt5/qtpy imports to use qtpy.QtCore exclusively
software/control/NL5Widget.py Migrated PyQt5 imports to qtpy for Qt framework compatibility
software/tests/control/test_HighContentScreeningGui.py Updated to use qtpy instead of PyQt5
software/tests/control/test_preferences_dialog.py Added QMessageBox.warning mock to prevent blocking during error handling tests
software/control/core/core.py Replaced deprecated QDesktopWidget with QApplication.primaryScreen()
.github/workflows/main.yml Re-enabled test_preferences_dialog.py and temporarily skipped test_HighContentScreeningGui.py
.pre-commit-config.yaml Added black pre-commit hook configuration (not mentioned in PR description)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread .pre-commit-config.yaml
Comment on lines +1 to +8
repos:
- repo: https://github.com/psf/black
rev: 24.10.0
hooks:
- id: black
language_version: python3
args: ["--config", "software/pyproject.toml"]
files: ^software/

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of .pre-commit-config.yaml is not mentioned in the PR description. This appears to be an unrelated change to the stated purpose of fixing CI thread cleanup and Qt compatibility issues. Consider either updating the PR description to document this addition or moving it to a separate PR for better change tracking and code review clarity.

Copilot uses AI. Check for mistakes.
QDialogButtonBox,
)
from PyQt5.QtCore import Qt
from qtpy.QtCore import Qt

Copilot AI Dec 28, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import of 'Qt' is not used.

Suggested change
from qtpy.QtCore import Qt

Copilot uses AI. Check for mistakes.
@hongquanli hongquanli changed the title fix: CI - add Microcontroller thread cleanup and fix Qt compatibility issues fix: Resolve test segfaults / hang + Qt compatibility update + .pre-commit-config Dec 28, 2025
@hongquanli
hongquanli merged commit 67dfbf5 into master Dec 28, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants