Merge pull request #1344 from ynput/bugfix/type-hint-annotation

Publish plugins: Fix dataclasses usage
This commit is contained in:
Jakub Trllo 2025-06-27 14:34:18 +02:00 committed by GitHub
commit f7bc23a487
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 143 additions and 49 deletions

View file

@ -1052,16 +1052,15 @@ def main_cli_publish(
log.info("Running publish ...") log.info("Running publish ...")
plugins = pyblish.api.discover() discover_result = publish_plugins_discover()
print("Using plugins:") publish_plugins = discover_result.plugins
for plugin in plugins: print("\n".join(discover_result.get_report(only_errors=False)))
print(plugin)
# Error exit as soon as any error occurs. # Error exit as soon as any error occurs.
error_format = ("Failed {plugin.__name__}: " error_format = ("Failed {plugin.__name__}: "
"{error} -- {error.traceback}") "{error} -- {error.traceback}")
for result in pyblish.util.publish_iter(): for result in pyblish.util.publish_iter(plugins=publish_plugins):
if result["error"]: if result["error"]:
log.error(error_format.format(**result)) log.error(error_format.format(**result))
# uninstall() # uninstall()

View file

@ -7,7 +7,6 @@ import shutil
import subprocess import subprocess
from abc import ABC, abstractmethod from abc import ABC, abstractmethod
from typing import Any, Optional from typing import Any, Optional
from dataclasses import dataclass, field
import tempfile import tempfile
import clique import clique
@ -37,37 +36,68 @@ from ayon_core.pipeline.publish import (
from ayon_core.pipeline.publish.lib import add_repre_files_for_cleanup from ayon_core.pipeline.publish.lib import add_repre_files_for_cleanup
@dataclass
class TempData: class TempData:
"""Temporary data used across extractor's process.""" """Temporary data used across extractor's process."""
fps: float def __init__(
frame_start: int self,
frame_end: int fps: float,
handle_start: int frame_start: int,
handle_end: int frame_end: int,
frame_start_handle: int handle_start: int,
frame_end_handle: int handle_end: int,
output_frame_start: int frame_start_handle: int,
output_frame_end: int frame_end_handle: int,
pixel_aspect: float output_frame_start: int,
resolution_width: int output_frame_end: int,
resolution_height: int pixel_aspect: float,
origin_repre: dict[str, Any] resolution_width: int,
input_is_sequence: bool resolution_height: int,
first_sequence_frame: int origin_repre: dict[str, Any],
input_allow_bg: bool input_is_sequence: bool,
with_audio: bool first_sequence_frame: int,
without_handles: bool input_allow_bg: bool,
handles_are_set: bool with_audio: bool,
input_ext: str without_handles: bool,
explicit_input_paths: list[str] handles_are_set: bool,
paths_to_remove: list[str] input_ext: str,
explicit_input_paths: list[str],
paths_to_remove: list[str],
# Set later # Set later
full_output_path: str = "" full_output_path: str = "",
filled_files: dict[int, str] = field(default_factory=dict) filled_files: dict[int, str] = None,
output_ext_is_image: bool = True output_ext_is_image: bool = True,
output_is_sequence: 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: def frame_to_timecode(frame: int, fps: float) -> str:

View file

@ -1,11 +1,9 @@
"""Integrate representations with traits.""" """Integrate representations with traits."""
from __future__ import annotations from __future__ import annotations
import contextlib import contextlib
import copy import copy
import hashlib import hashlib
import json import json
from dataclasses import dataclass
from pathlib import Path from pathlib import Path
from typing import TYPE_CHECKING, Any from typing import TYPE_CHECKING, Any
@ -64,7 +62,6 @@ if TYPE_CHECKING:
) )
@dataclass(frozen=True)
class TransferItem: class TransferItem:
"""Represents a single transfer item. """Represents a single transfer item.
@ -91,6 +88,25 @@ class TransferItem:
representation: Representation representation: Representation
related_trait: FileLocation 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 @staticmethod
def get_size(file_path: Path) -> int: def get_size(file_path: Path) -> int:
"""Get the size of the file. """Get the size of the file.
@ -120,7 +136,6 @@ class TransferItem:
).hexdigest() ).hexdigest()
@dataclass
class TemplateItem: class TemplateItem:
"""Represents single template item. """Represents single template item.
@ -135,10 +150,28 @@ class TemplateItem:
anatomy: Anatomy anatomy: Anatomy
template: str template: str
template_data: dict[str, Any] 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: class RepresentationEntity:
"""Representation entity data.""" """Representation entity data."""
id: str id: str
@ -150,6 +183,37 @@ class RepresentationEntity:
tags: list[str] tags: list[str]
status: 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]: def get_instance_families(instance: pyblish.api.Instance) -> list[str]:
"""Get all families of the instance. """Get all families of the instance.
@ -177,7 +241,7 @@ def get_instance_families(instance: pyblish.api.Instance) -> list[str]:
def get_changed_attributes( 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. """Prepare changes for entity update.
Todo: Todo:
@ -246,7 +310,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin):
label = "Integrate Traits of an Asset" label = "Integrate Traits of an Asset"
order = pyblish.api.IntegratorOrder order = pyblish.api.IntegratorOrder
log: logging.Logger log: "logging.Logger"
def process(self, instance: pyblish.api.Instance) -> None: def process(self, instance: pyblish.api.Instance) -> None:
"""Integrate representations with traits. """Integrate representations with traits.
@ -471,7 +535,8 @@ class IntegrateTraits(pyblish.api.InstancePlugin):
@staticmethod @staticmethod
def filter_lifecycle( def filter_lifecycle(
representations: list[Representation]) -> list[Representation]: representations: list[Representation]
) -> list[Representation]:
"""Filter representations based on LifeCycle traits. """Filter representations based on LifeCycle traits.
Args: Args:
@ -535,7 +600,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin):
return path_template_obj.template.replace("\\", "/") return path_template_obj.template.replace("\\", "/")
def get_publish_template_object( 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. """Return anatomy template object to use for integration.
Note: What is the actual type of the object? Note: What is the actual type of the object?
@ -756,7 +821,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin):
return version_data 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. r"""Get rootless variant of the path.
Returns, if possible, a path without an absolute portion from the root 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) udim: UDIM = representation.get_trait(UDIM)
path_template_object: AnatomyStringTemplate = ( path_template_object: "AnatomyStringTemplate" = (
template_item.template_object["path"] template_item.template_object["path"]
) )
for file_loc in representation.get_trait( for file_loc in representation.get_trait(
@ -1070,7 +1135,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin):
template_item (TemplateItem): Template item. template_item (TemplateItem): Template item.
""" """
path_template_object: AnatomyStringTemplate = ( path_template_object: "AnatomyStringTemplate" = (
template_item.template_object["path"] template_item.template_object["path"]
) )
template_item.template_data["ext"] = ( template_item.template_data["ext"] = (
@ -1152,7 +1217,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin):
) )
def _prepare_file_info( 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). """Prepare information for one file (asset or resource).
Arguments: Arguments:
@ -1183,7 +1248,7 @@ class IntegrateTraits(pyblish.api.InstancePlugin):
self, self,
transfer_items: list[TransferItem], transfer_items: list[TransferItem],
representation: Representation, representation: Representation,
anatomy: Anatomy, anatomy: "Anatomy",
) -> list[dict[str, str]]: ) -> list[dict[str, str]]:
"""Get legacy files for a given representation. """Get legacy files for a given representation.