From d7fb171f101bf36495a106fbca296515f692b080 Mon Sep 17 00:00:00 2001 From: iLLiCiTiT Date: Thu, 13 Jan 2022 13:08:35 +0100 Subject: [PATCH] added check if current running openpype has expected version --- openpype/lib/__init__.py | 6 ++- openpype/lib/pype_info.py | 48 +++++++++++++++++---- openpype/tools/tray/pype_tray.py | 74 ++++++++++++++++++++++++++++++-- 3 files changed, 115 insertions(+), 13 deletions(-) diff --git a/openpype/lib/__init__.py b/openpype/lib/__init__.py index 12e47a8961..65019f3fab 100644 --- a/openpype/lib/__init__.py +++ b/openpype/lib/__init__.py @@ -170,7 +170,9 @@ from .editorial import ( from .pype_info import ( get_openpype_version, - get_build_version + get_build_version, + is_running_from_build, + is_current_version_studio_latest ) terminal = Terminal @@ -304,4 +306,6 @@ __all__ = [ "get_openpype_version", "get_build_version", + "is_running_from_build", + "is_current_version_studio_latest", ] diff --git a/openpype/lib/pype_info.py b/openpype/lib/pype_info.py index 15856bfb19..ea804c8a18 100644 --- a/openpype/lib/pype_info.py +++ b/openpype/lib/pype_info.py @@ -10,6 +10,12 @@ from openpype.settings.lib import get_local_settings from .execute import get_openpype_execute_args from .local_settings import get_local_site_id from .python_module_tools import import_filepath +from .openpype_version import ( + op_version_control_available, + openpype_path_is_accessible, + get_expected_studio_version, + get_OpenPypeVersion +) def get_openpype_version(): @@ -17,15 +23,6 @@ def get_openpype_version(): return openpype.version.__version__ -def get_pype_version(): - """Backwards compatibility. Remove when 100% not used.""" - print(( - "Using deprecated function 'openpype.lib.pype_info.get_pype_version'" - " replace with 'openpype.lib.pype_info.get_openpype_version'." - )) - return get_openpype_version() - - def get_build_version(): """OpenPype version of build.""" # Return OpenPype version if is running from code @@ -138,3 +135,36 @@ def extract_pype_info_to_file(dirpath): with open(filepath, "w") as file_stream: json.dump(data, file_stream, indent=4) return filepath + + +def is_current_version_studio_latest(): + """Is currently running OpenPype version which is defined by studio. + + It is not recommended to ask in each process as there may be situations + when older OpenPype should be used. For example on farm. But it does make + sense in processes that can run for a long time. + + Returns: + None: Can't determine. e.g. when running from code or the build is + too old. + bool: True when is using studio + """ + output = None + # Skip if is not running from build + if not is_running_from_build(): + return output + + # Skip if build does not support version control + if not op_version_control_available(): + return output + + # Skip if path to folder with zip files is not accessible + if not openpype_path_is_accessible(): + return output + + # Check if current version is expected version + OpenPypeVersion = get_OpenPypeVersion() + current_version = OpenPypeVersion(get_openpype_version()) + expected_version = get_expected_studio_version(is_running_staging()) + + return current_version == expected_version diff --git a/openpype/tools/tray/pype_tray.py b/openpype/tools/tray/pype_tray.py index e7ac390c30..5af82b2c64 100644 --- a/openpype/tools/tray/pype_tray.py +++ b/openpype/tools/tray/pype_tray.py @@ -14,7 +14,11 @@ from openpype.api import ( resources, get_system_settings ) -from openpype.lib import get_openpype_execute_args +from openpype.lib import ( + get_openpype_execute_args, + is_current_version_studio_latest, + is_running_from_build +) from openpype.modules import TrayModulesManager from openpype import style from openpype.settings import ( @@ -27,11 +31,43 @@ from openpype.tools.utils import WrappedCallbackItem from .pype_info_widget import PypeInfoWidget +class VersionDialog(QtWidgets.QDialog): + def __init__(self, parent=None): + super(VersionDialog, self).__init__(parent) + + label_widget = QtWidgets.QLabel( + "Your version does not match to studio version", self + ) + + ignore_btn = QtWidgets.QPushButton("Ignore", self) + restart_btn = QtWidgets.QPushButton("Restart and Install", self) + + btns_layout = QtWidgets.QHBoxLayout() + btns_layout.addStretch(1) + btns_layout.addWidget(ignore_btn, 0) + btns_layout.addWidget(restart_btn, 0) + + layout = QtWidgets.QVBoxLayout(self) + layout.addWidget(label_widget, 0) + layout.addStretch(1) + layout.addLayout(btns_layout, 0) + + ignore_btn.clicked.connect(self._on_ignore) + restart_btn.clicked.connect(self._on_reset) + + def _on_ignore(self): + self.reject() + + def _on_reset(self): + self.accept() + + class TrayManager: """Cares about context of application. Load submenus, actions, separators and modules into tray's context. """ + _version_check_interval = 5 * 60 * 1000 def __init__(self, tray_widget, main_window): self.tray_widget = tray_widget @@ -46,6 +82,9 @@ class TrayManager: self.errors = [] + self._version_check_timer = None + self._version_dialog = None + self.main_thread_timer = None self._main_thread_callbacks = collections.deque() self._execution_in_progress = None @@ -62,6 +101,24 @@ class TrayManager: if callback: self.execute_in_main_thread(callback) + def _on_version_check_timer(self): + # Check if is running from build and stop future validations if yes + if not is_running_from_build(): + self._version_check_timer.stop() + return + + self.validate_openpype_version() + + def validate_openpype_version(self): + if is_current_version_studio_latest(): + return + + if self._version_dialog is None: + self._version_dialog = VersionDialog() + result = self._version_dialog.exec_() + if result: + self.restart() + def execute_in_main_thread(self, callback, *args, **kwargs): if isinstance(callback, WrappedCallbackItem): item = callback @@ -123,6 +180,12 @@ class TrayManager: self.main_thread_timer = main_thread_timer + version_check_timer = QtCore.QTimer() + version_check_timer.setInterval(self._version_check_interval) + version_check_timer.timeout.connect(self._on_version_check_timer) + version_check_timer.start() + self._version_check_timer = version_check_timer + # For storing missing settings dialog self._settings_validation_dialog = None @@ -207,7 +270,7 @@ class TrayManager: self.tray_widget.menu.addAction(version_action) self.tray_widget.menu.addSeparator() - def restart(self): + def restart(self, reset_version=True): """Restart Tray tool. First creates new process with same argument and close current tray. @@ -221,7 +284,9 @@ class TrayManager: additional_args.pop(0) args.extend(additional_args) - kwargs = {} + kwargs = { + "env": dict(os.environ.items()) + } if platform.system().lower() == "windows": flags = ( subprocess.CREATE_NEW_PROCESS_GROUP @@ -229,6 +294,9 @@ class TrayManager: ) kwargs["creationflags"] = flags + if reset_version: + kwargs["env"].pop("OPENPYPE_VERSION", None) + subprocess.Popen(args, **kwargs) self.exit()