mirror of
https://github.com/ynput/ayon-core.git
synced 2025-12-24 21:04:40 +01:00
Merge branch 'develop' into enhancement/adding-aces-1.3-ocio-support
This commit is contained in:
commit
c67958d9dd
55 changed files with 316 additions and 347 deletions
11
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
11
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -35,6 +35,17 @@ body:
|
|||
label: Version
|
||||
description: What version are you running? Look to AYON Tray
|
||||
options:
|
||||
- 1.2.0
|
||||
- 1.1.9
|
||||
- 1.1.8
|
||||
- 1.1.7
|
||||
- 1.1.6
|
||||
- 1.1.5
|
||||
- 1.1.4
|
||||
- 1.1.3
|
||||
- 1.1.2
|
||||
- 1.1.1
|
||||
- 1.1.0
|
||||
- 1.0.14
|
||||
- 1.0.13
|
||||
- 1.0.12
|
||||
|
|
|
|||
7
.github/workflows/update_bug_report.yml
vendored
7
.github/workflows/update_bug_report.yml
vendored
|
|
@ -1,10 +1,11 @@
|
|||
name: 🐞 Update Bug Report
|
||||
|
||||
on:
|
||||
workflow_run:
|
||||
workflows: ["🚀 Release Trigger"]
|
||||
types:
|
||||
- completed
|
||||
workflow_dispatch:
|
||||
release:
|
||||
# https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#release
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
update-bug-report:
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ def _handle_error(
|
|||
if process_context.headless:
|
||||
if detail:
|
||||
print(detail)
|
||||
print(f"{10*'*'}\n{message}\n{10*'*'}")
|
||||
print(f"{10 * '*'}\n{message}\n{10 * '*'}")
|
||||
return
|
||||
|
||||
current_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ from ayon_core.lib.env_tools import (
|
|||
)
|
||||
|
||||
|
||||
|
||||
@click.group(invoke_without_command=True)
|
||||
@click.pass_context
|
||||
@click.option("--use-staging", is_flag=True,
|
||||
|
|
@ -173,7 +172,6 @@ def contextselection(
|
|||
main(output_path, project, folder, strict)
|
||||
|
||||
|
||||
|
||||
@main_cli.command(
|
||||
context_settings=dict(
|
||||
ignore_unknown_options=True,
|
||||
|
|
|
|||
30
client/ayon_core/hooks/pre_remove_launcher_paths.py
Normal file
30
client/ayon_core/hooks/pre_remove_launcher_paths.py
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
""""Pre launch hook to remove launcher paths from the system."""
|
||||
import os
|
||||
|
||||
from ayon_applications import PreLaunchHook
|
||||
|
||||
|
||||
class PreRemoveLauncherPaths(PreLaunchHook):
|
||||
"""Remove launcher paths from the system.
|
||||
|
||||
This hook is used to remove launcher paths from the system before launching
|
||||
an application. It is used to ensure that the application is launched with
|
||||
the correct environment variables. Especially for Windows, where
|
||||
paths in `PATH` are used to load DLLs. This is important to avoid
|
||||
conflicts with other applications that may have the same DLLs in their
|
||||
paths.
|
||||
"""
|
||||
order = 1
|
||||
|
||||
def execute(self) -> None:
|
||||
"""Execute the hook."""
|
||||
# Remove launcher paths from the system
|
||||
ayon_root = os.path.normpath(os.environ["AYON_ROOT"])
|
||||
|
||||
paths = [
|
||||
path
|
||||
for path in self.launch_context.env.get(
|
||||
"PATH", "").split(os.pathsep)
|
||||
if not os.path.normpath(path).startswith(ayon_root)
|
||||
]
|
||||
self.launch_context.env["PATH"] = os.pathsep.join(paths)
|
||||
|
|
@ -98,7 +98,6 @@ from .profiles_filtering import (
|
|||
from .transcoding import (
|
||||
get_transcode_temp_directory,
|
||||
should_convert_for_ffmpeg,
|
||||
convert_for_ffmpeg,
|
||||
convert_input_paths_for_ffmpeg,
|
||||
get_ffprobe_data,
|
||||
get_ffprobe_streams,
|
||||
|
|
@ -198,7 +197,6 @@ __all__ = [
|
|||
|
||||
"get_transcode_temp_directory",
|
||||
"should_convert_for_ffmpeg",
|
||||
"convert_for_ffmpeg",
|
||||
"convert_input_paths_for_ffmpeg",
|
||||
"get_ffprobe_data",
|
||||
"get_ffprobe_streams",
|
||||
|
|
|
|||
|
|
@ -22,12 +22,10 @@ import clique
|
|||
if typing.TYPE_CHECKING:
|
||||
from typing import Self, Tuple, Union, TypedDict, Pattern
|
||||
|
||||
|
||||
class EnumItemDict(TypedDict):
|
||||
label: str
|
||||
value: Any
|
||||
|
||||
|
||||
EnumItemsInputType = Union[
|
||||
Dict[Any, str],
|
||||
List[Tuple[Any, str]],
|
||||
|
|
@ -35,7 +33,6 @@ if typing.TYPE_CHECKING:
|
|||
List[EnumItemDict]
|
||||
]
|
||||
|
||||
|
||||
class FileDefItemDict(TypedDict):
|
||||
directory: str
|
||||
filenames: List[str]
|
||||
|
|
@ -289,6 +286,7 @@ AttrDefType = TypeVar("AttrDefType", bound=AbstractAttrDef)
|
|||
# UI attribute definitions won't hold value
|
||||
# -----------------------------------------
|
||||
|
||||
|
||||
class UIDef(AbstractAttrDef):
|
||||
is_value_def = False
|
||||
|
||||
|
|
|
|||
|
|
@ -177,10 +177,12 @@ def initialize_ayon_connection(force=False):
|
|||
return _new_get_last_versions(
|
||||
con, *args, **kwargs
|
||||
)
|
||||
|
||||
def _lv_by_pi_wrapper(*args, **kwargs):
|
||||
return _new_get_last_version_by_product_id(
|
||||
con, *args, **kwargs
|
||||
)
|
||||
|
||||
def _lv_by_pn_wrapper(*args, **kwargs):
|
||||
return _new_get_last_version_by_product_name(
|
||||
con, *args, **kwargs
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ class Terminal:
|
|||
"""
|
||||
|
||||
from ayon_core.lib import env_value_to_bool
|
||||
|
||||
log_no_colors = env_value_to_bool(
|
||||
"AYON_LOG_NO_COLORS", default=None
|
||||
)
|
||||
|
|
|
|||
|
|
@ -526,137 +526,6 @@ def should_convert_for_ffmpeg(src_filepath):
|
|||
return False
|
||||
|
||||
|
||||
# Deprecated since 2022 4 20
|
||||
# - Reason - Doesn't convert sequences right way: Can't handle gaps, reuse
|
||||
# first frame for all frames and changes filenames when input
|
||||
# is sequence.
|
||||
# - use 'convert_input_paths_for_ffmpeg' instead
|
||||
def convert_for_ffmpeg(
|
||||
first_input_path,
|
||||
output_dir,
|
||||
input_frame_start=None,
|
||||
input_frame_end=None,
|
||||
logger=None
|
||||
):
|
||||
"""Convert source file to format supported in ffmpeg.
|
||||
|
||||
Currently can convert only exrs.
|
||||
|
||||
Args:
|
||||
first_input_path (str): Path to first file of a sequence or a single
|
||||
file path for non-sequential input.
|
||||
output_dir (str): Path to directory where output will be rendered.
|
||||
Must not be same as input's directory.
|
||||
input_frame_start (int): Frame start of input.
|
||||
input_frame_end (int): Frame end of input.
|
||||
logger (logging.Logger): Logger used for logging.
|
||||
|
||||
Raises:
|
||||
ValueError: If input filepath has extension not supported by function.
|
||||
Currently is supported only ".exr" extension.
|
||||
"""
|
||||
if logger is None:
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
logger.warning((
|
||||
"DEPRECATED: 'ayon_core.lib.transcoding.convert_for_ffmpeg' is"
|
||||
" deprecated function of conversion for FFMpeg. Please replace usage"
|
||||
" with 'ayon_core.lib.transcoding.convert_input_paths_for_ffmpeg'"
|
||||
))
|
||||
|
||||
ext = os.path.splitext(first_input_path)[1].lower()
|
||||
if ext != ".exr":
|
||||
raise ValueError((
|
||||
"Function 'convert_for_ffmpeg' currently support only"
|
||||
" \".exr\" extension. Got \"{}\"."
|
||||
).format(ext))
|
||||
|
||||
is_sequence = False
|
||||
if input_frame_start is not None and input_frame_end is not None:
|
||||
is_sequence = int(input_frame_end) != int(input_frame_start)
|
||||
|
||||
input_info = get_oiio_info_for_input(first_input_path, logger=logger)
|
||||
|
||||
# Change compression only if source compression is "dwaa" or "dwab"
|
||||
# - they're not supported in ffmpeg
|
||||
compression = input_info["attribs"].get("compression")
|
||||
if compression in ("dwaa", "dwab"):
|
||||
compression = "none"
|
||||
|
||||
# Prepare subprocess arguments
|
||||
oiio_cmd = get_oiio_tool_args(
|
||||
"oiiotool",
|
||||
# Don't add any additional attributes
|
||||
"--nosoftwareattrib",
|
||||
)
|
||||
# Add input compression if available
|
||||
if compression:
|
||||
oiio_cmd.extend(["--compression", compression])
|
||||
|
||||
# Collect channels to export
|
||||
input_arg, channels_arg = get_oiio_input_and_channel_args(input_info)
|
||||
|
||||
oiio_cmd.extend([
|
||||
input_arg, first_input_path,
|
||||
# Tell oiiotool which channels should be put to top stack (and output)
|
||||
"--ch", channels_arg,
|
||||
# Use first subimage
|
||||
"--subimage", "0"
|
||||
])
|
||||
|
||||
# Add frame definitions to arguments
|
||||
if is_sequence:
|
||||
oiio_cmd.extend([
|
||||
"--frames", "{}-{}".format(input_frame_start, input_frame_end)
|
||||
])
|
||||
|
||||
for attr_name, attr_value in input_info["attribs"].items():
|
||||
if not isinstance(attr_value, str):
|
||||
continue
|
||||
|
||||
# Remove attributes that have string value longer than allowed length
|
||||
# for ffmpeg or when contain prohibited symbols
|
||||
erase_reason = "Missing reason"
|
||||
erase_attribute = False
|
||||
if len(attr_value) > MAX_FFMPEG_STRING_LEN:
|
||||
erase_reason = "has too long value ({} chars).".format(
|
||||
len(attr_value)
|
||||
)
|
||||
erase_attribute = True
|
||||
|
||||
if not erase_attribute:
|
||||
for char in NOT_ALLOWED_FFMPEG_CHARS:
|
||||
if char in attr_value:
|
||||
erase_attribute = True
|
||||
erase_reason = (
|
||||
"contains unsupported character \"{}\"."
|
||||
).format(char)
|
||||
break
|
||||
|
||||
if erase_attribute:
|
||||
# Set attribute to empty string
|
||||
logger.info((
|
||||
"Removed attribute \"{}\" from metadata because {}."
|
||||
).format(attr_name, erase_reason))
|
||||
oiio_cmd.extend(["--eraseattrib", attr_name])
|
||||
|
||||
# Add last argument - path to output
|
||||
if is_sequence:
|
||||
ext = os.path.splitext(first_input_path)[1]
|
||||
base_filename = "tmp.%{:0>2}d{}".format(
|
||||
len(str(input_frame_end)), ext
|
||||
)
|
||||
else:
|
||||
base_filename = os.path.basename(first_input_path)
|
||||
output_path = os.path.join(output_dir, base_filename)
|
||||
oiio_cmd.extend([
|
||||
"-o", output_path
|
||||
])
|
||||
|
||||
logger.debug("Conversion command: {}".format(" ".join(oiio_cmd)))
|
||||
run_subprocess(oiio_cmd, logger=logger)
|
||||
|
||||
|
||||
def convert_input_paths_for_ffmpeg(
|
||||
input_paths,
|
||||
output_dir,
|
||||
|
|
@ -664,7 +533,7 @@ def convert_input_paths_for_ffmpeg(
|
|||
):
|
||||
"""Convert source file to format supported in ffmpeg.
|
||||
|
||||
Currently can convert only exrs. The input filepaths should be files
|
||||
Can currently convert only EXRs. The input filepaths should be files
|
||||
with same type. Information about input is loaded only from first found
|
||||
file.
|
||||
|
||||
|
|
@ -691,10 +560,10 @@ def convert_input_paths_for_ffmpeg(
|
|||
ext = os.path.splitext(first_input_path)[1].lower()
|
||||
|
||||
if ext != ".exr":
|
||||
raise ValueError((
|
||||
"Function 'convert_for_ffmpeg' currently support only"
|
||||
" \".exr\" extension. Got \"{}\"."
|
||||
).format(ext))
|
||||
raise ValueError(
|
||||
"Function 'convert_input_paths_for_ffmpeg' currently supports"
|
||||
f" only \".exr\" extension. Got \"{ext}\"."
|
||||
)
|
||||
|
||||
input_info = get_oiio_info_for_input(first_input_path, logger=logger)
|
||||
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ def find_tool_in_custom_paths(paths, tool, validation_func=None):
|
|||
# Handle cases when path is just an executable
|
||||
# - it allows to use executable from PATH
|
||||
# - basename must match 'tool' value (without extension)
|
||||
extless_path, ext = os.path.splitext(path)
|
||||
extless_path, _ext = os.path.splitext(path)
|
||||
if extless_path == tool:
|
||||
executable_path = find_executable(tool)
|
||||
if executable_path and (
|
||||
|
|
@ -181,7 +181,7 @@ def find_tool_in_custom_paths(paths, tool, validation_func=None):
|
|||
|
||||
# If path is a file validate it
|
||||
if os.path.isfile(normalized):
|
||||
basename, ext = os.path.splitext(os.path.basename(path))
|
||||
basename, _ext = os.path.splitext(os.path.basename(path))
|
||||
# Check if the filename has actually the sane bane as 'tool'
|
||||
if basename == tool:
|
||||
executable_path = find_executable(normalized)
|
||||
|
|
|
|||
|
|
@ -872,7 +872,7 @@ class CreateContext:
|
|||
"""
|
||||
return self._event_hub.add_callback(INSTANCE_ADDED_TOPIC, callback)
|
||||
|
||||
def add_instances_removed_callback (self, callback):
|
||||
def add_instances_removed_callback(self, callback):
|
||||
"""Register callback for removed instances.
|
||||
|
||||
Event is triggered when instances are already removed from context.
|
||||
|
|
@ -933,7 +933,7 @@ class CreateContext:
|
|||
"""
|
||||
self._event_hub.add_callback(VALUE_CHANGED_TOPIC, callback)
|
||||
|
||||
def add_pre_create_attr_defs_change_callback (self, callback):
|
||||
def add_pre_create_attr_defs_change_callback(self, callback):
|
||||
"""Register callback to listen pre-create attribute changes.
|
||||
|
||||
Create plugin can trigger refresh of pre-create attributes. Usage of
|
||||
|
|
@ -961,7 +961,7 @@ class CreateContext:
|
|||
PRE_CREATE_ATTR_DEFS_CHANGED_TOPIC, callback
|
||||
)
|
||||
|
||||
def add_create_attr_defs_change_callback (self, callback):
|
||||
def add_create_attr_defs_change_callback(self, callback):
|
||||
"""Register callback to listen create attribute changes.
|
||||
|
||||
Create plugin changed attribute definitions of instance.
|
||||
|
|
@ -986,7 +986,7 @@ class CreateContext:
|
|||
"""
|
||||
self._event_hub.add_callback(CREATE_ATTR_DEFS_CHANGED_TOPIC, callback)
|
||||
|
||||
def add_publish_attr_defs_change_callback (self, callback):
|
||||
def add_publish_attr_defs_change_callback(self, callback):
|
||||
"""Register callback to listen publish attribute changes.
|
||||
|
||||
Publish plugin changed attribute definitions of instance of context.
|
||||
|
|
|
|||
|
|
@ -369,7 +369,7 @@ class PublishAttributes:
|
|||
return copy.deepcopy(self._origin_data)
|
||||
|
||||
def attribute_value_changed(self, key, changes):
|
||||
self._parent.publish_attribute_value_changed(key, changes)
|
||||
self._parent.publish_attribute_value_changed(key, changes)
|
||||
|
||||
def set_publish_plugin_attr_defs(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ def deliver_sequence(
|
|||
report_items[""].append(msg)
|
||||
return report_items, 0
|
||||
|
||||
dir_path, file_name = os.path.split(str(src_path))
|
||||
dir_path, _file_name = os.path.split(str(src_path))
|
||||
|
||||
context = repre["context"]
|
||||
ext = context.get("ext", context.get("representation"))
|
||||
|
|
@ -270,7 +270,7 @@ def deliver_sequence(
|
|||
# context.representation could be .psd
|
||||
ext = ext.replace("..", ".")
|
||||
|
||||
src_collections, remainder = clique.assemble(os.listdir(dir_path))
|
||||
src_collections, _remainder = clique.assemble(os.listdir(dir_path))
|
||||
src_collection = None
|
||||
for col in src_collections:
|
||||
if col.tail != ext:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from __future__ import annotations
|
||||
from __future__ import annotations
|
||||
import copy
|
||||
import os
|
||||
import re
|
||||
|
|
@ -660,14 +660,6 @@ def _get_legacy_product_name_and_group(
|
|||
warnings.warn("Using legacy product name for renders",
|
||||
DeprecationWarning)
|
||||
|
||||
if not source_product_name.startswith(product_type):
|
||||
resulting_group_name = '{}{}{}{}{}'.format(
|
||||
product_type,
|
||||
task_name[0].upper(), task_name[1:],
|
||||
source_product_name[0].upper(), source_product_name[1:])
|
||||
else:
|
||||
resulting_group_name = source_product_name
|
||||
|
||||
# create product name `<product type><Task><Product name>`
|
||||
if not source_product_name.startswith(product_type):
|
||||
resulting_group_name = '{}{}{}{}{}'.format(
|
||||
|
|
@ -1168,7 +1160,7 @@ def prepare_cache_representations(skeleton_data, exp_files, anatomy):
|
|||
|
||||
"""
|
||||
representations = []
|
||||
collections, remainders = clique.assemble(exp_files)
|
||||
collections, _remainders = clique.assemble(exp_files)
|
||||
|
||||
log = Logger.get_logger("farm_publishing")
|
||||
|
||||
|
|
|
|||
|
|
@ -221,19 +221,6 @@ class LoaderPlugin(list):
|
|||
"""
|
||||
return cls.options or []
|
||||
|
||||
@property
|
||||
def fname(self):
|
||||
"""Backwards compatibility with deprecation warning"""
|
||||
|
||||
self.log.warning((
|
||||
"DEPRECATION WARNING: Source - Loader plugin {}."
|
||||
" The 'fname' property on the Loader plugin will be removed in"
|
||||
" future versions of OpenPype. Planned version to drop the support"
|
||||
" is 3.16.6 or 3.17.0."
|
||||
).format(self.__class__.__name__))
|
||||
if hasattr(self, "_fname"):
|
||||
return self._fname
|
||||
|
||||
@classmethod
|
||||
def get_representation_name_aliases(cls, representation_name: str):
|
||||
"""Return representation names to which switching is allowed from
|
||||
|
|
|
|||
|
|
@ -316,12 +316,6 @@ def load_with_repre_context(
|
|||
)
|
||||
|
||||
loader = Loader()
|
||||
|
||||
# Backwards compatibility: Originally the loader's __init__ required the
|
||||
# representation context to set `fname` attribute to the filename to load
|
||||
# Deprecated - to be removed in OpenPype 3.16.6 or 3.17.0.
|
||||
loader._fname = get_representation_path_from_context(repre_context)
|
||||
|
||||
return loader.load(repre_context, name, namespace, options)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ def validate(data, schema=None):
|
|||
if not _CACHED:
|
||||
_precache()
|
||||
|
||||
root, schema = data["schema"].rsplit(":", 1)
|
||||
_root, schema = data["schema"].rsplit(":", 1)
|
||||
|
||||
if isinstance(schema, str):
|
||||
schema = _cache[schema + ".json"]
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ def get_staging_dir_info(
|
|||
staging_dir_config = get_staging_dir_config(
|
||||
project_entity["name"],
|
||||
task_type,
|
||||
task_name ,
|
||||
task_name,
|
||||
product_type,
|
||||
product_name,
|
||||
host_name,
|
||||
|
|
|
|||
|
|
@ -329,9 +329,9 @@ def get_last_workfile(
|
|||
|
||||
Returns:
|
||||
str: Last or first workfile as filename of full path to filename.
|
||||
"""
|
||||
|
||||
filename, version = get_last_workfile_with_version(
|
||||
"""
|
||||
filename, _version = get_last_workfile_with_version(
|
||||
workdir, file_template, fill_data, extensions
|
||||
)
|
||||
if filename is None:
|
||||
|
|
|
|||
|
|
@ -211,7 +211,7 @@ class DeleteOldVersions(load.ProductLoaderPlugin):
|
|||
f"This will keep only the last {versions_to_keep} "
|
||||
f"versions for the {num_contexts} selected product{s}."
|
||||
)
|
||||
informative_text="Warning: This will delete files from disk"
|
||||
informative_text = "Warning: This will delete files from disk"
|
||||
detailed_text = (
|
||||
f"Keep only {versions_to_keep} versions for:\n{contexts_list}"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ from ayon_core.tools.utils import show_message_dialog
|
|||
OTIO = None
|
||||
FRAME_SPLITTER = "__frame_splitter__"
|
||||
|
||||
|
||||
def _import_otio():
|
||||
global OTIO
|
||||
if OTIO is None:
|
||||
|
|
|
|||
|
|
@ -394,7 +394,6 @@ class CollectAnatomyInstanceData(pyblish.api.ContextPlugin):
|
|||
if aov:
|
||||
anatomy_data["aov"] = aov
|
||||
|
||||
|
||||
def _fill_folder_data(self, instance, project_entity, anatomy_data):
|
||||
# QUESTION: should we make sure that all folder data are popped if
|
||||
# folder data cannot be found?
|
||||
|
|
|
|||
|
|
@ -43,4 +43,3 @@ class CollectCoreJobEnvVars(pyblish.api.ContextPlugin):
|
|||
if value:
|
||||
self.log.debug(f"Setting job env: {key}: {value}")
|
||||
env[key] = value
|
||||
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ class CollectHierarchy(pyblish.api.ContextPlugin):
|
|||
"comments": instance.data.get("comments", []),
|
||||
}
|
||||
|
||||
shot_data["attributes"] = {}
|
||||
shot_data["attributes"] = {}
|
||||
SHOT_ATTRS = (
|
||||
"handleStart",
|
||||
"handleEnd",
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ class CollectOtioSubsetResources(
|
|||
repre = self._create_representation(
|
||||
frame_start, frame_end, file=filename)
|
||||
|
||||
|
||||
else:
|
||||
_trim = False
|
||||
dirname, filename = os.path.split(media_ref.target_url)
|
||||
|
|
@ -209,7 +208,6 @@ class CollectOtioSubsetResources(
|
|||
repre = self._create_representation(
|
||||
frame_start, frame_end, file=filename, trim=_trim)
|
||||
|
||||
|
||||
instance.data["originalDirname"] = self.staging_dir
|
||||
|
||||
# add representation to instance data
|
||||
|
|
@ -221,7 +219,6 @@ class CollectOtioSubsetResources(
|
|||
|
||||
instance.data["representations"].append(repre)
|
||||
|
||||
|
||||
self.log.debug(instance.data)
|
||||
|
||||
def _create_representation(self, start, end, **kwargs):
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin):
|
|||
# Keep "filesequence" for backwards compatibility of older jobs
|
||||
targets = ["filesequence", "farm"]
|
||||
label = "Collect rendered frames"
|
||||
settings_category = "core"
|
||||
|
||||
remove_files = False
|
||||
|
||||
_context = None
|
||||
|
||||
|
|
@ -120,7 +123,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin):
|
|||
self._fill_staging_dir(repre_data, anatomy)
|
||||
representations.append(repre_data)
|
||||
|
||||
if not staging_dir_persistent:
|
||||
if self.remove_files and not staging_dir_persistent:
|
||||
add_repre_files_for_cleanup(instance, repre_data)
|
||||
|
||||
instance.data["representations"] = representations
|
||||
|
|
@ -170,7 +173,7 @@ class CollectRenderedFiles(pyblish.api.ContextPlugin):
|
|||
os.environ.update(session_data)
|
||||
|
||||
staging_dir_persistent = self._process_path(data, anatomy)
|
||||
if not staging_dir_persistent:
|
||||
if self.remove_files and not staging_dir_persistent:
|
||||
context.data["cleanupFullPaths"].append(path)
|
||||
context.data["cleanupEmptyDirs"].append(
|
||||
os.path.dirname(path)
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ class ExtractOIIOTranscode(publish.Extractor):
|
|||
|
||||
collection = collections[0]
|
||||
frames = list(collection.indexes)
|
||||
if collection.holes():
|
||||
if collection.holes().indexes:
|
||||
return files_to_convert
|
||||
|
||||
frame_str = "{}-{}#".format(frames[0], frames[-1])
|
||||
|
|
|
|||
|
|
@ -1333,7 +1333,7 @@ class ExtractReview(pyblish.api.InstancePlugin):
|
|||
bg_red, bg_green, bg_blue = overscan_color
|
||||
else:
|
||||
# Backwards compatibility
|
||||
bg_red, bg_green, bg_blue, _ = overscan_color
|
||||
bg_red, bg_green, bg_blue, _ = overscan_color
|
||||
|
||||
overscan_color_value = "#{0:0>2X}{1:0>2X}{2:0>2X}".format(
|
||||
bg_red, bg_green, bg_blue
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from ayon_core.lib import (
|
|||
)
|
||||
from ayon_core.lib.transcoding import convert_colorspace
|
||||
|
||||
from ayon_core.lib.transcoding import VIDEO_EXTENSIONS
|
||||
from ayon_core.lib.transcoding import VIDEO_EXTENSIONS, IMAGE_EXTENSIONS
|
||||
|
||||
|
||||
class ExtractThumbnail(pyblish.api.InstancePlugin):
|
||||
|
|
@ -163,9 +163,12 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
|
|||
# Store new staging to cleanup paths
|
||||
instance.context.data["cleanupFullPaths"].append(dst_staging)
|
||||
|
||||
thumbnail_created = False
|
||||
oiio_supported = is_oiio_supported()
|
||||
thumbnail_created = False
|
||||
for repre in filtered_repres:
|
||||
# Reset for each iteration to handle cases where multiple
|
||||
# reviewable thumbnails are needed
|
||||
repre_thumb_created = False
|
||||
repre_files = repre["files"]
|
||||
src_staging = os.path.normpath(repre["stagingDir"])
|
||||
if not isinstance(repre_files, (list, tuple)):
|
||||
|
|
@ -214,7 +217,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
|
|||
)
|
||||
# If the input can read by OIIO then use OIIO method for
|
||||
# conversion otherwise use ffmpeg
|
||||
thumbnail_created = self._create_thumbnail_oiio(
|
||||
repre_thumb_created = self._create_thumbnail_oiio(
|
||||
full_input_path,
|
||||
full_output_path,
|
||||
colorspace_data
|
||||
|
|
@ -223,21 +226,22 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
|
|||
# Try to use FFMPEG if OIIO is not supported or for cases when
|
||||
# oiiotool isn't available or representation is not having
|
||||
# colorspace data
|
||||
if not thumbnail_created:
|
||||
if not repre_thumb_created:
|
||||
if oiio_supported:
|
||||
self.log.debug(
|
||||
"Converting with FFMPEG because input"
|
||||
" can't be read by OIIO."
|
||||
)
|
||||
|
||||
thumbnail_created = self._create_thumbnail_ffmpeg(
|
||||
repre_thumb_created = self._create_thumbnail_ffmpeg(
|
||||
full_input_path, full_output_path
|
||||
)
|
||||
|
||||
# Skip representation and try next one if wasn't created
|
||||
if not thumbnail_created:
|
||||
if not repre_thumb_created:
|
||||
continue
|
||||
|
||||
thumbnail_created = True
|
||||
if len(explicit_repres) > 1:
|
||||
repre_name = "thumbnail_{}".format(repre["outputName"])
|
||||
else:
|
||||
|
|
@ -332,7 +336,8 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
|
|||
return need_thumb_repres
|
||||
|
||||
def _get_filtered_repres(self, instance):
|
||||
filtered_repres = []
|
||||
review_repres = []
|
||||
other_repres = []
|
||||
src_repres = instance.data.get("representations") or []
|
||||
|
||||
for repre in src_repres:
|
||||
|
|
@ -344,17 +349,36 @@ class ExtractThumbnail(pyblish.api.InstancePlugin):
|
|||
# to be published locally
|
||||
continue
|
||||
|
||||
if "review" not in tags:
|
||||
continue
|
||||
|
||||
if not repre.get("files"):
|
||||
self.log.debug((
|
||||
"Representation \"{}\" doesn't have files. Skipping"
|
||||
).format(repre["name"]))
|
||||
continue
|
||||
|
||||
filtered_repres.append(repre)
|
||||
return filtered_repres
|
||||
if "review" in tags:
|
||||
review_repres.append(repre)
|
||||
elif self._is_valid_images_repre(repre):
|
||||
other_repres.append(repre)
|
||||
|
||||
return review_repres + other_repres
|
||||
|
||||
def _is_valid_images_repre(self, repre):
|
||||
"""Check if representation contains valid image files
|
||||
|
||||
Args:
|
||||
repre (dict): representation
|
||||
|
||||
Returns:
|
||||
bool: whether the representation has the valid image content
|
||||
"""
|
||||
# Get first file's extension
|
||||
first_file = repre["files"]
|
||||
if isinstance(first_file, (list, tuple)):
|
||||
first_file = first_file[0]
|
||||
|
||||
ext = os.path.splitext(first_file)[1].lower()
|
||||
|
||||
return ext in IMAGE_EXTENSIONS or ext in VIDEO_EXTENSIONS
|
||||
|
||||
def _create_thumbnail_oiio(
|
||||
self,
|
||||
|
|
|
|||
|
|
@ -683,7 +683,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin):
|
|||
|
||||
elif is_sequence_representation:
|
||||
# Collection of files (sequence)
|
||||
src_collections, remainders = clique.assemble(files)
|
||||
src_collections, _remainders = clique.assemble(files)
|
||||
|
||||
src_collection = src_collections[0]
|
||||
destination_indexes = list(src_collection.indexes)
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class IntegrateResourcesPath(pyblish.api.InstancePlugin):
|
|||
|
||||
label = "Integrate Resources Path"
|
||||
order = pyblish.api.IntegratorOrder - 0.05
|
||||
families = ["clip", "projectfile", "plate"]
|
||||
families = ["clip", "projectfile", "plate"]
|
||||
|
||||
def process(self, instance):
|
||||
resources = instance.data.get("resources") or []
|
||||
|
|
|
|||
|
|
@ -173,7 +173,6 @@ class ModifiedBurnins(ffmpeg_burnins.Burnins):
|
|||
if frame_end is not None:
|
||||
options["frame_end"] = frame_end
|
||||
|
||||
|
||||
options["label"] = align
|
||||
self._add_burnin(text, align, options, DRAWTEXT)
|
||||
|
||||
|
|
|
|||
|
|
@ -175,7 +175,7 @@ class BaseObj:
|
|||
self.log.warning("Invalid range '{}'".format(part))
|
||||
continue
|
||||
|
||||
for idx in range(sub_parts[0], sub_parts[1]+1):
|
||||
for idx in range(sub_parts[0], sub_parts[1] + 1):
|
||||
indexes.append(idx)
|
||||
return indexes
|
||||
|
||||
|
|
@ -353,7 +353,6 @@ class BaseObj:
|
|||
self.items[item.id] = item
|
||||
item.fill_data_format()
|
||||
|
||||
|
||||
def reset(self):
|
||||
for item in self.items.values():
|
||||
item.reset()
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ class ItemTable(BaseItem):
|
|||
value.draw(image, drawer)
|
||||
|
||||
def value_width(self):
|
||||
row_heights, col_widths = self.size_values
|
||||
_row_heights, col_widths = self.size_values
|
||||
width = 0
|
||||
for _width in col_widths:
|
||||
width += _width
|
||||
|
|
@ -292,7 +292,7 @@ class ItemTable(BaseItem):
|
|||
return width
|
||||
|
||||
def value_height(self):
|
||||
row_heights, col_widths = self.size_values
|
||||
row_heights, _col_widths = self.size_values
|
||||
height = 0
|
||||
for _height in row_heights:
|
||||
height += _height
|
||||
|
|
@ -569,21 +569,21 @@ class TableField(BaseItem):
|
|||
|
||||
@property
|
||||
def item_pos_x(self):
|
||||
pos_x, pos_y, width, height = (
|
||||
pos_x, _pos_y, _width, _height = (
|
||||
self.parent.content_pos_info_by_cord(self.row_idx, self.col_idx)
|
||||
)
|
||||
return pos_x
|
||||
|
||||
@property
|
||||
def item_pos_y(self):
|
||||
pos_x, pos_y, width, height = (
|
||||
_pos_x, pos_y, _width, _height = (
|
||||
self.parent.content_pos_info_by_cord(self.row_idx, self.col_idx)
|
||||
)
|
||||
return pos_y
|
||||
|
||||
@property
|
||||
def value_pos_x(self):
|
||||
pos_x, pos_y, width, height = (
|
||||
pos_x, _pos_y, width, _height = (
|
||||
self.parent.content_pos_info_by_cord(self.row_idx, self.col_idx)
|
||||
)
|
||||
alignment_hor = self.style["alignment-horizontal"].lower()
|
||||
|
|
@ -605,7 +605,7 @@ class TableField(BaseItem):
|
|||
|
||||
@property
|
||||
def value_pos_y(self):
|
||||
pos_x, pos_y, width, height = (
|
||||
_pos_x, pos_y, _width, height = (
|
||||
self.parent.content_pos_info_by_cord(self.row_idx, self.col_idx)
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -248,4 +248,3 @@ class EnhancedTabBar(QtWidgets.QTabBar):
|
|||
|
||||
else:
|
||||
super().mouseReleaseEvent(event)
|
||||
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ def show(parent=None):
|
|||
|
||||
try:
|
||||
module.window.close()
|
||||
del(module.window)
|
||||
del module.window
|
||||
except (AttributeError, RuntimeError):
|
||||
pass
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ from qtpy import QtWidgets, QtCore, QtGui
|
|||
import pyblish.api
|
||||
from ayon_core import style
|
||||
|
||||
TAB = 4* " "
|
||||
TAB = 4 * " "
|
||||
HEADER_SIZE = "15px"
|
||||
|
||||
KEY_COLOR = QtGui.QColor("#ffffff")
|
||||
|
|
@ -243,7 +243,7 @@ class DebugUI(QtWidgets.QDialog):
|
|||
|
||||
self._set_window_title(plugin=result["plugin"])
|
||||
|
||||
print(10*"<", result["plugin"].__name__, 10*">")
|
||||
print(10 * "<", result["plugin"].__name__, 10 * ">")
|
||||
|
||||
plugin_order = result["plugin"].order
|
||||
plugin_name = result["plugin"].__name__
|
||||
|
|
|
|||
|
|
@ -519,9 +519,9 @@ class LoaderWindow(QtWidgets.QWidget):
|
|||
thumbnail_paths.discard(None)
|
||||
|
||||
if thumbnail_paths:
|
||||
self._thumbnails_widget.set_current_thumbnail_paths(
|
||||
thumbnail_paths
|
||||
)
|
||||
self._thumbnails_widget.set_current_thumbnail_paths(
|
||||
thumbnail_paths
|
||||
)
|
||||
else:
|
||||
self._thumbnails_widget.set_current_thumbnails(None)
|
||||
|
||||
|
|
|
|||
|
|
@ -461,19 +461,19 @@ class CreateModel:
|
|||
self._create_context.add_instances_added_callback(
|
||||
self._cc_added_instance
|
||||
)
|
||||
self._create_context.add_instances_removed_callback (
|
||||
self._create_context.add_instances_removed_callback(
|
||||
self._cc_removed_instance
|
||||
)
|
||||
self._create_context.add_value_changed_callback(
|
||||
self._cc_value_changed
|
||||
)
|
||||
self._create_context.add_pre_create_attr_defs_change_callback (
|
||||
self._create_context.add_pre_create_attr_defs_change_callback(
|
||||
self._cc_pre_create_attr_changed
|
||||
)
|
||||
self._create_context.add_create_attr_defs_change_callback (
|
||||
self._create_context.add_create_attr_defs_change_callback(
|
||||
self._cc_create_attr_changed
|
||||
)
|
||||
self._create_context.add_publish_attr_defs_change_callback (
|
||||
self._create_context.add_publish_attr_defs_change_callback(
|
||||
self._cc_publish_attr_changed
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -358,7 +358,7 @@ class PublishReportMaker:
|
|||
|
||||
exception = result.get("error")
|
||||
if exception:
|
||||
fname, line_no, func, exc = exception.traceback
|
||||
fname, line_no, func, _ = exception.traceback
|
||||
|
||||
# Conversion of exception into string may crash
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
import warnings
|
||||
from .broker import StdOutBroker
|
||||
|
||||
warnings.warn(
|
||||
(
|
||||
"Import of 'StdOutBroker' from 'ayon_core.tools.stdout_broker.app'"
|
||||
" is deprecated. Please use 'ayon_core.tools.stdout_broker' instead."
|
||||
),
|
||||
DeprecationWarning
|
||||
)
|
||||
|
||||
__all__ = ("StdOutBroker", )
|
||||
|
|
@ -738,4 +738,3 @@ def main(force=False):
|
|||
sys.exit(1)
|
||||
|
||||
main()
|
||||
|
||||
|
|
|
|||
|
|
@ -350,21 +350,21 @@ class ProjectSortFilterProxy(QtCore.QSortFilterProxyModel):
|
|||
if project_name is None:
|
||||
return True
|
||||
|
||||
string_pattern = self.filterRegularExpression().pattern()
|
||||
if string_pattern:
|
||||
return string_pattern.lower() in project_name.lower()
|
||||
|
||||
# Current project keep always visible
|
||||
default = super(ProjectSortFilterProxy, self).filterAcceptsRow(
|
||||
source_row, source_parent
|
||||
)
|
||||
if not default:
|
||||
return default
|
||||
|
||||
# Make sure current project is visible
|
||||
if index.data(PROJECT_IS_CURRENT_ROLE):
|
||||
return True
|
||||
|
||||
default = super().filterAcceptsRow(source_row, source_parent)
|
||||
if not default:
|
||||
return default
|
||||
|
||||
string_pattern = self.filterRegularExpression().pattern()
|
||||
if (
|
||||
string_pattern
|
||||
and string_pattern.lower() not in project_name.lower()
|
||||
):
|
||||
return False
|
||||
|
||||
if (
|
||||
self._filter_inactive
|
||||
and not index.data(PROJECT_IS_ACTIVE_ROLE)
|
||||
|
|
|
|||
|
|
@ -575,7 +575,7 @@ class TasksWidget(QtWidgets.QWidget):
|
|||
if self._tasks_model.is_refreshing:
|
||||
return
|
||||
|
||||
parent_id, task_id, task_name, _ = self._get_selected_item_ids()
|
||||
_parent_id, task_id, task_name, _ = self._get_selected_item_ids()
|
||||
self._controller.set_selected_task(task_id, task_name)
|
||||
self.selection_changed.emit()
|
||||
|
||||
|
|
|
|||
|
|
@ -462,7 +462,7 @@ class WorkfileEntitiesModel:
|
|||
anatomy = self._controller.project_anatomy
|
||||
|
||||
workdir, filename = os.path.split(filepath)
|
||||
success, rootless_dir = anatomy.find_root_template_from_path(workdir)
|
||||
_, rootless_dir = anatomy.find_root_template_from_path(workdir)
|
||||
return "/".join([
|
||||
os.path.normpath(rootless_dir).replace("\\", "/"),
|
||||
filename
|
||||
|
|
|
|||
|
|
@ -1,3 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Package declaring AYON addon 'core' version."""
|
||||
__version__ = "1.1.7+dev"
|
||||
__version__ = "1.2.0+dev"
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
name = "core"
|
||||
title = "Core"
|
||||
version = "1.1.7+dev"
|
||||
version = "1.2.0+dev"
|
||||
|
||||
client_dir = "ayon_core"
|
||||
|
||||
plugin_for = ["ayon_server"]
|
||||
|
||||
ayon_server_version = ">=1.0.3,<2.0.0"
|
||||
ayon_server_version = ">=1.7.6,<2.0.0"
|
||||
ayon_launcher_version = ">=1.0.2"
|
||||
ayon_required_addons = {}
|
||||
ayon_compatible_addons = {
|
||||
"ayon_ocio": ">=1.2.0",
|
||||
"harmony": ">0.4.0",
|
||||
"fusion": ">=0.3.3",
|
||||
"openrv": ">=1.0.2",
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
[tool.poetry]
|
||||
name = "ayon-core"
|
||||
version = "1.1.7+dev"
|
||||
version = "1.2.0+dev"
|
||||
description = ""
|
||||
authors = ["Ynput Team <team@ynput.io>"]
|
||||
readme = "README.md"
|
||||
|
|
@ -20,7 +20,7 @@ pytest = "^8.0"
|
|||
pytest-print = "^1.0"
|
||||
ayon-python-api = "^1.0"
|
||||
# linting dependencies
|
||||
ruff = "^0.3.3"
|
||||
ruff = "0.11.7"
|
||||
pre-commit = "^3.6.2"
|
||||
codespell = "^2.2.6"
|
||||
semver = "^3.0.2"
|
||||
|
|
@ -41,80 +41,6 @@ pymdown-extensions = "^10.14.3"
|
|||
mike = "^2.1.3"
|
||||
mkdocstrings-shell = "^1.0.2"
|
||||
|
||||
|
||||
[tool.ruff]
|
||||
# Exclude a variety of commonly ignored directories.
|
||||
exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".ipynb_checkpoints",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".pants.d",
|
||||
".pyenv",
|
||||
".pytest_cache",
|
||||
".pytype",
|
||||
".ruff_cache",
|
||||
".svn",
|
||||
".tox",
|
||||
".venv",
|
||||
".vscode",
|
||||
"__pypackages__",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"site-packages",
|
||||
"venv",
|
||||
"vendor",
|
||||
"generated",
|
||||
]
|
||||
|
||||
# Same as Black.
|
||||
line-length = 79
|
||||
indent-width = 4
|
||||
|
||||
# Assume Python 3.9
|
||||
target-version = "py39"
|
||||
|
||||
[tool.ruff.lint]
|
||||
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
||||
select = ["E", "F", "W"]
|
||||
ignore = []
|
||||
|
||||
# Allow fix for all enabled rules (when `--fix`) is provided.
|
||||
fixable = ["ALL"]
|
||||
unfixable = []
|
||||
|
||||
# Allow unused variables when underscore-prefixed.
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
|
||||
exclude = [
|
||||
"client/ayon_core/modules/click_wrap.py",
|
||||
"client/ayon_core/scripts/slates/__init__.py"
|
||||
]
|
||||
|
||||
[tool.ruff.lint.per-file-ignores]
|
||||
"client/ayon_core/lib/__init__.py" = ["E402"]
|
||||
|
||||
[tool.ruff.format]
|
||||
# Like Black, use double quotes for strings.
|
||||
quote-style = "double"
|
||||
|
||||
# Like Black, indent with spaces, rather than tabs.
|
||||
indent-style = "space"
|
||||
|
||||
# Like Black, respect magic trailing commas.
|
||||
skip-magic-trailing-comma = false
|
||||
|
||||
# Like Black, automatically detect the appropriate line ending.
|
||||
line-ending = "auto"
|
||||
|
||||
[tool.codespell]
|
||||
# Ignore words that are not in the dictionary.
|
||||
ignore-words-list = "ayon,ynput,parms,parm,hda,developpement"
|
||||
|
|
@ -123,7 +49,7 @@ ignore-words-list = "ayon,ynput,parms,parm,hda,developpement"
|
|||
# Remove with next codespell release (>2.2.6)
|
||||
ignore-regex = ".*codespell:ignore.*"
|
||||
|
||||
skip = "./.*,./package/*,*/vendor/*,*/unreal/integration/*,*/aftereffects/api/extension/js/libs/*"
|
||||
skip = "./.*,./package/*,*/client/ayon_core/vendor/*"
|
||||
count = true
|
||||
quiet-level = 3
|
||||
|
||||
|
|
|
|||
86
ruff.toml
Normal file
86
ruff.toml
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
# Exclude a variety of commonly ignored directories.
|
||||
exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".ipynb_checkpoints",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".pants.d",
|
||||
".pyenv",
|
||||
".pytest_cache",
|
||||
".pytype",
|
||||
".ruff_cache",
|
||||
".svn",
|
||||
".tox",
|
||||
".venv",
|
||||
".vscode",
|
||||
"__pypackages__",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"site-packages",
|
||||
"venv",
|
||||
"vendor",
|
||||
"generated",
|
||||
]
|
||||
|
||||
# Same as Black.
|
||||
line-length = 79
|
||||
indent-width = 4
|
||||
|
||||
# Assume Python 3.9
|
||||
target-version = "py39"
|
||||
|
||||
[lint]
|
||||
preview = true
|
||||
pydocstyle.convention = "google"
|
||||
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
|
||||
select = ["E", "F", "W"]
|
||||
ignore = []
|
||||
|
||||
# Allow fix for all enabled rules (when `--fix`) is provided.
|
||||
fixable = ["ALL"]
|
||||
unfixable = []
|
||||
|
||||
# Allow unused variables when underscore-prefixed.
|
||||
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||
|
||||
exclude = [
|
||||
"client/ayon_core/scripts/slates/__init__.py"
|
||||
]
|
||||
|
||||
[lint.per-file-ignores]
|
||||
"client/ayon_core/lib/__init__.py" = ["E402"]
|
||||
|
||||
[format]
|
||||
# Like Black, use double quotes for strings.
|
||||
quote-style = "double"
|
||||
|
||||
# Like Black, indent with spaces, rather than tabs.
|
||||
indent-style = "space"
|
||||
|
||||
# Like Black, respect magic trailing commas.
|
||||
skip-magic-trailing-comma = false
|
||||
|
||||
# Like Black, automatically detect the appropriate line ending.
|
||||
line-ending = "auto"
|
||||
|
||||
# Enable auto-formatting of code examples in docstrings. Markdown,
|
||||
# reStructuredText code/literal blocks and doctests are all supported.
|
||||
#
|
||||
# This is currently disabled by default, but it is planned for this
|
||||
# to be opt-out in the future.
|
||||
docstring-code-format = false
|
||||
|
||||
# Set the line length limit used when formatting code snippets in
|
||||
# docstrings.
|
||||
#
|
||||
# This only has an effect when the `docstring-code-format` setting is
|
||||
# enabled.
|
||||
docstring-code-line-length = "dynamic"
|
||||
|
|
@ -7,6 +7,7 @@ from ayon_server.settings import (
|
|||
normalize_name,
|
||||
ensure_unique_names,
|
||||
task_types_enum,
|
||||
anatomy_template_items_enum
|
||||
)
|
||||
|
||||
from ayon_server.types import ColorRGBA_uint8
|
||||
|
|
@ -889,7 +890,11 @@ class IntegrateANTemplateNameProfileModel(BaseSettingsModel):
|
|||
default_factory=list,
|
||||
title="Task names"
|
||||
)
|
||||
template_name: str = SettingsField("", title="Template name")
|
||||
template_name: str = SettingsField(
|
||||
"",
|
||||
title="Template name",
|
||||
enum_resolver=anatomy_template_items_enum(category="publish")
|
||||
)
|
||||
|
||||
|
||||
class IntegrateHeroTemplateNameProfileModel(BaseSettingsModel):
|
||||
|
|
@ -910,7 +915,11 @@ class IntegrateHeroTemplateNameProfileModel(BaseSettingsModel):
|
|||
default_factory=list,
|
||||
title="Task names"
|
||||
)
|
||||
template_name: str = SettingsField("", title="Template name")
|
||||
template_name: str = SettingsField(
|
||||
"",
|
||||
title="Template name",
|
||||
enum_resolver=anatomy_template_items_enum(category="hero")
|
||||
)
|
||||
|
||||
|
||||
class IntegrateHeroVersionModel(BaseSettingsModel):
|
||||
|
|
@ -929,6 +938,20 @@ class IntegrateHeroVersionModel(BaseSettingsModel):
|
|||
"hero versions.")
|
||||
|
||||
|
||||
class CollectRenderedFilesModel(BaseSettingsModel):
|
||||
remove_files: bool = SettingsField(
|
||||
False,
|
||||
title="Remove rendered files",
|
||||
description=(
|
||||
"Remove rendered files and metadata json on publish.\n\n"
|
||||
"Note that when enabled but the render is to a configured "
|
||||
"persistent staging directory the files will not be removed. "
|
||||
"However with this disabled the files will **not** be removed in "
|
||||
"either case."
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class CleanUpModel(BaseSettingsModel):
|
||||
_isGroup = True
|
||||
paterns: list[str] = SettingsField( # codespell:ignore paterns
|
||||
|
|
@ -1041,6 +1064,10 @@ class PublishPuginsModel(BaseSettingsModel):
|
|||
"published as a render/review product of its own."
|
||||
)
|
||||
)
|
||||
CollectRenderedFiles: CollectRenderedFilesModel = SettingsField(
|
||||
default_factory=CollectRenderedFilesModel,
|
||||
title="Clean up farm rendered files"
|
||||
)
|
||||
CleanUp: CleanUpModel = SettingsField(
|
||||
default_factory=CleanUpModel,
|
||||
title="Clean Up"
|
||||
|
|
@ -1428,6 +1455,9 @@ DEFAULT_PUBLISH_VALUES = {
|
|||
"AttachReviewables": {
|
||||
"enabled": True,
|
||||
},
|
||||
"CollectRenderedFiles": {
|
||||
"remove_files": False
|
||||
},
|
||||
"CleanUp": {
|
||||
"paterns": [], # codespell:ignore paterns
|
||||
"remove_temp_renders": False
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ from ayon_server.settings import (
|
|||
normalize_name,
|
||||
ensure_unique_names,
|
||||
task_types_enum,
|
||||
anatomy_template_items_enum
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -283,7 +284,34 @@ class PublishTemplateNameProfile(BaseSettingsModel):
|
|||
task_names: list[str] = SettingsField(
|
||||
default_factory=list, title="Task names"
|
||||
)
|
||||
template_name: str = SettingsField("", title="Template name")
|
||||
template_name: str = SettingsField(
|
||||
"",
|
||||
title="Template name",
|
||||
enum_resolver=anatomy_template_items_enum(category="publish")
|
||||
)
|
||||
|
||||
|
||||
class HeroTemplateNameProfile(BaseSettingsModel):
|
||||
_layout = "expanded"
|
||||
product_types: list[str] = SettingsField(
|
||||
default_factory=list,
|
||||
title="Product types"
|
||||
)
|
||||
# TODO this should use hosts enum
|
||||
hosts: list[str] = SettingsField(default_factory=list, title="Hosts")
|
||||
task_types: list[str] = SettingsField(
|
||||
default_factory=list,
|
||||
title="Task types",
|
||||
enum_resolver=task_types_enum
|
||||
)
|
||||
task_names: list[str] = SettingsField(
|
||||
default_factory=list, title="Task names"
|
||||
)
|
||||
template_name: str = SettingsField(
|
||||
"",
|
||||
title="Template name",
|
||||
enum_resolver=anatomy_template_items_enum(category="hero")
|
||||
)
|
||||
|
||||
|
||||
class CustomStagingDirProfileModel(BaseSettingsModel):
|
||||
|
|
@ -306,7 +334,11 @@ class CustomStagingDirProfileModel(BaseSettingsModel):
|
|||
custom_staging_dir_persistent: bool = SettingsField(
|
||||
False, title="Custom Staging Folder Persistent"
|
||||
)
|
||||
template_name: str = SettingsField("", title="Template Name")
|
||||
template_name: str = SettingsField(
|
||||
"",
|
||||
title="Template name",
|
||||
enum_resolver=anatomy_template_items_enum(category="staging")
|
||||
)
|
||||
|
||||
|
||||
class PublishToolModel(BaseSettingsModel):
|
||||
|
|
@ -314,7 +346,7 @@ class PublishToolModel(BaseSettingsModel):
|
|||
default_factory=list,
|
||||
title="Template name profiles"
|
||||
)
|
||||
hero_template_name_profiles: list[PublishTemplateNameProfile] = (
|
||||
hero_template_name_profiles: list[HeroTemplateNameProfile] = (
|
||||
SettingsField(
|
||||
default_factory=list,
|
||||
title="Hero template name profiles"
|
||||
|
|
|
|||
|
|
@ -101,6 +101,7 @@ def test_image_sequence():
|
|||
expected_data,
|
||||
)
|
||||
|
||||
|
||||
def test_media_retimed():
|
||||
"""
|
||||
EXR image sequence.
|
||||
|
|
|
|||
|
|
@ -215,6 +215,7 @@ def test_short_movie_tail_gap_handles():
|
|||
|
||||
assert calls == expected
|
||||
|
||||
|
||||
def test_multiple_review_clips_no_gap():
|
||||
"""
|
||||
Use multiple review clips (image sequence).
|
||||
|
|
@ -298,6 +299,7 @@ def test_multiple_review_clips_no_gap():
|
|||
|
||||
assert calls == expected
|
||||
|
||||
|
||||
def test_multiple_review_clips_with_gap():
|
||||
"""
|
||||
Use multiple review clips (image sequence) with gap.
|
||||
|
|
|
|||
|
|
@ -257,7 +257,6 @@ def test_movie_timewarp():
|
|||
)
|
||||
|
||||
|
||||
|
||||
def test_img_sequence_no_handles():
|
||||
"""
|
||||
Img sequence clip (no embedded timecode)
|
||||
|
|
@ -334,6 +333,7 @@ def test_img_sequence_relative_source_range():
|
|||
expected_data
|
||||
)
|
||||
|
||||
|
||||
def test_img_sequence_conform_to_23_976fps():
|
||||
"""
|
||||
Img sequence clip
|
||||
|
|
@ -409,6 +409,7 @@ def test_img_sequence_reverse_speed_no_tc():
|
|||
handle_end=0,
|
||||
)
|
||||
|
||||
|
||||
def test_img_sequence_reverse_speed_from_24_to_23_976fps():
|
||||
"""
|
||||
Img sequence clip
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue