diff --git a/.github/workflows/pr_linting.yml b/.github/workflows/pr_linting.yml index 896d5b7f4d..d41596fb4a 100644 --- a/.github/workflows/pr_linting.yml +++ b/.github/workflows/pr_linting.yml @@ -21,6 +21,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - - uses: astral-sh/ruff-action@v1 + - uses: astral-sh/ruff-action@v3 with: changed-files: "true" + version-file: "pyproject.toml" diff --git a/client/ayon_core/addon/utils.py b/client/ayon_core/addon/utils.py index f983e37d3c..bb365f42e1 100644 --- a/client/ayon_core/addon/utils.py +++ b/client/ayon_core/addon/utils.py @@ -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__)) diff --git a/client/ayon_core/cli.py b/client/ayon_core/cli.py index 6f89a6d17d..322c294cfb 100644 --- a/client/ayon_core/cli.py +++ b/client/ayon_core/cli.py @@ -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, diff --git a/client/ayon_core/lib/attribute_definitions.py b/client/ayon_core/lib/attribute_definitions.py index 6b334aa16a..cb74fea0f1 100644 --- a/client/ayon_core/lib/attribute_definitions.py +++ b/client/ayon_core/lib/attribute_definitions.py @@ -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 diff --git a/client/ayon_core/lib/ayon_connection.py b/client/ayon_core/lib/ayon_connection.py index 1132d77aaa..32aa5ad629 100644 --- a/client/ayon_core/lib/ayon_connection.py +++ b/client/ayon_core/lib/ayon_connection.py @@ -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 diff --git a/client/ayon_core/lib/terminal.py b/client/ayon_core/lib/terminal.py index 10fcc79a27..ea23feeb95 100644 --- a/client/ayon_core/lib/terminal.py +++ b/client/ayon_core/lib/terminal.py @@ -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 ) diff --git a/client/ayon_core/lib/vendor_bin_utils.py b/client/ayon_core/lib/vendor_bin_utils.py index 41654476c2..412a9292cc 100644 --- a/client/ayon_core/lib/vendor_bin_utils.py +++ b/client/ayon_core/lib/vendor_bin_utils.py @@ -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) diff --git a/client/ayon_core/pipeline/create/context.py b/client/ayon_core/pipeline/create/context.py index 6ac6685647..f0d9fa8927 100644 --- a/client/ayon_core/pipeline/create/context.py +++ b/client/ayon_core/pipeline/create/context.py @@ -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. diff --git a/client/ayon_core/pipeline/create/structures.py b/client/ayon_core/pipeline/create/structures.py index 6b45a5c610..d7ba6b9c24 100644 --- a/client/ayon_core/pipeline/create/structures.py +++ b/client/ayon_core/pipeline/create/structures.py @@ -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, diff --git a/client/ayon_core/pipeline/delivery.py b/client/ayon_core/pipeline/delivery.py index 55c840f3a5..e686b739ae 100644 --- a/client/ayon_core/pipeline/delivery.py +++ b/client/ayon_core/pipeline/delivery.py @@ -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: diff --git a/client/ayon_core/pipeline/farm/pyblish_functions.py b/client/ayon_core/pipeline/farm/pyblish_functions.py index e10bcc9bb1..0d8e70f9d2 100644 --- a/client/ayon_core/pipeline/farm/pyblish_functions.py +++ b/client/ayon_core/pipeline/farm/pyblish_functions.py @@ -1,4 +1,4 @@ -from __future__ import annotations +from __future__ import annotations import copy import os import re @@ -1160,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") diff --git a/client/ayon_core/pipeline/schema/__init__.py b/client/ayon_core/pipeline/schema/__init__.py index d16755696d..5e4e8a668d 100644 --- a/client/ayon_core/pipeline/schema/__init__.py +++ b/client/ayon_core/pipeline/schema/__init__.py @@ -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"] diff --git a/client/ayon_core/pipeline/staging_dir.py b/client/ayon_core/pipeline/staging_dir.py index 1cb2979415..a172c177fd 100644 --- a/client/ayon_core/pipeline/staging_dir.py +++ b/client/ayon_core/pipeline/staging_dir.py @@ -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, diff --git a/client/ayon_core/pipeline/workfile/path_resolving.py b/client/ayon_core/pipeline/workfile/path_resolving.py index 61c6e5b876..9b2fe25199 100644 --- a/client/ayon_core/pipeline/workfile/path_resolving.py +++ b/client/ayon_core/pipeline/workfile/path_resolving.py @@ -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: diff --git a/client/ayon_core/plugins/load/delete_old_versions.py b/client/ayon_core/plugins/load/delete_old_versions.py index f8c45baff6..3a42ccba7e 100644 --- a/client/ayon_core/plugins/load/delete_old_versions.py +++ b/client/ayon_core/plugins/load/delete_old_versions.py @@ -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}" ) diff --git a/client/ayon_core/plugins/load/export_otio.py b/client/ayon_core/plugins/load/export_otio.py index e7a844aed3..8094490246 100644 --- a/client/ayon_core/plugins/load/export_otio.py +++ b/client/ayon_core/plugins/load/export_otio.py @@ -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: diff --git a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py index 677ebb04a2..2fcf562dd0 100644 --- a/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py +++ b/client/ayon_core/plugins/publish/collect_anatomy_instance_data.py @@ -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? diff --git a/client/ayon_core/plugins/publish/collect_farm_env_variables.py b/client/ayon_core/plugins/publish/collect_farm_env_variables.py index 2782ea86ac..39c421381d 100644 --- a/client/ayon_core/plugins/publish/collect_farm_env_variables.py +++ b/client/ayon_core/plugins/publish/collect_farm_env_variables.py @@ -43,4 +43,3 @@ class CollectCoreJobEnvVars(pyblish.api.ContextPlugin): if value: self.log.debug(f"Setting job env: {key}: {value}") env[key] = value - diff --git a/client/ayon_core/plugins/publish/collect_hierarchy.py b/client/ayon_core/plugins/publish/collect_hierarchy.py index 266c2e1458..56b48c37f6 100644 --- a/client/ayon_core/plugins/publish/collect_hierarchy.py +++ b/client/ayon_core/plugins/publish/collect_hierarchy.py @@ -50,7 +50,7 @@ class CollectHierarchy(pyblish.api.ContextPlugin): "comments": instance.data.get("comments", []), } - shot_data["attributes"] = {} + shot_data["attributes"] = {} SHOT_ATTRS = ( "handleStart", "handleEnd", diff --git a/client/ayon_core/plugins/publish/collect_otio_subset_resources.py b/client/ayon_core/plugins/publish/collect_otio_subset_resources.py index f1fa6a817d..275b8a7f55 100644 --- a/client/ayon_core/plugins/publish/collect_otio_subset_resources.py +++ b/client/ayon_core/plugins/publish/collect_otio_subset_resources.py @@ -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): diff --git a/client/ayon_core/plugins/publish/collect_rendered_files.py b/client/ayon_core/plugins/publish/collect_rendered_files.py index deecf7ba24..5c68af888f 100644 --- a/client/ayon_core/plugins/publish/collect_rendered_files.py +++ b/client/ayon_core/plugins/publish/collect_rendered_files.py @@ -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) diff --git a/client/ayon_core/plugins/publish/extract_review.py b/client/ayon_core/plugins/publish/extract_review.py index df87abba91..a15886451b 100644 --- a/client/ayon_core/plugins/publish/extract_review.py +++ b/client/ayon_core/plugins/publish/extract_review.py @@ -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 diff --git a/client/ayon_core/plugins/publish/extract_thumbnail.py b/client/ayon_core/plugins/publish/extract_thumbnail.py index 7062a0a591..b72862ea22 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail.py @@ -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: @@ -450,7 +454,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): # output arguments from presets jpeg_items.extend(ffmpeg_args.get("output") or []) # we just want one frame from movie files - jpeg_items.extend(["-vframes", "1"]) + jpeg_items.extend(["-frames:v", "1"]) if resolution_arg: jpeg_items.extend(resolution_arg) @@ -498,7 +502,7 @@ class ExtractThumbnail(pyblish.api.InstancePlugin): "-i", video_file_path, "-analyzeduration", max_int, "-probesize", max_int, - "-vframes", "1" + "-frames:v", "1" ] # add output file path diff --git a/client/ayon_core/plugins/publish/extract_thumbnail_from_source.py b/client/ayon_core/plugins/publish/extract_thumbnail_from_source.py index 7751d73335..59a62b1d7b 100644 --- a/client/ayon_core/plugins/publish/extract_thumbnail_from_source.py +++ b/client/ayon_core/plugins/publish/extract_thumbnail_from_source.py @@ -170,7 +170,7 @@ class ExtractThumbnailFromSource(pyblish.api.InstancePlugin): "-analyzeduration", max_int, "-probesize", max_int, "-i", src_path, - "-vframes", "1", + "-frames:v", "1", dst_path ) diff --git a/client/ayon_core/plugins/publish/integrate.py b/client/ayon_core/plugins/publish/integrate.py index ae043a10a9..f1e066018c 100644 --- a/client/ayon_core/plugins/publish/integrate.py +++ b/client/ayon_core/plugins/publish/integrate.py @@ -619,8 +619,7 @@ class IntegrateAsset(pyblish.api.InstancePlugin): # used for all represe # from temp to final original_directory = ( - instance.data.get("originalDirname") or instance_stagingdir) - + instance.data.get("originalDirname") or stagingdir) _rootless = self.get_rootless_path(anatomy, original_directory) if _rootless == original_directory: raise KnownPublishError(( @@ -684,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) diff --git a/client/ayon_core/plugins/publish/integrate_resources_path.py b/client/ayon_core/plugins/publish/integrate_resources_path.py index 56dc0e5ef7..b518f7f6f1 100644 --- a/client/ayon_core/plugins/publish/integrate_resources_path.py +++ b/client/ayon_core/plugins/publish/integrate_resources_path.py @@ -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 [] diff --git a/client/ayon_core/plugins/publish/integrate_thumbnail.py b/client/ayon_core/plugins/publish/integrate_thumbnail.py index ca32e60cc2..067c3470e8 100644 --- a/client/ayon_core/plugins/publish/integrate_thumbnail.py +++ b/client/ayon_core/plugins/publish/integrate_thumbnail.py @@ -27,8 +27,10 @@ import collections import pyblish.api import ayon_api +from ayon_api import RequestTypes from ayon_api.operations import OperationsSession + InstanceFilterResult = collections.namedtuple( "InstanceFilterResult", ["instance", "thumbnail_path", "version_id"] @@ -161,6 +163,30 @@ class IntegrateThumbnailsAYON(pyblish.api.ContextPlugin): return None return os.path.normpath(filled_path) + def _create_thumbnail(self, project_name: str, src_filepath: str) -> str: + """Upload thumbnail to AYON and return its id. + + This is temporary fix of 'create_thumbnail' function in ayon_api to + fix jpeg mime type. + + """ + mime_type = None + with open(src_filepath, "rb") as stream: + if b"\xff\xd8\xff" == stream.read(3): + mime_type = "image/jpeg" + + if mime_type is None: + return ayon_api.create_thumbnail(project_name, src_filepath) + + response = ayon_api.upload_file( + f"projects/{project_name}/thumbnails", + src_filepath, + request_type=RequestTypes.post, + headers={"Content-Type": mime_type}, + ) + response.raise_for_status() + return response.json()["id"] + def _integrate_thumbnails( self, filtered_instance_items, @@ -179,7 +205,7 @@ class IntegrateThumbnailsAYON(pyblish.api.ContextPlugin): ).format(instance_label)) continue - thumbnail_id = ayon_api.create_thumbnail( + thumbnail_id = self._create_thumbnail( project_name, thumbnail_path ) diff --git a/client/ayon_core/scripts/otio_burnin.py b/client/ayon_core/scripts/otio_burnin.py index cb72606222..77eeecaff6 100644 --- a/client/ayon_core/scripts/otio_burnin.py +++ b/client/ayon_core/scripts/otio_burnin.py @@ -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) diff --git a/client/ayon_core/scripts/slates/slate_base/base.py b/client/ayon_core/scripts/slates/slate_base/base.py index e1648c916a..a4427bbb86 100644 --- a/client/ayon_core/scripts/slates/slate_base/base.py +++ b/client/ayon_core/scripts/slates/slate_base/base.py @@ -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() diff --git a/client/ayon_core/scripts/slates/slate_base/items.py b/client/ayon_core/scripts/slates/slate_base/items.py index ec3358ed5e..eb7859a6e1 100644 --- a/client/ayon_core/scripts/slates/slate_base/items.py +++ b/client/ayon_core/scripts/slates/slate_base/items.py @@ -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) ) diff --git a/client/ayon_core/tools/common_models/thumbnails.py b/client/ayon_core/tools/common_models/thumbnails.py index 5111d0be28..d25c6a1ecd 100644 --- a/client/ayon_core/tools/common_models/thumbnails.py +++ b/client/ayon_core/tools/common_models/thumbnails.py @@ -27,9 +27,12 @@ class ThumbnailsModel: entity_type, entity_ids, ): - thumbnail_paths = set() + output = { + entity_id: None + for entity_id in entity_ids + } if not project_name or not entity_type or not entity_ids: - return thumbnail_paths + return output thumbnail_id_by_entity_id = {} if entity_type == "folder": @@ -43,7 +46,7 @@ class ThumbnailsModel: ) if not thumbnail_id_by_entity_id: - return thumbnail_paths + return output entity_ids_by_thumbnail_id = collections.defaultdict(set) for entity_id, thumbnail_id in thumbnail_id_by_entity_id.items(): @@ -51,10 +54,6 @@ class ThumbnailsModel: continue entity_ids_by_thumbnail_id[thumbnail_id].add(entity_id) - output = { - entity_id: None - for entity_id in entity_ids - } for thumbnail_id, entity_ids in entity_ids_by_thumbnail_id.items(): thumbnail_path = self._get_thumbnail_path( project_name, entity_type, next(iter(entity_ids)), thumbnail_id diff --git a/client/ayon_core/tools/console_interpreter/ui/widgets.py b/client/ayon_core/tools/console_interpreter/ui/widgets.py index 2b9361666e..3dc55b081c 100644 --- a/client/ayon_core/tools/console_interpreter/ui/widgets.py +++ b/client/ayon_core/tools/console_interpreter/ui/widgets.py @@ -248,4 +248,3 @@ class EnhancedTabBar(QtWidgets.QTabBar): else: super().mouseReleaseEvent(event) - diff --git a/client/ayon_core/tools/creator/window.py b/client/ayon_core/tools/creator/window.py index 5bdc6da9b6..5d1c0a272a 100644 --- a/client/ayon_core/tools/creator/window.py +++ b/client/ayon_core/tools/creator/window.py @@ -492,7 +492,7 @@ def show(parent=None): try: module.window.close() - del(module.window) + del module.window except (AttributeError, RuntimeError): pass diff --git a/client/ayon_core/tools/experimental_tools/pyblish_debug_stepper.py b/client/ayon_core/tools/experimental_tools/pyblish_debug_stepper.py index 33de4bf036..a485c682a1 100644 --- a/client/ayon_core/tools/experimental_tools/pyblish_debug_stepper.py +++ b/client/ayon_core/tools/experimental_tools/pyblish_debug_stepper.py @@ -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__ diff --git a/client/ayon_core/tools/loader/ui/window.py b/client/ayon_core/tools/loader/ui/window.py index 3d2e15c630..b70f5554c7 100644 --- a/client/ayon_core/tools/loader/ui/window.py +++ b/client/ayon_core/tools/loader/ui/window.py @@ -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) diff --git a/client/ayon_core/tools/publisher/models/create.py b/client/ayon_core/tools/publisher/models/create.py index 9644af43e0..900168eaef 100644 --- a/client/ayon_core/tools/publisher/models/create.py +++ b/client/ayon_core/tools/publisher/models/create.py @@ -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 ) diff --git a/client/ayon_core/tools/publisher/models/publish.py b/client/ayon_core/tools/publisher/models/publish.py index 97a956b18f..97070d106f 100644 --- a/client/ayon_core/tools/publisher/models/publish.py +++ b/client/ayon_core/tools/publisher/models/publish.py @@ -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: diff --git a/client/ayon_core/tools/tray/lib.py b/client/ayon_core/tools/tray/lib.py index 13ee1eea5c..deb49b9711 100644 --- a/client/ayon_core/tools/tray/lib.py +++ b/client/ayon_core/tools/tray/lib.py @@ -738,4 +738,3 @@ def main(force=False): sys.exit(1) main() - diff --git a/client/ayon_core/tools/utils/tasks_widget.py b/client/ayon_core/tools/utils/tasks_widget.py index 9118611c23..744eb6060a 100644 --- a/client/ayon_core/tools/utils/tasks_widget.py +++ b/client/ayon_core/tools/utils/tasks_widget.py @@ -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() diff --git a/client/ayon_core/tools/workfiles/models/workfiles.py b/client/ayon_core/tools/workfiles/models/workfiles.py index c621a44937..cc034571f3 100644 --- a/client/ayon_core/tools/workfiles/models/workfiles.py +++ b/client/ayon_core/tools/workfiles/models/workfiles.py @@ -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 diff --git a/client/ayon_core/version.py b/client/ayon_core/version.py index 962ec487a7..01e431577e 100644 --- a/client/ayon_core/version.py +++ b/client/ayon_core/version.py @@ -1,3 +1,3 @@ # -*- coding: utf-8 -*- """Package declaring AYON addon 'core' version.""" -__version__ = "1.1.7+dev" +__version__ = "1.1.8+dev" diff --git a/package.py b/package.py index fe870315cf..a4ffe1a20d 100644 --- a/package.py +++ b/package.py @@ -1,6 +1,6 @@ name = "core" title = "Core" -version = "1.1.7+dev" +version = "1.1.8+dev" client_dir = "ayon_core" diff --git a/pyproject.toml b/pyproject.toml index 86df6535aa..4c4272cc30 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ [tool.poetry] name = "ayon-core" -version = "1.1.7+dev" +version = "1.1.8+dev" description = "" authors = ["Ynput Team "] readme = "README.md" @@ -83,6 +83,8 @@ indent-width = 4 target-version = "py39" [tool.ruff.lint] +preview = true +pydocstyle.convention = "google" # Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default. select = ["E", "F", "W"] ignore = [] diff --git a/server/settings/publish_plugins.py b/server/settings/publish_plugins.py index 39a9c028f9..5f5891e4f4 100644 --- a/server/settings/publish_plugins.py +++ b/server/settings/publish_plugins.py @@ -929,6 +929,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 +1055,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 +1446,9 @@ DEFAULT_PUBLISH_VALUES = { "AttachReviewables": { "enabled": True, }, + "CollectRenderedFiles": { + "remove_files": False + }, "CleanUp": { "paterns": [], # codespell:ignore paterns "remove_temp_renders": False diff --git a/tests/client/ayon_core/pipeline/editorial/test_collect_otio_frame_ranges.py b/tests/client/ayon_core/pipeline/editorial/test_collect_otio_frame_ranges.py index 20f0c05804..2f67ee244c 100644 --- a/tests/client/ayon_core/pipeline/editorial/test_collect_otio_frame_ranges.py +++ b/tests/client/ayon_core/pipeline/editorial/test_collect_otio_frame_ranges.py @@ -101,6 +101,7 @@ def test_image_sequence(): expected_data, ) + def test_media_retimed(): """ EXR image sequence. diff --git a/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py b/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py index 8ad2e44b06..45191a2c53 100644 --- a/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py +++ b/tests/client/ayon_core/pipeline/editorial/test_extract_otio_review.py @@ -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. diff --git a/tests/client/ayon_core/pipeline/editorial/test_media_range_with_retimes.py b/tests/client/ayon_core/pipeline/editorial/test_media_range_with_retimes.py index 112d00b3e4..b475d629bb 100644 --- a/tests/client/ayon_core/pipeline/editorial/test_media_range_with_retimes.py +++ b/tests/client/ayon_core/pipeline/editorial/test_media_range_with_retimes.py @@ -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