mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 12:54:40 +01:00
Merge branch 'develop' into enhancement/publish_job_do_not_register_publish_plugins_twice
This commit is contained in:
commit
281500b3ae
8 changed files with 162 additions and 52 deletions
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring AYON addon 'core' version."""
|
||||
__version__ = "1.3.2+dev"
|
||||
__version__ = "1.4.0+dev"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
name = "core"
|
||||
title = "Core"
|
||||
version = "1.3.2+dev"
|
||||
version = "1.4.0+dev"
|
||||
|
||||
client_dir = "ayon_core"
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
[tool.poetry]
|
||||
name = "ayon-core"
|
||||
version = "1.3.2+dev"
|
||||
version = "1.4.0+dev"
|
||||
description = ""
|
||||
authors = ["Ynput Team <team@ynput.io>"]
|
||||
readme = "README.md"
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue