Package Manager¶
The REvoDesign Package Manager is a standalone PyMOL plugin that installs, upgrades, and removes REvoDesign itself. It is not distributed on PyPI -- the manager script is installed as a PyMOL plugin from a GitHub Gist URL, and it manages REvoDesign through pip under the hood.
# The manager serves as both:
# 1. A PyMOL plugin entry point (when __file__ != "package_manager.py")
# 2. A runtime library within REvoDesign (when __file__ == "package_manager.py")
Installation Sources¶
The manager supports three installation sources, selected through the UI:
| Source | Description |
|---|---|
| Repository | Clones and installs from https://github.com/YaoYinYing/REvoDesign. Supports tag/commit pinning (e.g., main, v1.2.0). |
| Local clone/directory | Installs from a local git clone or source directory on disk. |
| Local file | Installs from a local .zip or .tar.gz archive. |
Key Features¶
- Upgrade -- Reinstalls with
--upgradeflag to update an existing installation. - Verbose logging -- Adjustable verbosity level controls pip's
-v/-qflags. - Version/commit pinning -- Tags and branches are parsed from
source@tagsyntax byPIPInstaller.install(). - Proxy support -- HTTP, HTTPS, SOCKS5, and SOCKS5h proxies are supported via the
ALLOWED_PROXY_PROTOCOLSconstant. - Mirror selection -- An alternative PyPI index URL can be specified for regions where the main index is slow.
- Extras selection -- The
CheckableListViewwidget displays extras groups from a remote JSON manifest. Each extra item can declare platform requirements and Python version constraints. - Cache control -- Pip cache management is integrated into the installation workflow.
- Self-upgrades -- Right-click the manager's title bar to upgrade the manager script itself from the Gist.
Architecture¶
WorkerThread (::: REvoDesign.tools.package_manager.WorkerThread)¶
A QThread subclass that executes an arbitrary Python function in a background
thread. Results are returned via result_signal. The thread supports
interruption via requestInterruption() and automatic cleanup of spawned
subprocesses through RunningProcessRegistry.
class WorkerThread(QtCore.QThread):
result_signal = QtCore.pyqtSignal(list)
finished_signal = QtCore.pyqtSignal()
interrupt_signal = QtCore.pyqtSignal()
notify_signal = QtCore.pyqtSignal(str)
progress_val_set_signal = QtCore.pyqtSignal(int)
progress_range_set_signal = QtCore.pyqtSignal(int, int)
ThreadExecutionManager (::: REvoDesign.tools.package_manager.ThreadExecutionManager)¶
Binds a WorkerThread with UI affordances: abort button overlay, progress
reporting, and dashboard integration. Manages the lifecycle of abort overlays
and handles thread cleanup on finish or cancellation.
ThreadDashboard (::: REvoDesign.tools.package_manager.ThreadDashboard)¶
A floating dialog that visualizes all active WorkerThread instances. It
displays task description, duration, and thread ID in a table. Right-click
offers a "Kill" action to force-terminate a thread and its subprocesses.
AbortButtonOverlay (::: REvoDesign.tools.package_manager.AbortButtonOverlay)¶
An overlay widget that reveals a red "Abort" button when hovering over a
trigger button. It acts as a non-modal interruption mechanism: clicking it
calls cmd.interrupt() and requests the worker thread to stop.
ThreadPoolRegistry (::: REvoDesign.tools.package_manager.ThreadPoolRegistry)¶
Global registry tracking running WorkerThread instances. Thread-safe (uses a
threading.Lock). Automatically syncs with ThreadDashboard on register and
unregister.
RunningProcessRegistry (::: REvoDesign.tools.package_manager.RunningProcessRegistry)¶
Tracks subprocesses spawned within worker threads, enabling cancellation. Each
subprocess.Popen is linked to its parent worker via TLS (_WORKER_CONTEXT).
On termination, all tracked processes are terminated, waited, and if necessary
killed.
REvoDesignPackageManager (::: REvoDesign.tools.package_manager.REvoDesignPackageManager)¶
The top-level orchestrator. It:
1. Fetches the UI file (REvoDesign-PyMOL-entry.ui) from Gist and loads it via loadUi
2. Fetches the extras manifest JSON (REvoDesignExtrasTableRich.json) from Gist
3. Fetches GitHub release tags for version selection
4. Registers PyMOL menu items (Install, Reinstall, Uninstall, Manager)
5. Configures proxy, mirror, and extras in the UI
6. Delegates pip operations to PIPInstaller
The UI File¶
The manager's graphical interface is defined in REvoDesign-PyMOL-entry.ui,
a Qt Designer file stored at src/REvoDesign/UI/REvoDesign-PyMOL-entry.ui.
This file is uploaded to a GitHub Gist via make upload-gists and fetched at
runtime by the manager plugin.
Extras Registry¶
The file REvoDesignExtrasTableRich.json (version-tracked alongside the UI
file on Gist) defines available extras. It is fetched at manager startup and
displayed in a CheckableListView widget. Each extras entry can specify:
name-- Display nameextras_id-- The pip extras identifier (e.g.,[scatter])depts-- Category tagsdescription-- Human-readable descriptionplatform-- Required hardware platform (CUDA,MPS)python_version-- Python version constraint (e.g.,>=3.8,<3.12)
The extras groups are modeled by three dataclasses:
- ::: REvoDesign.tools.package_manager.ExtrasItem
- ::: REvoDesign.tools.package_manager.ExtrasGroup
- ::: REvoDesign.tools.package_manager.ExtrasGroups
PIPInstaller (::: REvoDesign.tools.package_manager.PIPInstaller)¶
Wraps pip install, pip uninstall, and ensurepip as a Python API. Key
behaviors:
- Automatically upgrades pip before any REvoDesign installation
- Supports extras via
package_name[extras1,extras2]syntax - Supports mirror URLs with
-iflag - Verbosity is controlled by an integer level (negative = silent, positive = verbose)
- Returns a
LiveProcessResultwith captured stdout/stderr
GitSolver (::: REvoDesign.tools.package_manager.GitSolver)¶
Detects available package managers on the current system (winget, choco, scoop,
conda, mamba, brew, apt, dnf, yum, zypper, pacman, pkg, snap, port) and
attempts to install Git if it is missing. The INSTALLERS class variable is an
ordered tuple of PackageManagerCommand dataclasses that define each
platform's install command.
Self-Upgrades¶
The manager can upgrade itself. A right-click context menu on the
ThreadDashboard table or the manager dialog triggers a fetch of the latest
manager script from the Gist, replacing the running module.
Thread Management Flow¶
User clicks "Install"
|
v
REvoDesignPackageManager
-> PIPInstaller.install()
-> run_command() # spawns subprocess.Popen
-> RunningProcessRegistry tracks the process
-> WorkerThread wraps the pip call
-> ThreadPoolRegistry registers the thread
-> ThreadDashboard updates its table
-> ThreadExecutionManager provides abort overlay
-> On completion or abort:
-> RunningProcessRegistry clears processes
-> ThreadPoolRegistry unregisters thread
-> ThreadDashboard refreshes