diff --git a/openpype/tools/ayon_push_to_project/control.py b/openpype/tools/ayon_push_to_project/control.py index 4fc011da09..0a19136701 100644 --- a/openpype/tools/ayon_push_to_project/control.py +++ b/openpype/tools/ayon_push_to_project/control.py @@ -14,12 +14,8 @@ from openpype.tools.ayon_utils.models import ProjectsModel, HierarchyModel from .models import ( PushToProjectSelectionModel, - UserPublishValuesModel, - - ProjectPushItem, - ProjectPushItemProcess, - ProjectPushItemStatus, + IntegrateModel, ) @@ -29,6 +25,7 @@ class PushToContextController: self._projects_model = ProjectsModel(self) self._hierarchy_model = HierarchyModel(self) + self._integrate_model = IntegrateModel(self) self._selection_model = PushToProjectSelectionModel(self) self._user_values = UserPublishValuesModel(self) @@ -42,7 +39,7 @@ class PushToContextController: self._submission_enabled = False self._process_thread = None - self._process_item = None + self._process_item_id = None self.set_source(project_name, version_id) @@ -58,6 +55,13 @@ class PushToContextController: self._event_system.add_callback(topic, callback) def set_source(self, project_name, version_id): + """Set source project and version. + + Args: + project_name (Union[str, None]): Source project name. + version_id (Union[str, None]): Source version id. + """ + if ( project_name == self._src_project_name and version_id == self._src_version_id @@ -101,6 +105,12 @@ class PushToContextController: ) def get_source_label(self): + """Get source label. + + Returns: + str: Label describing source project and version as path. + """ + if self._src_label is None: self._src_label = self._prepare_source_label() return self._src_label @@ -142,6 +152,9 @@ class PushToContextController: def set_selected_task(self, task_id, task_name): self._selection_model.set_selected_task(task_id, task_name) + def get_process_item_status(self, item_id): + return self._integrate_model.get_item_status(item_id) + # Processing methods def submit(self, wait=True): if not self._submission_enabled: @@ -150,7 +163,7 @@ class PushToContextController: if self._process_thread is not None: return - item = ProjectPushItem( + item_id = self._integrate_model.create_process_item( self._src_project_name, self._src_version_id, self._selection_model.get_selected_project_name(), @@ -162,19 +175,17 @@ class PushToContextController: dst_version=1 ) - status_item = ProjectPushItemStatus(event_system=self._event_system) - process_item = ProjectPushItemProcess(item, status_item) - self._process_item = process_item + self._process_item_id = item_id self._emit_event("submit.started") if wait: self._submit_callback() - self._process_item = None - return process_item + self._process_item_id = None + return item_id thread = threading.Thread(target=self._submit_callback) self._process_thread = thread thread.start() - return process_item + return item_id def wait_for_process_thread(self): if self._process_thread is None: @@ -316,13 +327,13 @@ class PushToContextController: ) def _submit_callback(self): - process_item = self._process_item - if process_item is None: + process_item_id = self._process_item_id + if process_item_id is None: return - process_item.process() + self._integrate_model.integrate_item(process_item_id) self._emit_event("submit.finished", {}) - if process_item is self._process_item: - self._process_item = None + if process_item_id == self._process_item_id: + self._process_item_id = None def _emit_event(self, topic, data=None): if data is None: diff --git a/openpype/tools/ayon_push_to_project/models/__init__.py b/openpype/tools/ayon_push_to_project/models/__init__.py index e8c0fae02e..5f909437a7 100644 --- a/openpype/tools/ayon_push_to_project/models/__init__.py +++ b/openpype/tools/ayon_push_to_project/models/__init__.py @@ -4,6 +4,7 @@ from .integrate import ( ProjectPushItem, ProjectPushItemProcess, ProjectPushItemStatus, + IntegrateModel, ) @@ -15,4 +16,5 @@ __all__ = ( "ProjectPushItem", "ProjectPushItemProcess", "ProjectPushItemStatus", + "IntegrateModel", ) diff --git a/openpype/tools/ayon_push_to_project/models/integrate.py b/openpype/tools/ayon_push_to_project/models/integrate.py index a822339ccf..b3de69c79a 100644 --- a/openpype/tools/ayon_push_to_project/models/integrate.py +++ b/openpype/tools/ayon_push_to_project/models/integrate.py @@ -6,6 +6,7 @@ import itertools import datetime import sys import traceback +import uuid from bson.objectid import ObjectId @@ -98,38 +99,62 @@ class ProjectPushItem: src_project_name, src_version_id, dst_project_name, - dst_asset_id, + dst_folder_id, dst_task_name, variant, - comment=None, - new_asset_name=None, - dst_version=None + comment, + new_folder_name, + dst_version, + item_id=None, ): + if not item_id: + item_id = uuid.uuid4().hex self.src_project_name = src_project_name self.src_version_id = src_version_id self.dst_project_name = dst_project_name - self.dst_asset_id = dst_asset_id + self.dst_folder_id = dst_folder_id self.dst_task_name = dst_task_name self.dst_version = dst_version self.variant = variant - self.new_asset_name = new_asset_name + self.new_folder_name = new_folder_name self.comment = comment or "" - self._id = "|".join([ - src_project_name, - src_version_id, - dst_project_name, - str(dst_asset_id), - str(new_asset_name), - str(dst_task_name), - str(dst_version) - ]) + self.item_id = item_id + self._repr_value = None @property - def id(self): - return self._id + def _repr(self): + if not self._repr_value: + self._repr_value = "|".join([ + self.src_project_name, + self.src_version_id, + self.dst_project_name, + str(self.dst_folder_id), + str(self.new_folder_name), + str(self.dst_task_name), + str(self.dst_version) + ]) + return self._repr_value def __repr__(self): - return "<{} - {}>".format(self.__class__.__name__, self.id) + return "<{} - {}>".format(self.__class__.__name__, self._repr) + + def to_data(self): + return { + "src_project_name": self.src_project_name, + "src_version_id": self.src_version_id, + "dst_project_name": self.dst_project_name, + "dst_folder_id": self.dst_folder_id, + "dst_task_name": self.dst_task_name, + "dst_version": self.dst_version, + "variant": self.variant, + "comment": self.comment, + "new_folder_name": self.new_folder_name, + "item_id": self.item_id, + } + + @classmethod + def from_data(cls, data): + return cls(**data) class StatusMessage: @@ -149,49 +174,17 @@ class StatusMessage: class ProjectPushItemStatus: def __init__( self, + started=False, failed=False, finished=False, fail_reason=None, - formatted_traceback=None, - messages=None, - event_system=None + full_traceback=None ): - if messages is None: - messages = [] - self._failed = failed - self._finished = finished - self._fail_reason = fail_reason - self._traceback = formatted_traceback - self._messages = messages - self._event_system = event_system - - def emit_event(self, topic, data=None): - if self._event_system is None: - return - - self._event_system.emit(topic, data or {}, "push.status") - - def get_finished(self): - """Processing of push to project finished. - - Returns: - bool: Finished. - """ - - return self._finished - - def set_finished(self, finished=True): - """Mark status as finished. - - Args: - finished (bool): Processing finished (failed or not). - """ - - if finished != self._finished: - self._finished = finished - self.emit_event("push.finished.changed", {"finished": finished}) - - finished = property(get_finished, set_finished) + self.started = started + self.failed = failed + self.finished = finished + self.fail_reason = fail_reason + self.full_traceback = full_traceback def set_failed(self, fail_reason, exc_info=None): """Set status as failed. @@ -201,8 +194,8 @@ class ProjectPushItemStatus: is set to 'True' and reason is not set. Args: - failed (bool): Push to project failed. fail_reason (str): Reason why failed. + exc_info(tuple): Exception info. """ failed = True @@ -215,84 +208,22 @@ class ProjectPushItemStatus: if not fail_reason: fail_reason = "Failed without specified reason" - if ( - self._failed == failed - and self._traceback == full_traceback - and self._fail_reason == fail_reason - ): - return + self.failed = failed + self.fail_reason = fail_reason or None + self.full_traceback = full_traceback - self._failed = failed - self._fail_reason = fail_reason or None - self._traceback = full_traceback + def to_data(self): + return { + "started": self.started, + "failed": self.failed, + "finished": self.finished, + "fail_reason": self.fail_reason, + "full_traceback": self.full_traceback, + } - self.emit_event( - "push.failed.changed", - { - "failed": failed, - "reason": fail_reason, - "traceback": full_traceback - } - ) - - @property - def failed(self): - """Processing failed. - - Returns: - bool: Processing failed. - """ - - return self._failed - - @property - def fail_reason(self): - """Reason why push to process failed. - - Returns: - Union[str, None]: Reason why push failed or None. - """ - - return self._fail_reason - - @property - def traceback(self): - """Traceback of failed process. - - Traceback is available only if unhandled exception happened. - - Returns: - Union[str, None]: Formatted traceback. - """ - - return self._traceback - - # Loggin helpers - # TODO better logging - def add_message(self, message, level): - message_obj = StatusMessage(message, level) - self._messages.append(message_obj) - self.emit_event( - "push.message.added", - {"message": message, "level": level} - ) - print(message_obj) - return message_obj - - def debug(self, message): - return self.add_message(message, "debug") - - def info(self, message): - return self.add_message(message, "info") - - def warning(self, message): - return self.add_message(message, "warning") - - def error(self, message): - return self.add_message(message, "error") - - def critical(self, message): - return self.add_message(message, "critical") + @classmethod + def from_data(cls, data): + return cls(**data) class ProjectPushRepreItem: @@ -508,22 +439,21 @@ class ProjectPushRepreItem: class ProjectPushItemProcess: """ Args: + model (IntegrateModel): Model which is processing item. item (ProjectPushItem): Item which is being processed. - item_status (ProjectPushItemStatus): Object to store status. """ # TODO where to get host?!!! host_name = "republisher" - def __init__(self, item, item_status=None): + def __init__(self, model, item): + self._model = model self._item = item - self._src_project_doc = None self._src_asset_doc = None self._src_subset_doc = None self._src_version_doc = None self._src_repre_items = None - self._src_anatomy = None self._project_doc = None self._anatomy = None @@ -539,85 +469,98 @@ class ProjectPushItemProcess: self._project_settings = None self._template_name = None - if item_status is None: - item_status = ProjectPushItemStatus() - self._status = item_status + self._status = ProjectPushItemStatus() self._operations = OperationsSession() self._file_transaction = FileTransaction() - @property - def status(self): - return self._status + self._messages = [] @property - def src_project_doc(self): - return self._src_project_doc + def item_id(self): + return self._item.item_id @property - def src_anatomy(self): - return self._src_anatomy + def started(self): + return self._status.started - @property - def src_asset_doc(self): - return self._src_asset_doc + def get_status_data(self): + return self._status.to_data() - @property - def src_subset_doc(self): - return self._src_subset_doc + def integrate(self): + self._status.started = True + try: + self._log_info("Process started") + self._fill_source_variables() + self._log_info("Source entities were found") + self._fill_destination_project() + self._log_info("Destination project was found") + self._fill_or_create_destination_asset() + self._log_info("Destination asset was determined") + self._determine_family() + self._determine_publish_template_name() + self._determine_subset_name() + self._make_sure_subset_exists() + self._make_sure_version_exists() + self._log_info("Prerequirements were prepared") + self._integrate_representations() + self._log_info("Integration finished") - @property - def src_version_doc(self): - return self._src_version_doc + except PushToProjectError as exc: + if not self._status.failed: + self._status.set_failed(str(exc)) - @property - def src_repre_items(self): - return self._src_repre_items + except Exception as exc: + _exc, _value, _tb = sys.exc_info() + self._status.set_failed( + "Unhandled error happened: {}".format(str(exc)), + (_exc, _value, _tb) + ) - @property - def project_doc(self): - return self._project_doc + finally: + self._status.finished = True + self._emit_event( + "push.finished.changed", + { + "finished": True, + "item_id": self.item_id, + } + ) - @property - def anatomy(self): - return self._anatomy + def _emit_event(self, topic, data): + self._model.emit_event(topic, data) - @property - def project_settings(self): - return self._project_settings + # Loggin helpers + # TODO better logging + def _add_message(self, message, level): + message_obj = StatusMessage(message, level) + self._messages.append(message_obj) + self._emit_event( + "push.message.added", + { + "message": message, + "level": level, + "item_id": self.item_id, + } + ) + print(message_obj) + return message_obj - @property - def asset_doc(self): - return self._asset_doc + def _log_debug(self, message): + return self._add_message(message, "debug") - @property - def task_info(self): - return self._task_info + def _log_info(self, message): + return self._add_message(message, "info") - @property - def subset_doc(self): - return self._subset_doc + def _log_warning(self, message): + return self._add_message(message, "warning") - @property - def version_doc(self): - return self._version_doc + def _log_error(self, message): + return self._add_message(message, "error") - @property - def variant(self): - return self._item.variant + def _log_critical(self, message): + return self._add_message(message, "critical") - @property - def family(self): - return self._family - - @property - def subset_name(self): - return self._subset_name - - @property - def template_name(self): - return self._template_name - - def fill_source_variables(self): + def _fill_source_variables(self): src_project_name = self._item.src_project_name src_version_id = self._item.src_version_id @@ -626,9 +569,14 @@ class ProjectPushItemProcess: self._status.set_failed( f"Source project \"{src_project_name}\" was not found" ) + + self._emit_event( + "push.failed.changed", + {"item_id": self.item_id} + ) raise PushToProjectError(self._status.fail_reason) - self._status.debug(f"Project '{src_project_name}' found") + self._log_debug(f"Project '{src_project_name}' found") version_doc = get_version_by_id(src_project_name, src_version_id) if not version_doc: @@ -666,7 +614,7 @@ class ProjectPushItemProcess: ProjectPushRepreItem(repre_doc, anatomy.roots) for repre_doc in repre_docs ] - self._status.debug(( + self._log_debug(( f"Found {len(repre_items)} representations on" f" version {src_version_id} in project '{src_project_name}'" )) @@ -677,14 +625,12 @@ class ProjectPushItemProcess: ) raise PushToProjectError(self._status.fail_reason) - self._src_anatomy = anatomy - self._src_project_doc = project_doc self._src_asset_doc = asset_doc self._src_subset_doc = subset_doc self._src_version_doc = version_doc self._src_repre_items = repre_items - def fill_destination_project(self): + def _fill_destination_project(self): # --- Destination entities --- dst_project_name = self._item.dst_project_name # Validate project existence @@ -695,7 +641,7 @@ class ProjectPushItemProcess: ) raise PushToProjectError(self._status.fail_reason) - self._status.debug( + self._log_debug( f"Destination project '{dst_project_name}' found" ) self._project_doc = dst_project_doc @@ -739,7 +685,7 @@ class ProjectPushItemProcess: )) raise PushToProjectError(self._status.fail_reason) - self._status.debug(( + self._log_debug(( f"Found already existing asset with name \"{other_name}\"" f" which match requested name \"{asset_name}\"" )) @@ -780,18 +726,18 @@ class ProjectPushItemProcess: asset_doc["type"], asset_doc ) - self._status.info( + self._log_info( f"Creating new asset with name \"{asset_name}\"" ) self._created_asset_doc = asset_doc return asset_doc - def fill_or_create_destination_asset(self): + def _fill_or_create_destination_asset(self): dst_project_name = self._item.dst_project_name - dst_asset_id = self._item.dst_asset_id + dst_folder_id = self._item.dst_folder_id dst_task_name = self._item.dst_task_name - new_asset_name = self._item.new_asset_name - if not dst_asset_id and not new_asset_name: + new_folder_name = self._item.new_folder_name + if not dst_folder_id and not new_folder_name: self._status.set_failed( "Push item does not have defined destination asset" ) @@ -799,25 +745,25 @@ class ProjectPushItemProcess: # Get asset document parent_asset_doc = None - if dst_asset_id: + if dst_folder_id: parent_asset_doc = get_asset_by_id( - self._item.dst_project_name, self._item.dst_asset_id + self._item.dst_project_name, self._item.dst_folder_id ) if not parent_asset_doc: self._status.set_failed( - f"Could find asset with id \"{dst_asset_id}\"" + f"Could find asset with id \"{dst_folder_id}\"" f" in project \"{dst_project_name}\"" ) raise PushToProjectError(self._status.fail_reason) - if not new_asset_name: + if not new_folder_name: asset_doc = parent_asset_doc else: asset_doc = self._create_asset( - self.src_asset_doc, - self.project_doc, + self._src_asset_doc, + self._project_doc, parent_asset_doc, - new_asset_name + new_folder_name ) self._asset_doc = asset_doc if not dst_task_name: @@ -842,12 +788,13 @@ class ProjectPushItemProcess: task_info["name"] = dst_task_name # Fill rest of task information based on task type task_type = task_info["type"] - task_type_info = self.project_doc["config"]["tasks"].get(task_type, {}) + task_type_info = self._project_doc["config"]["tasks"].get( + task_type, {}) task_info.update(task_type_info) self._task_info = task_info - def determine_family(self): - subset_doc = self.src_subset_doc + def _determine_family(self): + subset_doc = self._src_subset_doc family = subset_doc["data"].get("family") families = subset_doc["data"].get("families") if not family and families: @@ -859,48 +806,48 @@ class ProjectPushItemProcess: ) raise PushToProjectError(self._status.fail_reason) - self._status.debug( + self._log_debug( f"Publishing family is '{family}' (Based on source subset)" ) self._family = family - def determine_publish_template_name(self): + def _determine_publish_template_name(self): template_name = get_publish_template_name( self._item.dst_project_name, self.host_name, - self.family, - self.task_info.get("name"), - self.task_info.get("type"), - project_settings=self.project_settings + self._family, + self._task_info.get("name"), + self._task_info.get("type"), + project_settings=self._project_settings ) - self._status.debug( + self._log_debug( f"Using template '{template_name}' for integration" ) self._template_name = template_name - def determine_subset_name(self): - family = self.family - asset_doc = self.asset_doc - task_info = self.task_info + def _determine_subset_name(self): + family = self._family + asset_doc = self._asset_doc + task_info = self._task_info subset_name = get_subset_name( family, - self.variant, + self._item.variant, task_info.get("name"), asset_doc, project_name=self._item.dst_project_name, host_name=self.host_name, - project_settings=self.project_settings + project_settings=self._project_settings ) - self._status.info( + self._log_info( f"Push will be integrating to subset with name '{subset_name}'" ) self._subset_name = subset_name - def make_sure_subset_exists(self): + def _make_sure_subset_exists(self): project_name = self._item.dst_project_name - asset_id = self.asset_doc["_id"] - subset_name = self.subset_name - family = self.family + asset_id = self._asset_doc["_id"] + subset_name = self._subset_name + family = self._family subset_doc = get_subset_by_name(project_name, subset_name, asset_id) if subset_doc: self._subset_doc = subset_doc @@ -915,13 +862,13 @@ class ProjectPushItemProcess: self._operations.create_entity(project_name, "subset", subset_doc) self._subset_doc = subset_doc - def make_sure_version_exists(self): + def _make_sure_version_exists(self): """Make sure version document exits in database.""" project_name = self._item.dst_project_name version = self._item.dst_version - src_version_doc = self.src_version_doc - subset_doc = self.subset_doc + src_version_doc = self._src_version_doc + subset_doc = self._subset_doc subset_id = subset_doc["_id"] src_data = src_version_doc["data"] families = subset_doc["data"].get("families") @@ -947,8 +894,8 @@ class ProjectPushItemProcess: version = get_versioning_start( project_name, self.host_name, - task_name=self.task_info["name"], - task_type=self.task_info["type"], + task_name=self._task_info["name"], + task_type=self._task_info["type"], family=families[0], subset=subset_doc["name"] ) @@ -982,16 +929,16 @@ class ProjectPushItemProcess: self._version_doc = version_doc - def integrate_representations(self): + def _integrate_representations(self): try: - self._integrate_representations() + self._real_integrate_representations() except Exception: self._operations.clear() self._file_transaction.rollback() raise - def _integrate_representations(self): - version_doc = self.version_doc + def _real_integrate_representations(self): + version_doc = self._version_doc version_id = version_doc["_id"] existing_repres = get_representations( self._item.dst_project_name, @@ -1001,17 +948,17 @@ class ProjectPushItemProcess: repre_doc["name"].lower(): repre_doc for repre_doc in existing_repres } - template_name = self.template_name - anatomy = self.anatomy + template_name = self._template_name + anatomy = self._anatomy formatting_data = get_template_data( - self.project_doc, - self.asset_doc, - self.task_info.get("name"), + self._project_doc, + self._asset_doc, + self._task_info.get("name"), self.host_name ) formatting_data.update({ - "subset": self.subset_name, - "family": self.family, + "subset": self._subset_name, + "family": self._family, "version": version_doc["name"] }) @@ -1021,19 +968,19 @@ class ProjectPushItemProcess: file_template = StringTemplate( anatomy.templates[template_name]["file"] ) - self._status.info("Preparing files to transfer") + self._log_info("Preparing files to transfer") processed_repre_items = self._prepare_file_transactions( anatomy, template_name, formatting_data, file_template ) self._file_transaction.process() - self._status.info("Preparing database changes") + self._log_info("Preparing database changes") self._prepare_database_operations( version_id, processed_repre_items, path_template, existing_repres_by_low_name ) - self._status.info("Finalization") + self._log_info("Finalization") self._operations.commit() self._file_transaction.finalize() @@ -1041,7 +988,7 @@ class ProjectPushItemProcess: self, anatomy, template_name, formatting_data, file_template ): processed_repre_items = [] - for repre_item in self.src_repre_items: + for repre_item in self._src_repre_items: repre_doc = repre_item.repre_doc repre_name = repre_doc["name"] repre_format_data = copy.deepcopy(formatting_data) @@ -1050,6 +997,9 @@ class ProjectPushItemProcess: ext = os.path.splitext(src_file.path)[-1] repre_format_data["ext"] = ext[1:] break + repre_output_name = repre_doc["context"].get("output") + if repre_output_name is not None: + repre_format_data["output"] = repre_output_name template_obj = anatomy.templates_obj[template_name]["folder"] folder_path = template_obj.format_strict(formatting_data) @@ -1177,34 +1127,86 @@ class ProjectPushItemProcess: {"type": "archived_representation"} ) - def process(self): - try: - self._status.info("Process started") - self.fill_source_variables() - self._status.info("Source entities were found") - self.fill_destination_project() - self._status.info("Destination project was found") - self.fill_or_create_destination_asset() - self._status.info("Destination asset was determined") - self.determine_family() - self.determine_publish_template_name() - self.determine_subset_name() - self.make_sure_subset_exists() - self.make_sure_version_exists() - self._status.info("Prerequirements were prepared") - self.integrate_representations() - self._status.info("Integration finished") - except PushToProjectError as exc: - if not self._status.failed: - self._status.set_failed(str(exc)) +class IntegrateModel: + def __init__(self, controller): + self._controller = controller + self._process_items = {} - except Exception as exc: - _exc, _value, _tb = sys.exc_info() - self._status.set_failed( - "Unhandled error happened: {}".format(str(exc)), - (_exc, _value, _tb) - ) + def reset(self): + self._process_items = {} - finally: - self._status.set_finished() + def emit_event(self, topic, data=None, source=None): + self._controller.emit_event(topic, data, source) + + def create_process_item( + self, + src_project_name, + src_version_id, + dst_project_name, + dst_folder_id, + dst_task_name, + variant, + comment, + new_folder_name, + dst_version, + ): + """Create new item for integration. + + Args: + src_project_name (str): Source project name. + src_version_id (str): Source version id. + dst_project_name (str): Destination project name. + dst_folder_id (str): Destination folder id. + dst_task_name (str): Destination task name. + variant (str): Variant name. + comment (Union[str, None]): Comment. + new_folder_name (Union[str, None]): New folder name. + dst_version (int): Destination version number. + + Returns: + str: Item id. The id can be used to trigger integration or get + status information. + """ + + item = ProjectPushItem( + src_project_name, + src_version_id, + dst_project_name, + dst_folder_id, + dst_task_name, + variant, + comment=comment, + new_folder_name=new_folder_name, + dst_version=dst_version + ) + process_item = ProjectPushItemProcess(self, item) + self._process_items[item.item_id] = process_item + return item.item_id + + def integrate_item(self, item_id): + """Start integration of item. + + Args: + item_id (str): Item id which should be integrated. + """ + + item = self._process_items.get(item_id) + if item is None or item.started: + return + item.integrate() + + def get_item_status(self, item_id): + """Status of an item. + + Args: + item_id (str): Item id for which status should be returned. + + Returns: + dict[str, Any]: Status data. + """ + + item = self._process_items.get(item_id) + if item is not None: + return item.get_status_data() + return None diff --git a/openpype/tools/ayon_push_to_project/ui/window.py b/openpype/tools/ayon_push_to_project/ui/window.py index 57c4c2619f..535c01c643 100644 --- a/openpype/tools/ayon_push_to_project/ui/window.py +++ b/openpype/tools/ayon_push_to_project/ui/window.py @@ -231,7 +231,7 @@ class PushToContextSelectWindow(QtWidgets.QWidget): self._main_thread_timer = main_thread_timer self._main_thread_timer_can_stop = True self._last_submit_message = None - self._process_item = None + self._process_item_id = None self._variant_is_valid = None self._folder_is_valid = None @@ -380,10 +380,10 @@ class PushToContextSelectWindow(QtWidgets.QWidget): self.close() def _on_select_click(self): - self._process_item = self._controller.submit(wait=False) + self._process_item_id = self._controller.submit(wait=False) def _on_try_again_click(self): - self._process_item = None + self._process_item_id = None self._last_submit_message = None self._overlay_close_btn.setVisible(False) @@ -395,9 +395,11 @@ class PushToContextSelectWindow(QtWidgets.QWidget): self._overlay_label.setText(self._last_submit_message) self._last_submit_message = None - process_status = self._process_item.status - push_failed = process_status.failed - fail_traceback = process_status.traceback + process_status = self._controller.get_process_item_status( + self._process_item_id + ) + push_failed = process_status["failed"] + fail_traceback = process_status["full_traceback"] if self._main_thread_timer_can_stop: self._main_thread_timer.stop() self._overlay_close_btn.setVisible(True) @@ -405,7 +407,7 @@ class PushToContextSelectWindow(QtWidgets.QWidget): self._overlay_try_btn.setVisible(True) if push_failed: - message = "Push Failed:\n{}".format(process_status.fail_reason) + message = "Push Failed:\n{}".format(process_status["fail_reason"]) if fail_traceback: message += "\n{}".format(fail_traceback) self._overlay_label.setText(message) @@ -415,7 +417,7 @@ class PushToContextSelectWindow(QtWidgets.QWidget): # Join thread in controller self._controller.wait_for_process_thread() # Reset process item to None - self._process_item = None + self._process_item_id = None def _on_controller_submit_start(self): self._main_thread_timer_can_stop = False