Skip to content

Commit

Permalink
Merge branch 'develop' into feature/AY-971_Use-custom-staging-dir-fun…
Browse files Browse the repository at this point in the history
…ctions
  • Loading branch information
robin-ynput committed Nov 25, 2024
2 parents 2d69115 + 333363f commit c459404
Show file tree
Hide file tree
Showing 35 changed files with 319 additions and 135 deletions.
15 changes: 15 additions & 0 deletions .github/workflows/assign_pr_to_project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: 🔸Auto assign pr
on:
pull_request:
types:
- opened

jobs:
auto-assign-pr:
uses: ynput/ops-repo-automation/.github/workflows/pr_to_project.yml@develop
with:
repo: "${{ github.repository }}"
project_id: 16
pull_request_number: ${{ github.event.pull_request.number }}
secrets:
token: ${{ secrets.YNPUT_BOT_TOKEN }}
18 changes: 18 additions & 0 deletions .github/workflows/validate_pr_labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: 🔎 Validate PR Labels
on:
pull_request:
types:
- opened
- edited
- labeled
- unlabeled

jobs:
validate-type-label:
uses: ynput/ops-repo-automation/.github/workflows/validate_pr_labels.yml@develop
with:
repo: "${{ github.repository }}"
pull_request_number: ${{ github.event.pull_request.number }}
query_prefix: "type: "
secrets:
token: ${{ secrets.YNPUT_BOT_TOKEN }}
4 changes: 2 additions & 2 deletions client/ayon_core/addon/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -535,8 +535,8 @@ def ensure_is_process_ready(
Implementation of this method is optional.
Note:
The logic can be similar to logic in tray, but tray does not require
to be logged in.
The logic can be similar to logic in tray, but tray does not
require to be logged in.
Args:
process_context (ProcessContext): Context of child
Expand Down
3 changes: 2 additions & 1 deletion client/ayon_core/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ def publish_report_viewer():
@main_cli.command()
@click.argument("output_path")
@click.option("--project", help="Define project context")
@click.option("--folder", help="Define folder in project (project must be set)")
@click.option(
"--folder", help="Define folder in project (project must be set)")
@click.option(
"--strict",
is_flag=True,
Expand Down
4 changes: 3 additions & 1 deletion client/ayon_core/lib/attribute_definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -616,7 +616,9 @@ def serialize(self):
return data

@staticmethod
def prepare_enum_items(items: "EnumItemsInputType") -> List["EnumItemDict"]:
def prepare_enum_items(
items: "EnumItemsInputType"
) -> List["EnumItemDict"]:
"""Convert items to unified structure.
Output is a list where each item is dictionary with 'value'
Expand Down
14 changes: 2 additions & 12 deletions client/ayon_core/lib/local_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -276,12 +276,7 @@ def delete_item(self, name):
@abstractmethod
def _delete_item(self, name):
# type: (str) -> None
"""Delete item from settings.
Note:
see :meth:`ayon_core.lib.user_settings.ARegistrySettings.delete_item`
"""
"""Delete item from settings."""
pass

def __delitem__(self, name):
Expand Down Expand Up @@ -433,12 +428,7 @@ def delete_item_from_section(self, section, name):
config.write(cfg)

def _delete_item(self, name):
"""Delete item from default section.
Note:
See :meth:`~ayon_core.lib.IniSettingsRegistry.delete_item_from_section`
"""
"""Delete item from default section."""
self.delete_item_from_section("MAIN", name)


Expand Down
14 changes: 9 additions & 5 deletions client/ayon_core/pipeline/create/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -1283,12 +1283,16 @@ def bulk_value_changes(self, sender=None):

@contextmanager
def bulk_pre_create_attr_defs_change(self, sender=None):
with self._bulk_context("pre_create_attrs_change", sender) as bulk_info:
with self._bulk_context(
"pre_create_attrs_change", sender
) as bulk_info:
yield bulk_info

@contextmanager
def bulk_create_attr_defs_change(self, sender=None):
with self._bulk_context("create_attrs_change", sender) as bulk_info:
with self._bulk_context(
"create_attrs_change", sender
) as bulk_info:
yield bulk_info

@contextmanager
Expand Down Expand Up @@ -1946,9 +1950,9 @@ def remove_instances(self, instances, sender=None):
creator are just removed from context.
Args:
instances (List[CreatedInstance]): Instances that should be removed.
Remove logic is done using creator, which may require to
do other cleanup than just remove instance from context.
instances (List[CreatedInstance]): Instances that should be
removed. Remove logic is done using creator, which may require
to do other cleanup than just remove instance from context.
sender (Optional[str]): Sender of the event.
"""
Expand Down
6 changes: 5 additions & 1 deletion client/ayon_core/pipeline/create/product_name.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import ayon_api
from ayon_core.lib import StringTemplate, filter_profiles, prepare_template_data
from ayon_core.lib import (
StringTemplate,
filter_profiles,
prepare_template_data,
)
from ayon_core.settings import get_project_settings

from .constants import DEFAULT_PRODUCT_TEMPLATE
Expand Down
13 changes: 10 additions & 3 deletions client/ayon_core/pipeline/editorial.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,9 @@ def remap_range_on_file_sequence(otio_clip, in_out_range):
source_range = otio_clip.source_range
available_range_rate = available_range.start_time.rate
media_in = available_range.start_time.value
available_range_start_frame = (
available_range.start_time.to_frames()
)

# Temporary.
# Some AYON custom OTIO exporter were implemented with relative
Expand All @@ -230,7 +233,7 @@ def remap_range_on_file_sequence(otio_clip, in_out_range):
# while we are updating those.
if (
is_clip_from_media_sequence(otio_clip)
and otio_clip.available_range().start_time.to_frames() == media_ref.start_frame
and available_range_start_frame == media_ref.start_frame
and source_range.start_time.to_frames() < media_ref.start_frame
):
media_in = 0
Expand Down Expand Up @@ -303,8 +306,12 @@ def get_media_range_with_retimes(otio_clip, handle_start, handle_end):
rounded_av_rate = round(available_range_rate, 2)
rounded_src_rate = round(source_range.start_time.rate, 2)
if rounded_av_rate != rounded_src_rate:
conformed_src_in = source_range.start_time.rescaled_to(available_range_rate)
conformed_src_duration = source_range.duration.rescaled_to(available_range_rate)
conformed_src_in = source_range.start_time.rescaled_to(
available_range_rate
)
conformed_src_duration = source_range.duration.rescaled_to(
available_range_rate
)
conformed_source_range = otio.opentime.TimeRange(
start_time=conformed_src_in,
duration=conformed_src_duration
Expand Down
6 changes: 3 additions & 3 deletions client/ayon_core/pipeline/entity_uri.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ def parse_ayon_entity_uri(uri: str) -> Optional[dict]:
Example:
>>> parse_ayon_entity_uri(
>>> "ayon://test/char/villain?product=modelMain&version=2&representation=usd" # noqa: E501
>>> "ayon://test/char/villain?product=modelMain&version=2&representation=usd"
>>> )
{'project': 'test', 'folderPath': '/char/villain',
'product': 'modelMain', 'version': 1,
'representation': 'usd'}
>>> parse_ayon_entity_uri(
>>> "ayon+entity://project/folder?product=renderMain&version=3&representation=exr" # noqa: E501
>>> "ayon+entity://project/folder?product=renderMain&version=3&representation=exr"
>>> )
{'project': 'project', 'folderPath': '/folder',
'product': 'renderMain', 'version': 3,
Expand All @@ -34,7 +34,7 @@ def parse_ayon_entity_uri(uri: str) -> Optional[dict]:
dict[str, Union[str, int]]: The individual key with their values as
found in the ayon entity URI.
"""
""" # noqa: E501

if not (uri.startswith("ayon+entity://") or uri.startswith("ayon://")):
return {}
Expand Down
109 changes: 94 additions & 15 deletions client/ayon_core/pipeline/farm/pyblish_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@
import attr
import ayon_api
import clique
from ayon_core.lib import Logger
from ayon_core.pipeline import get_current_project_name, get_representation_path
from ayon_core.lib import Logger, collect_frames
from ayon_core.pipeline import (
get_current_project_name,
get_representation_path,
)
from ayon_core.pipeline.create import get_product_name
from ayon_core.pipeline.farm.patterning import match_aov_pattern
from ayon_core.pipeline.publish import KnownPublishError
Expand Down Expand Up @@ -295,11 +298,17 @@ def _add_review_families(families):
return families


def prepare_representations(skeleton_data, exp_files, anatomy, aov_filter,
skip_integration_repre_list,
do_not_add_review,
context,
color_managed_plugin):
def prepare_representations(
skeleton_data,
exp_files,
anatomy,
aov_filter,
skip_integration_repre_list,
do_not_add_review,
context,
color_managed_plugin,
frames_to_render=None
):
"""Create representations for file sequences.
This will return representations of expected files if they are not
Expand All @@ -315,6 +324,8 @@ def prepare_representations(skeleton_data, exp_files, anatomy, aov_filter,
skip_integration_repre_list (list): exclude specific extensions,
do_not_add_review (bool): explicitly skip review
color_managed_plugin (publish.ColormanagedPyblishPluginMixin)
frames_to_render (str): implicit or explicit range of frames to render
this value is sent to Deadline in JobInfo.Frames
Returns:
list of representations
Expand All @@ -325,6 +336,14 @@ def prepare_representations(skeleton_data, exp_files, anatomy, aov_filter,

log = Logger.get_logger("farm_publishing")

if frames_to_render is not None:
frames_to_render = _get_real_frames_to_render(frames_to_render)
else:
# Backwards compatibility for older logic
frame_start = int(skeleton_data.get("frameStartHandle"))
frame_end = int(skeleton_data.get("frameEndHandle"))
frames_to_render = list(range(frame_start, frame_end + 1))

# create representation for every collected sequence
for collection in collections:
ext = collection.tail.lstrip(".")
Expand Down Expand Up @@ -361,18 +380,21 @@ def prepare_representations(skeleton_data, exp_files, anatomy, aov_filter,
" This may cause issues on farm."
).format(staging))

frame_start = int(skeleton_data.get("frameStartHandle"))
frame_start = frames_to_render[0]
frame_end = frames_to_render[-1]
if skeleton_data.get("slate"):
frame_start -= 1

files = _get_real_files_to_rendered(collection, frames_to_render)

# explicitly disable review by user
preview = preview and not do_not_add_review
rep = {
"name": ext,
"ext": ext,
"files": [os.path.basename(f) for f in list(collection)],
"files": files,
"frameStart": frame_start,
"frameEnd": int(skeleton_data.get("frameEndHandle")),
"frameEnd": frame_end,
# If expectedFile are absolute, we need only filenames
"stagingDir": staging,
"fps": skeleton_data.get("fps"),
Expand Down Expand Up @@ -413,10 +435,13 @@ def prepare_representations(skeleton_data, exp_files, anatomy, aov_filter,
" This may cause issues on farm."
).format(staging))

files = _get_real_files_to_rendered(
[os.path.basename(remainder)], frames_to_render)

rep = {
"name": ext,
"ext": ext,
"files": os.path.basename(remainder),
"files": files[0],
"stagingDir": staging,
}

Expand Down Expand Up @@ -453,6 +478,53 @@ def prepare_representations(skeleton_data, exp_files, anatomy, aov_filter,
return representations


def _get_real_frames_to_render(frames):
"""Returns list of frames that should be rendered.
Artists could want to selectively render only particular frames
"""
frames_to_render = []
for frame in frames.split(","):
if "-" in frame:
splitted = frame.split("-")
frames_to_render.extend(
range(int(splitted[0]), int(splitted[1])+1))
else:
frames_to_render.append(int(frame))
frames_to_render.sort()
return frames_to_render


def _get_real_files_to_rendered(collection, frames_to_render):
"""Use expected files based on real frames_to_render.
Artists might explicitly set frames they want to render via Publisher UI.
This uses this value to filter out files
Args:
frames_to_render (list): of str '1001'
"""
files = [os.path.basename(f) for f in list(collection)]
file_name, extracted_frame = list(collect_frames(files).items())[0]

if not extracted_frame:
return files

found_frame_pattern_length = len(extracted_frame)
normalized_frames_to_render = {
str(frame_to_render).zfill(found_frame_pattern_length)
for frame_to_render in frames_to_render
}

return [
file_name
for file_name in files
if any(
frame in file_name
for frame in normalized_frames_to_render
)
]


def create_instances_for_aov(instance, skeleton, aov_filter,
skip_integration_repre_list,
do_not_add_review):
Expand Down Expand Up @@ -702,9 +774,14 @@ def _create_instances_for_aov(instance, skeleton, aov_filter, additional_data,

project_settings = instance.context.data.get("project_settings")

use_legacy_product_name = True
try:
use_legacy_product_name = project_settings["core"]["tools"]["creator"]["use_legacy_product_names_for_renders"] # noqa: E501
use_legacy_product_name = (
project_settings
["core"]
["tools"]
["creator"]
["use_legacy_product_names_for_renders"]
)
except KeyError:
warnings.warn(
("use_legacy_for_renders not found in project settings. "
Expand All @@ -720,7 +797,9 @@ def _create_instances_for_aov(instance, skeleton, aov_filter, additional_data,
dynamic_data=dynamic_data)

else:
product_name, group_name = get_product_name_and_group_from_template(
(
product_name, group_name
) = get_product_name_and_group_from_template(
task_entity=instance.data["taskEntity"],
project_name=instance.context.data["projectName"],
host_name=instance.context.data["hostName"],
Expand Down Expand Up @@ -863,7 +942,7 @@ def _collect_expected_files_for_aov(files):
# but we really expect only one collection.
# Nothing else make sense.
if len(cols) != 1:
raise ValueError("Only one image sequence type is expected.") # noqa: E501
raise ValueError("Only one image sequence type is expected.")
return list(cols[0])


Expand Down
Loading

0 comments on commit c459404

Please sign in to comment.