From f24f9983058d036bf2b30601c53d8a99d3b33fdc Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Tue, 13 Oct 2020 19:10:11 +0200 Subject: [PATCH 1/6] fix(hiero): review from imagesequence --- pype/plugins/hiero/publish/collect_reviews.py | 62 ++++++++++++++++--- 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/pype/plugins/hiero/publish/collect_reviews.py b/pype/plugins/hiero/publish/collect_reviews.py index a444d57d6b..1d961943c5 100644 --- a/pype/plugins/hiero/publish/collect_reviews.py +++ b/pype/plugins/hiero/publish/collect_reviews.py @@ -1,5 +1,7 @@ from pyblish import api import os +import re +import clique class CollectReviews(api.InstancePlugin): @@ -19,6 +21,8 @@ class CollectReviews(api.InstancePlugin): families = ["plate"] def process(self, instance): + is_sequence = instance.data["isSequence"] + # Exclude non-tagged instances. tagged = False for tag in instance.data["tags"]: @@ -83,7 +87,29 @@ class CollectReviews(api.InstancePlugin): file_path = rev_inst.data.get("sourcePath") file_dir = os.path.dirname(file_path) file = os.path.basename(file_path) - ext = os.path.splitext(file)[-1][1:] + ext = os.path.splitext(file)[-1] + + # detect if sequence + if not is_sequence: + # is video file + files = file + else: + files = list() + source_first = instance.data["sourceFirst"] + self.log.debug("_ file: {}".format(file)) + spliter, padding = self.detect_sequence(file) + self.log.debug("_ spliter, padding: {}, {}".format( + spliter, padding)) + base_name = file.split(spliter)[0] + collection = clique.Collection(base_name, ext, padding, set(range( + int(source_first + rev_inst.data.get("sourceInH")), + int(source_first + rev_inst.data.get("sourceOutH") + 1)))) + self.log.debug("_ collection: {}".format(collection)) + real_files = os.listdir(file_dir) + for item in collection: + if item not in real_files: + continue + files.append(item) # change label instance.data["label"] = "{0} - {1} - ({2})".format( @@ -94,7 +120,7 @@ class CollectReviews(api.InstancePlugin): # adding representation for review mov representation = { - "files": file, + "files": files, "stagingDir": file_dir, "frameStart": rev_inst.data.get("sourceIn"), "frameEnd": rev_inst.data.get("sourceOut"), @@ -102,15 +128,15 @@ class CollectReviews(api.InstancePlugin): "frameEndFtrack": rev_inst.data.get("sourceOutH"), "step": 1, "fps": rev_inst.data.get("fps"), - "name": "preview", - "tags": ["preview", "ftrackreview"], - "ext": ext + "name": "review", + "tags": ["review", "ftrackreview"], + "ext": ext[1:] } media_duration = instance.data.get("mediaDuration") clip_duration_h = instance.data.get("clipDurationH") - if media_duration > clip_duration_h: + if media_duration > clip_duration_h and not is_sequence: self.log.debug("Media duration higher: {}".format( (media_duration - clip_duration_h))) representation.update({ @@ -118,7 +144,7 @@ class CollectReviews(api.InstancePlugin): "frameEnd": instance.data.get("sourceOutH"), "tags": ["_cut-bigger", "delete"] }) - elif media_duration < clip_duration_h: + elif media_duration < clip_duration_h and not is_sequence: self.log.debug("Media duration higher: {}".format( (media_duration - clip_duration_h))) representation.update({ @@ -205,3 +231,25 @@ class CollectReviews(api.InstancePlugin): instance.data["versionData"] = version_data instance.data["source"] = instance.data["sourcePath"] + + def detect_sequence(self, file): + """ Get identificating pater for image sequence + + Can find file.0001.ext, file.%02d.ext, file.####.ext + + Return: + string: any matching sequence patern + int: padding of sequnce numbering + """ + foundall = re.findall(r"(#+)|(%\d+d)|[^a-zA-Z](\d+)\.\w+$", file) + if foundall: + found = sorted(list(set(foundall[0])))[-1] + + if "%" in found: + padding = int(re.findall(r"\d+", found)[-1]) + else: + padding = len(found) + + return found, padding + else: + return None From 17dab30fb34bf67f4022dca11d303ea047f797f2 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 15 Oct 2020 09:38:58 +0200 Subject: [PATCH 2/6] feat(hiero): renaming plugin to be used by image sequence --- ...{extract_review_cutup_video.py => extract_review_cutup.py} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename pype/plugins/hiero/publish/{extract_review_cutup_video.py => extract_review_cutup.py} (99%) diff --git a/pype/plugins/hiero/publish/extract_review_cutup_video.py b/pype/plugins/hiero/publish/extract_review_cutup.py similarity index 99% rename from pype/plugins/hiero/publish/extract_review_cutup_video.py rename to pype/plugins/hiero/publish/extract_review_cutup.py index 868d450fd6..1890f13738 100644 --- a/pype/plugins/hiero/publish/extract_review_cutup_video.py +++ b/pype/plugins/hiero/publish/extract_review_cutup.py @@ -3,12 +3,12 @@ from pyblish import api import pype -class ExtractReviewCutUpVideo(pype.api.Extractor): +class ExtractReviewCutUp(pype.api.Extractor): """Cut up clips from long video file""" order = api.ExtractorOrder # order = api.CollectorOrder + 0.1023 - label = "Extract Review CutUp Video" + label = "Extract Review CutUp" hosts = ["hiero"] families = ["review"] From 9c35bb30fac5cdc85d74e4504502a173332ad41e Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 15 Oct 2020 09:53:58 +0200 Subject: [PATCH 3/6] feat(hiero): rename collect reviews to review --- .../hiero/publish/{collect_reviews.py => collect_review.py} | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) rename pype/plugins/hiero/publish/{collect_reviews.py => collect_review.py} (98%) diff --git a/pype/plugins/hiero/publish/collect_reviews.py b/pype/plugins/hiero/publish/collect_review.py similarity index 98% rename from pype/plugins/hiero/publish/collect_reviews.py rename to pype/plugins/hiero/publish/collect_review.py index 1d961943c5..e6715d42b0 100644 --- a/pype/plugins/hiero/publish/collect_reviews.py +++ b/pype/plugins/hiero/publish/collect_review.py @@ -4,7 +4,7 @@ import re import clique -class CollectReviews(api.InstancePlugin): +class CollectReview(api.InstancePlugin): """Collect review from tags. Tag is expected to have metadata: @@ -136,7 +136,7 @@ class CollectReviews(api.InstancePlugin): media_duration = instance.data.get("mediaDuration") clip_duration_h = instance.data.get("clipDurationH") - if media_duration > clip_duration_h and not is_sequence: + if media_duration > clip_duration_h: self.log.debug("Media duration higher: {}".format( (media_duration - clip_duration_h))) representation.update({ @@ -144,7 +144,7 @@ class CollectReviews(api.InstancePlugin): "frameEnd": instance.data.get("sourceOutH"), "tags": ["_cut-bigger", "delete"] }) - elif media_duration < clip_duration_h and not is_sequence: + elif media_duration < clip_duration_h: self.log.debug("Media duration higher: {}".format( (media_duration - clip_duration_h))) representation.update({ From dba1f34bd773c74d8565de26bb1c3b363c2dcdff Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 15 Oct 2020 12:38:48 +0200 Subject: [PATCH 4/6] feat(hiero): review imagesequence with cuts --- pype/plugins/hiero/publish/collect_clips.py | 4 +- pype/plugins/hiero/publish/collect_review.py | 32 +- .../hiero/publish/extract_review_cutup.py | 349 +++++++++++------- 3 files changed, 235 insertions(+), 150 deletions(-) diff --git a/pype/plugins/hiero/publish/collect_clips.py b/pype/plugins/hiero/publish/collect_clips.py index 2c7ea3ec60..724e4730ed 100644 --- a/pype/plugins/hiero/publish/collect_clips.py +++ b/pype/plugins/hiero/publish/collect_clips.py @@ -143,8 +143,8 @@ class CollectClips(api.ContextPlugin): "asset": asset, "family": "clip", "families": [], - "handleStart": projectdata.get("handleStart", 0), - "handleEnd": projectdata.get("handleEnd", 0), + "handleStart": int(projectdata.get("handleStart", 0)), + "handleEnd": int(projectdata.get("handleEnd", 0)), "fps": context.data["fps"] }) instance = context.create_instance(**data) diff --git a/pype/plugins/hiero/publish/collect_review.py b/pype/plugins/hiero/publish/collect_review.py index e6715d42b0..157b8d88f8 100644 --- a/pype/plugins/hiero/publish/collect_review.py +++ b/pype/plugins/hiero/publish/collect_review.py @@ -16,7 +16,7 @@ class CollectReview(api.InstancePlugin): # Run just before CollectSubsets order = api.CollectorOrder + 0.1022 - label = "Collect Reviews" + label = "Collect Review" hosts = ["hiero"] families = ["plate"] @@ -158,11 +158,17 @@ class CollectReview(api.InstancePlugin): self.log.debug("Added representation: {}".format(representation)) def create_thumbnail(self, instance): + is_sequence = instance.data["isSequence"] item = instance.data["item"] source_path = instance.data["sourcePath"] source_file = os.path.basename(source_path) - head, ext = os.path.splitext(source_file) + spliter, padding = self.detect_sequence(source_file) + + if spliter: + head, ext = source_file.split(spliter) + else: + head, ext = os.path.splitext(source_file) # staging dir creation staging_dir = os.path.dirname( @@ -170,30 +176,28 @@ class CollectReview(api.InstancePlugin): media_duration = instance.data.get("mediaDuration") clip_duration_h = instance.data.get("clipDurationH") + self.log.debug("__ media_duration: {}".format(media_duration)) + self.log.debug("__ clip_duration_h: {}".format(clip_duration_h)) - if media_duration > clip_duration_h: - thumb_frame = instance.data["clipInH"] + ( - (instance.data["clipOutH"] - instance.data["clipInH"]) / 2) - elif media_duration <= clip_duration_h: - thumb_frame = instance.data["sourceIn"] + ( - (instance.data["sourceOut"] - instance.data["sourceIn"]) / 2) - thumb_file = "{}_{}{}".format(head, thumb_frame, ".png") + thumb_frame = int(instance.data["sourceIn"] + ( + (instance.data["sourceOut"] - instance.data["sourceIn"]) / 2)) + + thumb_file = "{}thumbnail{}{}".format(head, thumb_frame, ".png") thumb_path = os.path.join(staging_dir, thumb_file) self.log.debug("__ thumb_path: {}".format(thumb_path)) self.log.debug("__ thumb_frame: {}".format(thumb_frame)) + self.log.debug( + "__ sourceIn: `{}`".format(instance.data["sourceIn"])) + thumbnail = item.thumbnail(thumb_frame).save( thumb_path, format='png' ) - - self.log.debug( - "__ sourceIn: `{}`".format(instance.data["sourceIn"])) self.log.debug( "__ thumbnail: `{}`, frame: `{}`".format(thumbnail, thumb_frame)) self.log.debug("__ thumbnail: {}".format(thumbnail)) - thumb_representation = { 'files': thumb_file, 'stagingDir': staging_dir, @@ -252,4 +256,4 @@ class CollectReview(api.InstancePlugin): return found, padding else: - return None + return None, None diff --git a/pype/plugins/hiero/publish/extract_review_cutup.py b/pype/plugins/hiero/publish/extract_review_cutup.py index 1890f13738..57ec6c1107 100644 --- a/pype/plugins/hiero/publish/extract_review_cutup.py +++ b/pype/plugins/hiero/publish/extract_review_cutup.py @@ -1,6 +1,11 @@ import os +import sys +import six +import errno from pyblish import api import pype +import clique +from avalon.vendor import filelink class ExtractReviewCutUp(pype.api.Extractor): @@ -22,6 +27,9 @@ class ExtractReviewCutUp(pype.api.Extractor): # get representation and loop them representations = inst_data["representations"] + # check if sequence + is_sequence = inst_data["isSequence"] + # get resolution default resolution_width = inst_data["resolutionWidth"] resolution_height = inst_data["resolutionHeight"] @@ -51,174 +59,224 @@ class ExtractReviewCutUp(pype.api.Extractor): self.log.debug("__ repre: {}".format(repre)) - file = repre.get("files") + files = repre.get("files") staging_dir = repre.get("stagingDir") - frame_start = repre.get("frameStart") - frame_end = repre.get("frameEnd") fps = repre.get("fps") ext = repre.get("ext") - new_file_name = "{}_{}".format(asset, file) - - full_input_path = os.path.join( - staging_dir, file) - + # make paths full_output_dir = os.path.join( staging_dir, "cuts") - os.path.isdir(full_output_dir) or os.makedirs(full_output_dir) + if is_sequence: + new_files = list() - full_output_path = os.path.join( - full_output_dir, new_file_name) + # frame range delivery included handles + frame_start = ( + inst_data["frameStart"] - inst_data["handleStart"]) + frame_end = ( + inst_data["frameEnd"] + inst_data["handleEnd"]) + self.log.debug("_ frame_start: {}".format(frame_start)) + self.log.debug("_ frame_end: {}".format(frame_end)) - self.log.debug("__ full_input_path: {}".format(full_input_path)) - self.log.debug("__ full_output_path: {}".format(full_output_path)) + # make collection from input files list + collections, remainder = clique.assemble(files) + collection = collections.pop() + self.log.debug("_ collection: {}".format(collection)) - # check if audio stream is in input video file - ffprob_cmd = ( - "{ffprobe_path} -i \"{full_input_path}\" -show_streams " - "-select_streams a -loglevel error" - ).format(**locals()) - self.log.debug("ffprob_cmd: {}".format(ffprob_cmd)) - audio_check_output = pype.api.subprocess(ffprob_cmd) - self.log.debug("audio_check_output: {}".format(audio_check_output)) + # name components + head = collection.format("{head}") + padding = collection.format("{padding}") + tail = collection.format("{tail}") + self.log.debug("_ head: {}".format(head)) + self.log.debug("_ padding: {}".format(padding)) + self.log.debug("_ tail: {}".format(tail)) - # translate frame to sec - start_sec = float(frame_start) / fps - duration_sec = float(frame_end - frame_start + 1) / fps + # make destination file with instance data + # frame start and end range + index = 0 + for image in collection: + dst_file_num = frame_start + index + dst_file_name = head + str(padding % dst_file_num) + tail + src = os.path.join(staging_dir, image) + dst = os.path.join(full_output_dir, dst_file_name) + self.log.info("Creating temp hardlinks: {}".format(dst)) + self.hardlink_file(src, dst) + new_files.append(dst_file_name) + index += 1 - empty_add = None + self.log.debug("_ new_files: {}".format(new_files)) - # check if not missing frames at start - if (start_sec < 0) or (media_duration < frame_end): - # for later swithing off `-c:v copy` output arg - empty_add = True + else: + # ffmpeg when single file + new_files = "{}_{}".format(asset, files) - # init empty variables - video_empty_start = video_layer_start = "" - audio_empty_start = audio_layer_start = "" - video_empty_end = video_layer_end = "" - audio_empty_end = audio_layer_end = "" - audio_input = audio_output = "" - v_inp_idx = 0 - concat_n = 1 + # frame range + frame_start = repre.get("frameStart") + frame_end = repre.get("frameEnd") - # try to get video native resolution data - try: - resolution_output = pype.api.subprocess(( - "{ffprobe_path} -i \"{full_input_path}\" -v error " - "-select_streams v:0 -show_entries " - "stream=width,height -of csv=s=x:p=0" + full_input_path = os.path.join( + staging_dir, files) + + os.path.isdir(full_output_dir) or os.makedirs(full_output_dir) + + full_output_path = os.path.join( + full_output_dir, new_files) + + self.log.debug( + "__ full_input_path: {}".format(full_input_path)) + self.log.debug( + "__ full_output_path: {}".format(full_output_path)) + + # check if audio stream is in input video file + ffprob_cmd = ( + "{ffprobe_path} -i \"{full_input_path}\" -show_streams " + "-select_streams a -loglevel error" + ).format(**locals()) + self.log.debug("ffprob_cmd: {}".format(ffprob_cmd)) + audio_check_output = pype.api.subprocess(ffprob_cmd) + self.log.debug( + "audio_check_output: {}".format(audio_check_output)) + + # translate frame to sec + start_sec = float(frame_start) / fps + duration_sec = float(frame_end - frame_start + 1) / fps + + empty_add = None + + # check if not missing frames at start + if (start_sec < 0) or (media_duration < frame_end): + # for later swithing off `-c:v copy` output arg + empty_add = True + + # init empty variables + video_empty_start = video_layer_start = "" + audio_empty_start = audio_layer_start = "" + video_empty_end = video_layer_end = "" + audio_empty_end = audio_layer_end = "" + audio_input = audio_output = "" + v_inp_idx = 0 + concat_n = 1 + + # try to get video native resolution data + try: + resolution_output = pype.api.subprocess(( + "{ffprobe_path} -i \"{full_input_path}\" -v error " + "-select_streams v:0 -show_entries " + "stream=width,height -of csv=s=x:p=0" + ).format(**locals())) + + x, y = resolution_output.split("x") + resolution_width = int(x) + resolution_height = int(y) + except Exception as _ex: + self.log.warning( + "Video native resolution is untracable: {}".format( + _ex)) + + if audio_check_output: + # adding input for empty audio + input_args.append("-f lavfi -i anullsrc") + + # define audio empty concat variables + audio_input = "[1:a]" + audio_output = ":a=1" + v_inp_idx = 1 + + # adding input for video black frame + input_args.append(( + "-f lavfi -i \"color=c=black:" + "s={resolution_width}x{resolution_height}:r={fps}\"" ).format(**locals())) - x, y = resolution_output.split("x") - resolution_width = int(x) - resolution_height = int(y) - except Exception as E: - self.log.warning( - "Video native resolution is untracable: {}".format(E)) + if (start_sec < 0): + # recalculate input video timing + empty_start_dur = abs(start_sec) + start_sec = 0 + duration_sec = float(frame_end - ( + frame_start + (empty_start_dur * fps)) + 1) / fps - if audio_check_output: - # adding input for empty audio - input_args.append("-f lavfi -i anullsrc") - - # define audio empty concat variables - audio_input = "[1:a]" - audio_output = ":a=1" - v_inp_idx = 1 - - # adding input for video black frame - input_args.append(( - "-f lavfi -i \"color=c=black:" - "s={resolution_width}x{resolution_height}:r={fps}\"" - ).format(**locals())) - - if (start_sec < 0): - # recalculate input video timing - empty_start_dur = abs(start_sec) - start_sec = 0 - duration_sec = float(frame_end - ( - frame_start + (empty_start_dur * fps)) + 1) / fps - - # define starting empty video concat variables - video_empty_start = ( - "[{v_inp_idx}]trim=duration={empty_start_dur}[gv0];" - ).format(**locals()) - video_layer_start = "[gv0]" - - if audio_check_output: - # define starting empty audio concat variables - audio_empty_start = ( - "[0]atrim=duration={empty_start_dur}[ga0];" + # define starting empty video concat variables + video_empty_start = ( + "[{v_inp_idx}]trim=duration={empty_start_dur}[gv0];" # noqa ).format(**locals()) - audio_layer_start = "[ga0]" + video_layer_start = "[gv0]" - # alter concat number of clips - concat_n += 1 + if audio_check_output: + # define starting empty audio concat variables + audio_empty_start = ( + "[0]atrim=duration={empty_start_dur}[ga0];" + ).format(**locals()) + audio_layer_start = "[ga0]" - # check if not missing frames at the end - if (media_duration < frame_end): - # recalculate timing - empty_end_dur = float(frame_end - media_duration + 1) / fps - duration_sec = float(media_duration - frame_start) / fps + # alter concat number of clips + concat_n += 1 - # define ending empty video concat variables - video_empty_end = ( - "[{v_inp_idx}]trim=duration={empty_end_dur}[gv1];" - ).format(**locals()) - video_layer_end = "[gv1]" + # check if not missing frames at the end + if (media_duration < frame_end): + # recalculate timing + empty_end_dur = float( + frame_end - media_duration + 1) / fps + duration_sec = float( + media_duration - frame_start) / fps - if audio_check_output: - # define ending empty audio concat variables - audio_empty_end = ( - "[0]atrim=duration={empty_end_dur}[ga1];" + # define ending empty video concat variables + video_empty_end = ( + "[{v_inp_idx}]trim=duration={empty_end_dur}[gv1];" ).format(**locals()) - audio_layer_end = "[ga0]" + video_layer_end = "[gv1]" - # alter concat number of clips - concat_n += 1 + if audio_check_output: + # define ending empty audio concat variables + audio_empty_end = ( + "[0]atrim=duration={empty_end_dur}[ga1];" + ).format(**locals()) + audio_layer_end = "[ga0]" - # concatting black frame togather - output_args.append(( - "-filter_complex \"" - "{audio_empty_start}" - "{video_empty_start}" - "{audio_empty_end}" - "{video_empty_end}" - "{video_layer_start}{audio_layer_start}[1:v]{audio_input}" - "{video_layer_end}{audio_layer_end}" - "concat=n={concat_n}:v=1{audio_output}\"" - ).format(**locals())) + # alter concat number of clips + concat_n += 1 - # append ffmpeg input video clip - input_args.append("-ss {:0.2f}".format(start_sec)) - input_args.append("-t {:0.2f}".format(duration_sec)) - input_args.append("-i \"{}\"".format(full_input_path)) + # concatting black frame togather + output_args.append(( + "-filter_complex \"" + "{audio_empty_start}" + "{video_empty_start}" + "{audio_empty_end}" + "{video_empty_end}" + "{video_layer_start}{audio_layer_start}[1:v]{audio_input}" # noqa + "{video_layer_end}{audio_layer_end}" + "concat=n={concat_n}:v=1{audio_output}\"" + ).format(**locals())) - # add copy audio video codec if only shortening clip - if ("_cut-bigger" in tags) and (not empty_add): - output_args.append("-c:v copy") + # append ffmpeg input video clip + input_args.append("-ss {:0.2f}".format(start_sec)) + input_args.append("-t {:0.2f}".format(duration_sec)) + input_args.append("-i \"{}\"".format(full_input_path)) - # make sure it is having no frame to frame comprassion - output_args.append("-intra") + # add copy audio video codec if only shortening clip + if ("_cut-bigger" in tags) and (not empty_add): + output_args.append("-c:v copy") - # output filename - output_args.append("-y \"{}\"".format(full_output_path)) + # make sure it is having no frame to frame comprassion + output_args.append("-intra") - mov_args = [ - ffmpeg_path, - " ".join(input_args), - " ".join(output_args) - ] - subprcs_cmd = " ".join(mov_args) + # output filename + output_args.append("-y \"{}\"".format(full_output_path)) - # run subprocess - self.log.debug("Executing: {}".format(subprcs_cmd)) - output = pype.api.subprocess(subprcs_cmd) - self.log.debug("Output: {}".format(output)) + mov_args = [ + ffmpeg_path, + " ".join(input_args), + " ".join(output_args) + ] + subprcs_cmd = " ".join(mov_args) + + # run subprocess + self.log.debug("Executing: {}".format(subprcs_cmd)) + output = pype.api.subprocess(subprcs_cmd) + self.log.debug("Output: {}".format(output)) repre_new = { - "files": new_file_name, + "files": new_files, "stagingDir": full_output_dir, "frameStart": frame_start, "frameEnd": frame_end, @@ -242,3 +300,26 @@ class ExtractReviewCutUp(pype.api.Extractor): self.log.debug( "Representations: {}".format(representations_new)) instance.data["representations"] = representations_new + + def hardlink_file(self, src, dst): + dirname = os.path.dirname(dst) + + # make sure the destination folder exist + try: + os.makedirs(dirname) + except OSError as e: + if e.errno == errno.EEXIST: + pass + else: + self.log.critical("An unexpected error occurred.") + six.reraise(*sys.exc_info()) + + # create hardlined file + try: + filelink.create(src, dst, filelink.HARDLINK) + except OSError as e: + if e.errno == errno.EEXIST: + pass + else: + self.log.critical("An unexpected error occurred.") + six.reraise(*sys.exc_info()) From 7d78f971925c8d11debbb13725f789efa9f0f8c8 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 15 Oct 2020 13:04:06 +0200 Subject: [PATCH 5/6] fix(hiero): fixing regex expression --- pype/plugins/hiero/publish/collect_review.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pype/plugins/hiero/publish/collect_review.py b/pype/plugins/hiero/publish/collect_review.py index 157b8d88f8..781afd782a 100644 --- a/pype/plugins/hiero/publish/collect_review.py +++ b/pype/plugins/hiero/publish/collect_review.py @@ -245,7 +245,7 @@ class CollectReview(api.InstancePlugin): string: any matching sequence patern int: padding of sequnce numbering """ - foundall = re.findall(r"(#+)|(%\d+d)|[^a-zA-Z](\d+)\.\w+$", file) + foundall = re.findall(r"(#+)|(%\d+d)|(?<=[^a-zA-Z0-9])(\d+)(?=\.\w+$)", file) if foundall: found = sorted(list(set(foundall[0])))[-1] From 863cea4aa72ed30b2d50efeadfd0fb81686b2738 Mon Sep 17 00:00:00 2001 From: Jakub Jezek Date: Thu, 15 Oct 2020 13:07:02 +0200 Subject: [PATCH 6/6] hound(hiero) --- pype/plugins/hiero/publish/collect_review.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pype/plugins/hiero/publish/collect_review.py b/pype/plugins/hiero/publish/collect_review.py index 781afd782a..f1767b2a68 100644 --- a/pype/plugins/hiero/publish/collect_review.py +++ b/pype/plugins/hiero/publish/collect_review.py @@ -158,7 +158,6 @@ class CollectReview(api.InstancePlugin): self.log.debug("Added representation: {}".format(representation)) def create_thumbnail(self, instance): - is_sequence = instance.data["isSequence"] item = instance.data["item"] source_path = instance.data["sourcePath"] @@ -245,7 +244,8 @@ class CollectReview(api.InstancePlugin): string: any matching sequence patern int: padding of sequnce numbering """ - foundall = re.findall(r"(#+)|(%\d+d)|(?<=[^a-zA-Z0-9])(\d+)(?=\.\w+$)", file) + foundall = re.findall( + r"(#+)|(%\d+d)|(?<=[^a-zA-Z0-9])(\d+)(?=\.\w+$)", file) if foundall: found = sorted(list(set(foundall[0])))[-1]