Merge branch 'develop' into enhancement/AY-5552_Publisher-attr-defs-per-instance

This commit is contained in:
Jakub Trllo 2024-10-01 15:10:54 +02:00
commit 7427a0719e
11 changed files with 109 additions and 80 deletions

12
.github/workflows/release_trigger.yml vendored Normal file
View file

@ -0,0 +1,12 @@
name: 🚀 Release Trigger
on:
workflow_dispatch:
jobs:
call-release-trigger:
uses: ynput/ops-repo-automation/.github/workflows/release_trigger.yml@main
secrets:
token: ${{ secrets.YNPUT_BOT_TOKEN }}
email: ${{ secrets.CI_EMAIL }}
user: ${{ secrets.CI_USER }}

View file

@ -19,7 +19,8 @@ class OCIOEnvHook(PreLaunchHook):
"nuke",
"hiero",
"resolve",
"openrv"
"openrv",
"cinema4d"
}
launch_types = set()

View file

@ -81,7 +81,10 @@ def collect_frames(files):
dict: {'/folder/product_v001.0001.png': '0001', ....}
"""
patterns = [clique.PATTERNS["frames"]]
# clique.PATTERNS["frames"] supports only `.1001.exr` not `_1001.exr` so
# we use a customized pattern.
pattern = "[_.](?P<index>(?P<padding>0*)\\d+)\\.\\D+\\d?$"
patterns = [pattern]
collections, remainder = clique.assemble(
files, minimum_items=1, patterns=patterns)

View file

@ -3,7 +3,6 @@ from .constants import (
AVALON_INSTANCE_ID,
AYON_CONTAINER_ID,
AYON_INSTANCE_ID,
HOST_WORKFILE_EXTENSIONS,
)
from .anatomy import Anatomy
@ -114,7 +113,6 @@ __all__ = (
"AVALON_INSTANCE_ID",
"AYON_CONTAINER_ID",
"AYON_INSTANCE_ID",
"HOST_WORKFILE_EXTENSIONS",
# --- Anatomy ---
"Anatomy",

View file

@ -4,20 +4,3 @@ AYON_INSTANCE_ID = "ayon.create.instance"
# Backwards compatibility
AVALON_CONTAINER_ID = "pyblish.avalon.container"
AVALON_INSTANCE_ID = "pyblish.avalon.instance"
# TODO get extensions from host implementations
HOST_WORKFILE_EXTENSIONS = {
"blender": [".blend"],
"celaction": [".scn"],
"tvpaint": [".tvpp"],
"fusion": [".comp"],
"harmony": [".zip"],
"houdini": [".hip", ".hiplc", ".hipnc"],
"maya": [".ma", ".mb"],
"nuke": [".nk"],
"hiero": [".hrox"],
"photoshop": [".psd", ".psb"],
"premiere": [".prproj"],
"resolve": [".drp"],
"aftereffects": [".aep"]
}

View file

@ -17,8 +17,7 @@ from ayon_core.pipeline.load import get_representation_path_with_anatomy
from ayon_core.pipeline.delivery import (
get_format_dict,
check_destination_path,
deliver_single_file,
deliver_sequence,
deliver_single_file
)
@ -231,51 +230,55 @@ class DeliveryOptionsDialog(QtWidgets.QDialog):
self.log
]
if repre.get("files"):
src_paths = []
for repre_file in repre["files"]:
src_path = self.anatomy.fill_root(repre_file["path"])
src_paths.append(src_path)
sources_and_frames = collect_frames(src_paths)
# TODO: This will currently incorrectly detect 'resources'
# that are published along with the publish, because those should
# not adhere to the template directly but are ingested in a
# customized way. For example, maya look textures or any publish
# that directly adds files into `instance.data["transfers"]`
src_paths = []
for repre_file in repre["files"]:
src_path = self.anatomy.fill_root(repre_file["path"])
src_paths.append(src_path)
sources_and_frames = collect_frames(src_paths)
frames = set(sources_and_frames.values())
frames.discard(None)
first_frame = None
if frames:
first_frame = min(frames)
frames = set(sources_and_frames.values())
frames.discard(None)
first_frame = None
if frames:
first_frame = min(frames)
for src_path, frame in sources_and_frames.items():
args[0] = src_path
# Renumber frames
if renumber_frame and frame is not None:
# Calculate offset between
# first frame and current frame
# - '0' for first frame
offset = frame_offset - int(first_frame)
# Add offset to new frame start
dst_frame = int(frame) + offset
if dst_frame < 0:
msg = "Renumber frame has a smaller number than original frame" # noqa
report_items[msg].append(src_path)
self.log.warning("{} <{}>".format(
msg, dst_frame))
continue
frame = dst_frame
for src_path, frame in sources_and_frames.items():
args[0] = src_path
# Renumber frames
if renumber_frame and frame is not None:
# Calculate offset between
# first frame and current frame
# - '0' for first frame
offset = frame_offset - int(first_frame)
# Add offset to new frame start
dst_frame = int(frame) + offset
if dst_frame < 0:
msg = "Renumber frame has a smaller number than original frame" # noqa
report_items[msg].append(src_path)
self.log.warning("{} <{}>".format(
msg, dst_frame))
continue
frame = dst_frame
if frame is not None:
if frame is not None:
if repre["context"].get("frame"):
anatomy_data["frame"] = frame
new_report_items, uploaded = deliver_single_file(*args)
report_items.update(new_report_items)
self._update_progress(uploaded)
else: # fallback for Pype2 and representations without files
frame = repre["context"].get("frame")
if frame:
repre["context"]["frame"] = len(str(frame)) * "#"
if not frame:
new_report_items, uploaded = deliver_single_file(*args)
else:
new_report_items, uploaded = deliver_sequence(*args)
elif repre["context"].get("udim"):
anatomy_data["udim"] = frame
else:
# Fallback
self.log.warning(
"Representation context has no frame or udim"
" data. Supplying sequence frame to '{frame}'"
" formatting data."
)
anatomy_data["frame"] = frame
new_report_items, uploaded = deliver_single_file(*args)
report_items.update(new_report_items)
self._update_progress(uploaded)

View file

@ -509,8 +509,11 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
if not is_sequence_representation:
files = [files]
if any(os.path.isabs(fname) for fname in files):
raise KnownPublishError("Given file names contain full paths")
for fname in files:
if os.path.isabs(fname):
raise KnownPublishError(
f"Representation file names contains full paths: {fname}"
)
if not is_sequence_representation:
return

View file

@ -9,7 +9,14 @@ from ayon_api import (
class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
"""Connecting version level dependency links"""
"""Connecting version level dependency links
Handles links:
- generative - what gets produced from workfile
- reference - what was loaded into workfile
It expects workfile instance is being published.
"""
order = pyblish.api.IntegratorOrder + 0.2
label = "Connect Dependency InputLinks AYON"
@ -47,6 +54,11 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
self.create_links_on_server(context, new_links_by_type)
def split_instances(self, context):
"""Separates published instances into workfile and other
Returns:
(tuple(pyblish.plugin.Instance), list(pyblish.plugin.Instance))
"""
workfile_instance = None
other_instances = []
@ -83,6 +95,15 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
def create_workfile_links(
self, workfile_instance, other_instances, new_links_by_type
):
"""Adds links (generative and reference) for workfile.
Args:
workfile_instance (pyblish.plugin.Instance): published workfile
other_instances (list[pyblish.plugin.Instance]): other published
instances
new_links_by_type (dict[str, list[str]]): dictionary collecting new
created links by its type
"""
if workfile_instance is None:
self.log.warn("No workfile in this publish session.")
return
@ -97,7 +118,7 @@ class IntegrateInputLinksAYON(pyblish.api.ContextPlugin):
instance.data["versionEntity"]["id"],
)
loaded_versions = workfile_instance.context.get("loadedVersions")
loaded_versions = workfile_instance.context.data.get("loadedVersions")
if not loaded_versions:
return

View file

@ -36,7 +36,8 @@ class ValidateCurrentSaveFile(pyblish.api.ContextPlugin):
label = "Validate File Saved"
order = pyblish.api.ValidatorOrder - 0.1
hosts = ["fusion", "houdini", "max", "maya", "nuke", "substancepainter"]
hosts = ["fusion", "houdini", "max", "maya", "nuke", "substancepainter",
"cinema4d"]
actions = [SaveByVersionUpAction, ShowWorkfilesAction]
def process(self, context):

View file

@ -1,6 +1,9 @@
import collections
from ayon_api import get_representations, get_versions_links
from ayon_api import (
get_representations,
get_versions_links,
)
from ayon_core.lib import Logger, NestedCacheItem
from ayon_core.addon import AddonsManager
@ -509,18 +512,19 @@ class SiteSyncModel:
"reference"
)
for link_repre_id in links:
try:
if not self._sitesync_addon.is_representation_on_site(
project_name,
link_repre_id,
site_name
):
print("Adding {} to linked representation: {}".format(
site_name, link_repre_id))
self._sitesync_addon.add_site(
project_name,
link_repre_id,
site_name,
force=False
force=True
)
except Exception:
# do not add/reset working site for references
log.debug("Site present", exc_info=True)
def _get_linked_representation_id(
self,
@ -575,7 +579,7 @@ class SiteSyncModel:
project_name,
versions_to_check,
link_types=link_types,
link_direction="out")
link_direction="in") # looking for 'in'puts for version
versions_to_check = set()
for links in versions_links.values():
@ -584,9 +588,6 @@ class SiteSyncModel:
if link["entityType"] != "version":
continue
entity_id = link["entityId"]
# Skip already found linked version ids
if entity_id in linked_version_ids:
continue
linked_version_ids.add(entity_id)
versions_to_check.add(entity_id)

View file

@ -439,10 +439,13 @@ class PublisherWindow(QtWidgets.QDialog):
def make_sure_is_visible(self):
if self._window_is_visible:
self.setWindowState(QtCore.Qt.WindowActive)
else:
self.show()
self.raise_()
self.activateWindow()
self.showNormal()
def showEvent(self, event):
self._window_is_visible = True
super().showEvent(event)