diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 2cef7d13b0..eff53116a2 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -35,6 +35,7 @@ body: label: Version description: What version are you running? Look to AYON Tray options: + - 1.4.0 - 1.3.2 - 1.3.1 - 1.3.0 diff --git a/client/ayon_core/pipeline/publish/lib.py b/client/ayon_core/pipeline/publish/lib.py index 5d51b75b0c..49143c4426 100644 --- a/client/ayon_core/pipeline/publish/lib.py +++ b/client/ayon_core/pipeline/publish/lib.py @@ -1046,16 +1046,15 @@ def main_cli_publish( log.info("Running publish ...") - plugins = pyblish.api.discover() - print("Using plugins:") - for plugin in plugins: - print(plugin) + discover_result = publish_plugins_discover() + publish_plugins = discover_result.plugins + print("\n".join(discover_result.get_report(only_errors=False))) # Error exit as soon as any error occurs. error_format = ("Failed {plugin.__name__}: " "{error} -- {error.traceback}") - for result in pyblish.util.publish_iter(): + for result in pyblish.util.publish_iter(plugins=publish_plugins): if result["error"]: log.error(error_format.format(**result)) # uninstall() diff --git a/client/ayon_core/plugins/publish/extract_burnin.py b/client/ayon_core/plugins/publish/extract_burnin.py index 3f7c2f4cba..fa7fd4e504 100644 --- a/client/ayon_core/plugins/publish/extract_burnin.py +++ b/client/ayon_core/plugins/publish/extract_burnin.py @@ -757,6 +757,15 @@ class ExtractBurnin(publish.Extractor): ) }) + # burnin source resolution which might be different than on review + repre_source_resolution_width = repre.get("source_resolution_width") + repre_source_resolution_height = repre.get("source_resolution_height") + if repre_source_resolution_width and repre_source_resolution_height: + burnin_data.update({ + "source_resolution_width": repre_source_resolution_width, + "source_resolution_height": repre_source_resolution_height + }) + def filter_burnins_defs(self, profile, instance): """Filter outputs by their values from settings. diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index 89bc56c670..a5f541225c 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -7,7 +7,6 @@ import shutil import subprocess from abc import ABC, abstractmethod from typing import Any, Optional -from dataclasses import dataclass, field import tempfile import clique @@ -37,37 +36,68 @@ from ayon_core.pipeline.publish import ( from ayon_core.pipeline.publish.lib import add_repre_files_for_cleanup -@dataclass class TempData: """Temporary data used across extractor's process.""" - fps: float - frame_start: int - frame_end: int - handle_start: int - handle_end: int - frame_start_handle: int - frame_end_handle: int - output_frame_start: int - output_frame_end: int - pixel_aspect: float - resolution_width: int - resolution_height: int - origin_repre: dict[str, Any] - input_is_sequence: bool - first_sequence_frame: int - input_allow_bg: bool - with_audio: bool - without_handles: bool - handles_are_set: bool - input_ext: str - explicit_input_paths: list[str] - paths_to_remove: list[str] + def __init__( + self, + fps: float, + frame_start: int, + frame_end: int, + handle_start: int, + handle_end: int, + frame_start_handle: int, + frame_end_handle: int, + output_frame_start: int, + output_frame_end: int, + pixel_aspect: float, + resolution_width: int, + resolution_height: int, + origin_repre: dict[str, Any], + input_is_sequence: bool, + first_sequence_frame: int, + input_allow_bg: bool, + with_audio: bool, + without_handles: bool, + handles_are_set: bool, + input_ext: str, + explicit_input_paths: list[str], + paths_to_remove: list[str], - # Set later - full_output_path: str = "" - filled_files: dict[int, str] = field(default_factory=dict) - output_ext_is_image: bool = True - output_is_sequence: bool = True + # Set later + full_output_path: str = "", + filled_files: dict[int, str] = None, + output_ext_is_image: bool = True, + output_is_sequence: bool = True, + ): + if filled_files is None: + filled_files = {} + self.fps = fps + self.frame_start = frame_start + self.frame_end = frame_end + self.handle_start = handle_start + self.handle_end = handle_end + self.frame_start_handle = frame_start_handle + self.frame_end_handle = frame_end_handle + self.output_frame_start = output_frame_start + self.output_frame_end = output_frame_end + self.pixel_aspect = pixel_aspect + self.resolution_width = resolution_width + self.resolution_height = resolution_height + self.origin_repre = origin_repre + self.input_is_sequence = input_is_sequence + self.first_sequence_frame = first_sequence_frame + self.input_allow_bg = input_allow_bg + self.with_audio = with_audio + self.without_handles = without_handles + self.handles_are_set = handles_are_set + self.input_ext = input_ext + self.explicit_input_paths = explicit_input_paths + self.paths_to_remove = paths_to_remove + + self.full_output_path = full_output_path + self.filled_files = filled_files + self.output_ext_is_image = output_ext_is_image + self.output_is_sequence = output_is_sequence def frame_to_timecode(frame: int, fps: float) -> str: @@ -1598,6 +1628,12 @@ class ExtractReview(pyblish.api.InstancePlugin): "FFprobe couldn't read resolution from input file: \"{}\"" ).format(full_input_path_single_file)) + # collect source values to be potentially used in burnins later + if "source_resolution_width" not in new_repre: + new_repre["source_resolution_width"] = input_width + if "source_resolution_height" not in new_repre: + new_repre["source_resolution_height"] = input_height + # NOTE Setting only one of `width` or `height` is not allowed # - settings value can't have None but has value of 0 output_width = output_def["width"] or output_width or None diff --git a/client/ayon_core/plugins/publish/integrate_traits.py b/client/ayon_core/plugins/publish/integrate_traits.py index 38c9ecdeb4..45f32be4a0 100644 --- a/client/ayon_core/plugins/publish/integrate_traits.py +++ b/client/ayon_core/plugins/publish/integrate_traits.py @@ -1,11 +1,9 @@ """Integrate representations with traits.""" from __future__ import annotations - import contextlib import copy import hashlib import json -from dataclasses import dataclass from pathlib import Path from typing import TYPE_CHECKING, Any @@ -64,7 +62,6 @@ if TYPE_CHECKING: ) -@dataclass(frozen=True) class TransferItem: """Represents a single transfer item. @@ -91,6 +88,25 @@ class TransferItem: representation: Representation related_trait: FileLocation + def __init__(self, + source: Path, + destination: Path, + size: int, + checksum: str, + template: str, + template_data: dict[str, Any], + representation: Representation, + related_trait: FileLocation): + + self.source = source + self.destination = destination + self.size = size + self.checksum = checksum + self.template = template + self.template_data = template_data + self.representation = representation + self.related_trait = related_trait + @staticmethod def get_size(file_path: Path) -> int: """Get the size of the file. @@ -120,7 +136,6 @@ class TransferItem: ).hexdigest() -@dataclass class TemplateItem: """Represents single template item. @@ -135,10 +150,28 @@ class TemplateItem: anatomy: Anatomy template: str template_data: dict[str, Any] - template_object: AnatomyTemplateItem + template_object: "AnatomyTemplateItem" + + def __init__(self, + anatomy: "Anatomy", + template: str, + template_data: dict[str, Any], + template_object: "AnatomyTemplateItem"): + """Initialize TemplateItem. + + Args: + anatomy (Anatomy): Anatomy object. + template (str): Template path. + template_data (dict[str, Any]): Template data. + template_object (AnatomyTemplateItem): Template object. + + """ + self.anatomy = anatomy + self.template = template + self.template_data = template_data + self.template_object = template_object -@dataclass class RepresentationEntity: """Representation entity data.""" id: str @@ -150,6 +183,37 @@ class RepresentationEntity: tags: list[str] status: str + def __init__(self, + id: str, + versionId: str, # noqa: N815 + name: str, + files: dict[str, Any], + attrib: dict[str, Any], + data: str, + tags: list[str], + status: str): + """Initialize RepresentationEntity. + + Args: + id (str): Entity ID. + versionId (str): Version ID. + name (str): Representation name. + files (dict[str, Any]): Files in the representation. + attrib (dict[str, Any]): Attributes of the representation. + data (str): Data of the representation. + tags (list[str]): Tags of the representation. + status (str): Status of the representation. + + """ + self.id = id + self.versionId = versionId + self.name = name + self.files = files + self.attrib = attrib + self.data = data + self.tags = tags + self.status = status + def get_instance_families(instance: pyblish.api.Instance) -> list[str]: """Get all families of the instance. @@ -177,7 +241,7 @@ def get_instance_families(instance: pyblish.api.Instance) -> list[str]: def get_changed_attributes( - old_entity: dict, new_entity: dict) -> (dict[str, Any]): + old_entity: dict, new_entity: dict) -> dict[str, Any]: """Prepare changes for entity update. Todo: @@ -246,7 +310,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin): label = "Integrate Traits of an Asset" order = pyblish.api.IntegratorOrder - log: logging.Logger + log: "logging.Logger" def process(self, instance: pyblish.api.Instance) -> None: """Integrate representations with traits. @@ -471,7 +535,8 @@ class IntegrateTraits(pyblish.api.InstancePlugin): @staticmethod def filter_lifecycle( - representations: list[Representation]) -> list[Representation]: + representations: list[Representation] + ) -> list[Representation]: """Filter representations based on LifeCycle traits. Args: @@ -535,7 +600,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin): return path_template_obj.template.replace("\\", "/") def get_publish_template_object( - self, instance: pyblish.api.Instance) -> AnatomyTemplateItem: + self, instance: pyblish.api.Instance) -> "AnatomyTemplateItem": """Return anatomy template object to use for integration. Note: What is the actual type of the object? @@ -756,7 +821,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin): return version_data - def get_rootless_path(self, anatomy: Anatomy, path: str) -> str: + def get_rootless_path(self, anatomy: "Anatomy", path: str) -> str: r"""Get rootless variant of the path. Returns, if possible, a path without an absolute portion from the root @@ -1015,7 +1080,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin): """ udim: UDIM = representation.get_trait(UDIM) - path_template_object: AnatomyStringTemplate = ( + path_template_object: "AnatomyStringTemplate" = ( template_item.template_object["path"] ) for file_loc in representation.get_trait( @@ -1070,7 +1135,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin): template_item (TemplateItem): Template item. """ - path_template_object: AnatomyStringTemplate = ( + path_template_object: "AnatomyStringTemplate" = ( template_item.template_object["path"] ) template_item.template_data["ext"] = ( @@ -1152,7 +1217,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin): ) def _prepare_file_info( - self, path: Path, anatomy: Anatomy) -> dict[str, Any]: + self, path: Path, anatomy: "Anatomy") -> dict[str, Any]: """Prepare information for one file (asset or resource). Arguments: @@ -1183,7 +1248,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin): self, transfer_items: list[TransferItem], representation: Representation, - anatomy: Anatomy, + anatomy: "Anatomy", ) -> list[dict[str, str]]: """Get legacy files for a given representation. diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index 11fc31799b..df92396802 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.3.2+dev" +__version__ = "1.4.0+dev" diff --git a/package.py b/package.py index 908d34ffa8..efed91b6cf 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.3.2+dev" +version = "1.4.0+dev" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index f4a452a2b9..91579f04fb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.3.2+dev" +version = "1.4.0+dev" description = "" authors = ["Ynput Team "] readme = "README.md"