diff --git a/client/ayon_core/plugins/publish/collect_otio_subset_resources.py b/client/ayon_core/plugins/publish/collect_otio_subset_resources.py index c142036b83..2d8e91fe09 100644 --- a/client/ayon_core/plugins/publish/collect_otio_subset_resources.py +++ b/client/ayon_core/plugins/publish/collect_otio_subset_resources.py @@ -149,6 +149,7 @@ class CollectOtioSubsetResources( self.log.info( "frame_start-frame_end: {}-{}".format(frame_start, frame_end)) + review_repre = None if is_sequence: # file sequence way @@ -177,6 +178,11 @@ class CollectOtioSubsetResources( repre = self._create_representation( frame_start, frame_end, collection=collection) + if "review" in instance.data["families"]: + review_repre = self._create_representation( + frame_start, frame_end, collection=collection, + delete=True, review=True) + else: _trim = False dirname, filename = os.path.split(media_ref.target_url) @@ -191,17 +197,26 @@ class CollectOtioSubsetResources( repre = self._create_representation( frame_start, frame_end, file=filename, trim=_trim) + if "review" in instance.data["families"]: + review_repre = self._create_representation( + frame_start, frame_end, + file=filename, delete=True, review=True) + instance.data["originalDirname"] = self.staging_dir + # add representation to instance data if repre: colorspace = instance.data.get("colorspace") # add colorspace data to representation self.set_representation_colorspace( repre, instance.context, colorspace) - # add representation to instance data instance.data["representations"].append(repre) + # add review representation to instance data + if review_repre: + instance.data["representations"].append(review_repre) + self.log.debug(instance.data) def _create_representation(self, start, end, **kwargs): @@ -221,7 +236,8 @@ class CollectOtioSubsetResources( representation_data = { "frameStart": start, "frameEnd": end, - "stagingDir": self.staging_dir + "stagingDir": self.staging_dir, + "tags": [], } if kwargs.get("collection"): @@ -247,8 +263,10 @@ class CollectOtioSubsetResources( "frameEnd": end, }) - if kwargs.get("trim") is True: - representation_data["tags"] = ["trim"] + for tag_name in ("trim", "delete", "review"): + if kwargs.get(tag_name) is True: + representation_data["tags"].append(tag_name) + return representation_data def get_template_name(self, instance): diff --git a/client/ayon_core/tools/loader/control.py b/client/ayon_core/tools/loader/control.py index 2da77337fb..16cf7c31c7 100644 --- a/client/ayon_core/tools/loader/control.py +++ b/client/ayon_core/tools/loader/control.py @@ -372,17 +372,17 @@ class LoaderController(BackendLoaderController, FrontendLoaderController): repre_ids = set() for container in containers: - repre_id = container.get("representation") - # Ignore invalid representation ids. - # - invalid representation ids may be available if e.g. is - # opened scene from OpenPype whe 'ObjectId' was used instead - # of 'uuid'. - # NOTE: Server call would crash if there is any invalid id. - # That would cause crash we won't get any information. try: + repre_id = container.get("representation") + # Ignore invalid representation ids. + # - invalid representation ids may be available if e.g. is + # opened scene from OpenPype whe 'ObjectId' was used + # instead of 'uuid'. + # NOTE: Server call would crash if there is any invalid id. + # That would cause crash we won't get any information. uuid.UUID(repre_id) repre_ids.add(repre_id) - except ValueError: + except (ValueError, TypeError, AttributeError): pass product_ids = self._products_model.get_product_ids_by_repre_ids( diff --git a/client/ayon_core/tools/sceneinventory/models/containers.py b/client/ayon_core/tools/sceneinventory/models/containers.py index 9059485dff..f841f87c8e 100644 --- a/client/ayon_core/tools/sceneinventory/models/containers.py +++ b/client/ayon_core/tools/sceneinventory/models/containers.py @@ -4,6 +4,7 @@ import collections import ayon_api from ayon_api.graphql import GraphQlQuery +from ayon_core.lib import Logger from ayon_core.host import ILoadHost from ayon_core.tools.common_models.projects import StatusStates @@ -196,6 +197,7 @@ class ContainersModel: self._container_items_by_id = {} self._version_items_by_product_id = {} self._repre_info_by_id = {} + self._log = Logger.get_logger("ContainersModel") def reset(self): self._items_cache = None @@ -230,7 +232,7 @@ class ContainersModel: for repre_id in representation_ids: try: uuid.UUID(repre_id) - except ValueError: + except (ValueError, TypeError, AttributeError): output[repre_id] = RepresentationInfo.new_invalid() continue repre_info = self._repre_info_by_id.get(repre_id) @@ -348,12 +350,14 @@ class ContainersModel: return host = self._controller.get_host() - if isinstance(host, ILoadHost): - containers = list(host.get_containers()) - elif hasattr(host, "ls"): - containers = list(host.ls()) - else: - containers = [] + containers = [] + try: + if isinstance(host, ILoadHost): + containers = list(host.get_containers()) + elif hasattr(host, "ls"): + containers = list(host.ls()) + except Exception: + self._log.error("Failed to get containers", exc_info=True) container_items = [] containers_by_id = {} @@ -361,6 +365,9 @@ class ContainersModel: invalid_ids_mapping = {} current_project_name = self._controller.get_current_project_name() for container in containers: + if not container: + continue + try: item = ContainerItem.from_container_data( current_project_name, container) @@ -368,16 +375,20 @@ class ContainersModel: try: uuid.UUID(repre_id) except (ValueError, TypeError, AttributeError): + self._log.warning( + "Container contains invalid representation id." + f"\n{container}" + ) # Fake not existing representation id so container # is shown in UI but as invalid item.representation_id = invalid_ids_mapping.setdefault( repre_id, uuid.uuid4().hex ) - except Exception as e: + except Exception: # skip item if required data are missing - self._controller.log_error( - f"Failed to create item: {e}" + self._log.warning( + "Failed to create container item", exc_info=True ) continue