Source code for cgl.core.path.sequence

import glob
import logging
import os
import re

from cgl.core.path.constants import SEQ_SPLIT, SEQ2_SPLIT


[docs] class Sequence(object): """ Class for dealing with "Sequences" of images or files in general as defined within a vfx/animation/games cookbook """ sequence = None globals_info = {} frame_range = None start_frame = None end_frame = None middle_frame = None hash_sequence = None num_sequence = None star_sequence = None padding = None ext = None num = None hash = None def __init__(self, sequence, verbose=False): self.sequence = sequence self.verbose = verbose if not self.is_valid_sequence(): return self.padding = 4 self.set_frange() self.set_sequence_strings()
[docs] def get_project_info(self): pass
[docs] def is_valid_sequence(self): """ Checks "sequence" to ensure it matches our definition of a sequence: sequence.####.ext, sequence.%04d.ext, sequence.*.ext Returns: bool: True if valid, False if not """ self.set_ext() valid = False if not self.sequence: return False if self.sequence.endswith("#%s" % self.ext): valid = True elif "%" in self.sequence: valid = True elif self.sequence.endswith("*%s" % self.ext): valid = True if not valid and self.verbose: logging.error("%s is not a valid sequence" % self.sequence) return valid
[docs] def set_ext(self): """ sets the ext value for the sequence Returns: None """ _, self.ext = os.path.splitext(self.sequence)
[docs] def print_info(self): logging.debug("---------------- sequence info -------------------") logging.debug("Star: %s" % self.star_sequence) logging.debug("Hash: %s" % self.hash_sequence) logging.debug("Num: %s" % self.num_sequence) logging.debug("Frame Range: %s" % self.frame_range) logging.debug("Start Frame: %s" % self.start_frame) logging.debug("End Frame: %s" % self.end_frame) logging.debug("Middle Frame: %s" % self.middle_frame)
[docs] def set_sequence_strings(self): """ This is a utility function for setting all the various string formats we need for sequences depending on the software we happen to be working in: ####.exr - hash_sequence %04d.exr - num_sequence *.exr - star_sequence Returns: None """ seq_base = self.split_sequence() self.star_sequence = "%s*%s" % (seq_base, self.ext) self.num_sequence = "%s%s%s" % (seq_base, self.num, self.ext) self.hash_sequence = "%s%s%s" % (seq_base, self.hash, self.ext)
[docs] def split_sequence(self): """ We split the sequence at the delimiter ('*', '%0Nd', or '###') and return the first value. Example: :: split_sequence('sequence.####.exr') returns 'sequence' split_sequence('sequence.%04d.exr') returns 'sequence' split_sequence('sequence.*.exr') returns 'sequence' Returns: str: The first part of the sequence string or None if the sequence is not valid. """ frange = None group = None if self.sequence.endswith("#%s" % self.ext): frange = re.search(SEQ_SPLIT, self.sequence) group = frange.group(0) elif "%" in self.sequence: frange = re.search(SEQ2_SPLIT, self.sequence) group = frange.group(0) elif self.sequence.endswith("*%s" % self.ext): frange = True group = "*." if frange: return self.sequence.split(group)[0] else: return
[docs] def set_frange(self): """ Sets all information regarding frame range for the sequence start_frame, end_frame, middle_frame, frame_range are all set by this function Returns: None """ sframe = None eframe = None regex = re.compile(r"\s[\d]+-[\d]+$") current_sel = self.sequence frange = re.search(regex, current_sel) frame_range = "" if frange: sframe, eframe = frange.group(0).split("-") sframe = sframe.replace(" ", "") else: # This requires the # form of the sequence glob_string = "" if "#" in self.sequence: glob_string = "%s*%s" % (self.sequence.split("#")[0], self.ext) elif "%" in self.sequence: glob_string = "%s*%s" % (self.sequence.split("%")[0], self.ext) elif "*" in self.sequence: glob_string = self.sequence frames = sorted(glob.glob(glob_string)) if frames: try: from cgl.core.list_dir import get_frame_range frame_range = get_frame_range(frames) sframe, eframe = frame_range.split("-") # sframe = re.search(SEQ_REGEX, frames[0]).group(0).replace(".", "") # eframe = re.search(SEQ_REGEX, frames[-1]).group(0).replace(".", "") except AttributeError: logging.error( "problem with file_path: %s and frames: " "%s and %s in get_frange_from_seq, skipping." % (self.sequence, frames[0], frames[1]) ) else: self.start_frame = 1001 # TODO pull this from project_info self.hash = "#" * self.padding if self.padding < 10: self.num = "%0" + str(self.padding) + "d" else: self.num = "%" + str(self.padding) + "d" return if sframe and eframe: self.frame_range = frame_range self.start_frame = sframe self.end_frame = eframe self.padding = len(self.start_frame) self.hash = "#" * self.padding if self.padding < 10: self.num = "%0" + str(self.padding) + "d" else: self.num = "%" + str(self.padding) + "d" mid_frame = int((int(eframe) - int(sframe)) / 2) + int(sframe) self.middle_frame = self.int_as_padded_frame(mid_frame, self.padding)
[docs] @staticmethod def int_as_padded_frame(number, padding=None): """ Given number, return a string with padding of `padding`. Example: Given 3 return string with padding of 4 = 0003:: int_as_padded_frame(3, 4) Args: number (int): The number to convert to a string with padding. padding (int): The number of digits to pad the string with. Returns: str: The number as a string with padding. """ if padding == 2: return "%02d" % number elif padding == 3: return "%03d" % number elif padding == 4: return "%04d" % number elif padding == 5: return "%05d" % number elif padding == 6: return "%06d" % number elif padding == 7: return "%07d" % number elif padding == 8: return "%08d" % number elif padding == 9: return "%09d" % number elif padding == 10: return "%10d" % number elif padding == 11: return "%11d" % number