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 ...")
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()

View file

@ -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
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:

View file

@ -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.