Skip to content

Run update check in a separate thread#3234

Open
mikhailmikhalchuk wants to merge 12 commits intoDeepLabCut:mainfrom
mikhailmikhalchuk:main
Open

Run update check in a separate thread#3234
mikhailmikhalchuk wants to merge 12 commits intoDeepLabCut:mainfrom
mikhailmikhalchuk:main

Conversation

@mikhailmikhalchuk
Copy link
Copy Markdown

Currently DLC checks for updates to the program in a manner that is blocking. On my machine I've observed it freezes the program for up to 5-10secs to check this. This change threads it so it is not blocking the run loop.

@C-Achard
Copy link
Copy Markdown
Collaborator

Hello @mikhailmikhalchuk, thanks for the PR !

I made a few improvements that use the more Qt-native QThread/QProcess system to avoid issues with opening QMessageBox in another thread, and centralized/cleaned up the helpers a bit.

@C-Achard C-Achard requested a review from Copilot March 10, 2026 09:49
@C-Achard C-Achard self-assigned this Mar 10, 2026
@C-Achard C-Achard added enhancement New feature or request GUI issues relating to GUI labels Mar 10, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 moves the GUI update check off the main run loop by introducing a background Qt thread worker, preventing the application from freezing during network version checks.

Changes:

  • Replaced the blocking GUI update-check logic with a QThread + UpdateCheckWorker flow.
  • Added shared PyPI version-check helpers in deeplabcut/gui/utils.py with real network timeouts and better version comparisons (via packaging when available).
  • Switched the “Update” action to run pip install -U ... via QProcess rather than blocking subprocess.

Reviewed changes

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

File Description
deeplabcut/utils/multiprocessing.py Adds a deprecation note related to the old timeout helper (now unused by update-check path).
deeplabcut/gui/window.py Introduces threaded update checks and non-blocking package update installs via QProcess.
deeplabcut/gui/utils.py Adds PyPI version-check utilities and a Qt worker object to run checks in a background thread.

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

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

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


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

You can also share your feedback on Copilot code review. Take the survey.

@C-Achard
Copy link
Copy Markdown
Collaborator

Thanks for the additions @mikhailmikhalchuk !

I think this is a great contribution and I'm strongly in favor of merging it; we just need to ensure it fits neatly with our use of Qt.
After checking the Qt API, I think using QNetwork makes more sense here than my previous suggestion of using workers, as it simplifies the lifecycle management and is more straightforward overall for the current goal.

I will take care of the final details today; no need to worry about Copilot reviews, I will handle those if needed.

Once I’ve pushed the final changes, please feel free to take another look and share any further feedback you may have.

Best,
Cyril

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

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


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

You can also share your feedback on Copilot code review. Take the survey.

@C-Achard C-Achard requested review from deruyter92 and removed request for C-Achard March 11, 2026 10:43
Copy link
Copy Markdown
Collaborator

@deruyter92 deruyter92 left a comment

Choose a reason for hiding this comment

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

Looks good to me, just minor comments.

Copy link
Copy Markdown
Collaborator

@deruyter92 deruyter92 left a comment

Choose a reason for hiding this comment

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

Looks good! Thanks

@C-Achard C-Achard added the lint required Please run pre-commit hooks to ensure your formatting is up-to-date label Mar 30, 2026
mikhailmikhalchuk and others added 10 commits March 30, 2026 13:27
Introduce a non-blocking update check and in-app updater.

Key changes:
- deeplabcut/gui/utils.py: add check_pypi_version, is_latest_deeplabcut_version/is_latest_plugin_version, and UpdateCheckWorker (Qt QObject) to fetch PyPI info with timeouts and packaging-aware version comparison; handle network errors gracefully.
- deeplabcut/gui/window.py: replace the blocking _check_for_updates flow with a Qt-threaded update check (schedule_update_check, _start_update_check) that uses UpdateCheckWorker; add UI handling for results, prompt to update and run pip installs via QProcess, and cancel/cleanup on exit. Removed previous blocking imports/usages (subprocess, threading, call_with_timeout).
- deeplabcut/utils/multiprocessing.py: mark call_with_timeout as deprecated for update checks (note only), since it's no longer used for update checking.

Why: make update checking robust and non-blocking, avoid freezing the GUI, support plugin/version checks, provide an integrated, user-friendly update flow with proper error handling.
Co-Authored-By: Mikhail Mikhalchuk <[email protected]>
Accumulate and surface output from the pip update QProcess so users get live feedback and the full output after the process finishes. Added a _update_process_output list, initialized when starting/tearing down updates, and a helper _drain_update_process_output() that reads available data, appends it to the buffer, logs the latest non-empty line and shows it in the status bar. The finished handler now drains remaining output, builds the final output by joining the buffer, and resets the buffer and status message. Also added a clarifying comment in utils.py about making the plugin check optional in the future.
Reduce the UpdateCheckWorker timeout from 5.0s to 2.0s to make plugin/version checks quicker, and increase the update thread quit wait from 1000ms to 4000ms to give the thread more time to shut down cleanly. Changes applied in deeplabcut/gui/utils.py and deeplabcut/gui/window.py.
Ensure cancellation is handled
Missed deleteLater (qt tries to clean this up)
Replace the old thread/worker based update check with a single QtNetwork-backed UpdateChecker that issues async HTTP requests to PyPI for both deeplabcut and napari-deeplabcut, enforces a QTimer timeout, aggregates results, and supports silent/manual checks and cancellation. Integrate the new checker into MainWindow (use DLC and NAPARI_DLC __version__ imports), simplify scheduling, and connect finished signal to the existing handler. Also add safer shutdown handling (_closing flag), drain update process output, and minor UI/version label updates.
Replace singleShot scheduling with a dedicated QTimer to manage update checks. Adds _update_check_timer and _scheduled_update_check_silent to schedule, supersede, and run delayed checks via check_for_updates(..., delay_ms). Wire up startup and menu actions to the new API and stop the timer during shutdown. This prevents overlapping checks, allows cancelation on close, and centralizes delayed-check logic.
Add "packaging>=26.0" to pyproject.toml dependencies and update uv.lock to include the new requirement.
Add a _cleanup_update_process helper to centralize teardown of the update QProcess (deleteLater, clear output buffer, hide progress bar, reset status message). Replace duplicated cleanup code in _on_update_process_error, _on_update_process_finished and the finish handler with calls to this helper, add appropriate early returns and guards, and rewrap a long error message for readability. This reduces duplication and simplifies the update process error/finish handling.
@C-Achard
Copy link
Copy Markdown
Collaborator

Rebased as per #3263: please make sure to reset your local branch to track the current remote state if needed.

A local backup of the pre-rebase branch was made, if you feel there is an issue with the rebased branch please let us know and we will restore it.

@C-Achard C-Achard removed the lint required Please run pre-commit hooks to ensure your formatting is up-to-date label Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request GUI issues relating to GUI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants