def testGetPaddingNum(self): """ Ensure that we're getting back the proper padding number. :return: None """ self.assertEqual(getPaddingNum('@'), 1) self.assertEqual(getPaddingNum('@@'), 2) self.assertEqual(getPaddingNum('@@@'), 3) self.assertEqual(getPaddingNum('#'), 4) self.assertEqual(getPaddingNum('##'), 8) self.assertEqual(getPaddingNum('#@'), 5) self.assertEqual(getPaddingNum('##@@'), 10) self.assertEqual(getPaddingNum('%01d'), 1) self.assertEqual(getPaddingNum('%1d'), 1) self.assertEqual(getPaddingNum('%04d'), 4) self.assertEqual(getPaddingNum('%10d'), 10) allPossibleChars = [ s for s in string.printable if s not in list(PAD_MAP.keys()) ] for char in allPossibleChars: self.assertRaises(ValueError, getPaddingNum, char) self.assertRaises(ValueError, getPaddingNum, '#{}'.format(char)) self.assertRaises(ValueError, getPaddingNum, '@{}'.format(char)) allPossibleChars = [ s for s in string.printable if s not in list(PAD_MAP.keys()) and s not in string.digits ] for char in allPossibleChars: self.assertRaises(ValueError, getPaddingNum, '%{}d'.format(char))
def testGetPaddingNum(self): """ Ensure that we're getting back the proper padding number. :return: None """ self.assertEqual(getPaddingNum('@'), 1) self.assertEqual(getPaddingNum('@@'), 2) self.assertEqual(getPaddingNum('@@@'), 3) self.assertEqual(getPaddingNum('#'), 4) self.assertEqual(getPaddingNum('##'), 8) self.assertEqual(getPaddingNum('#@'), 5) self.assertEqual(getPaddingNum('##@@'), 10) self.assertEqual(getPaddingNum('%01d'), 1) self.assertEqual(getPaddingNum('%1d'), 1) self.assertEqual(getPaddingNum('%04d'), 4) self.assertEqual(getPaddingNum('%10d'), 10) allPossibleChars = [s for s in string.printable if s not in PAD_MAP.keys()] for char in allPossibleChars: self.assertRaises(ValueError, getPaddingNum, char) self.assertRaises(ValueError, getPaddingNum, '#{}'.format(char)) self.assertRaises(ValueError, getPaddingNum, '@{}'.format(char)) allPossibleChars = [s for s in string.printable if s not in PAD_MAP.keys() and s not in string.digits] for char in allPossibleChars: self.assertRaises(ValueError, getPaddingNum, '%{}d'.format(char))
def isFrameRange(frange): """ Return True if the given string is a frame range. Any padding characters, such as '#' and '@' are ignored. Args: frange (str): a frame range to test Returns: bool: """ # we're willing to trim padding characters from consideration # this translation is orders of magnitude faster than prior method if future.utils.PY2: frange = bytes(frange).translate(None, ''.join(PAD_MAP.keys())) else: frange = str(frange) for key in PAD_MAP: frange = frange.replace(key, u'') if not frange: return True for part in utils.asString(frange).split(','): if not part: continue try: FrameSet._parse_frange_part(part) except ParseException: return False return True
def isFrameRange(frange): """ Return True if the given string is a frame range. Any padding characters, such as '#' and '@' are ignored. Args: frange (str): a frame range to test Returns: bool: """ # we're willing to trim padding characters from consideration # this translation is orders of magnitude faster than prior method if future.utils.PY2: frange = bytes(frange).translate(None, ''.join(PAD_MAP.keys())) else: frange = str(frange) for key in PAD_MAP: frange = frange.replace(key, '') if not frange: return True for part in utils.asString(frange).split(','): if not part: continue try: FrameSet._parse_frange_part(part) except ParseException: return False return True
def __init__(self, sequence): """ Initialize the FileSequence. :param sequence: string (ie: dir/path.1-100#.ext) :return: None """ if not hasattr(self, '_frameSet'): self._frameSet = None try: # the main case, padding characters in the path.1-100#.exr path, frames, self._pad, self._ext = SPLIT_RE.split(sequence, 1) self._dir, self._base = os.path.split(path) self._frameSet = FrameSet(frames) except ValueError: # edge case 1; we've got an invalid pad for placeholder in PAD_MAP.keys(): if placeholder in sequence: msg = "Failed to parse FileSequence: {0}" raise ParseException(msg.format(sequence)) # edge case 2; we've got a single frame of a sequence a_frame = DISK_RE.match(sequence) if a_frame: self._dir, self._base, frames, self._ext = a_frame.groups() # edge case 3: we've got a single versioned file, not a sequence if frames and not self._base.endswith('.'): self._base = self._base + frames self._pad = '' elif not frames: self._pad = '' self._frameSet = None else: self._frameSet = FrameSet(frames) if self._frameSet: self._pad = FileSequence.getPaddingChars(len(frames)) else: self._pad = '' self._frameSet = None # edge case 4; we've got a solitary file, not a sequence else: path, self._ext = os.path.splitext(sequence) self._dir, self._base = os.path.split(path) self._pad = '' if self._dir: if not self._dir.endswith(os.sep): self._dir += os.sep else: self._dir = '' self._zfill = sum([PAD_MAP[c] for c in self._pad])
def getPaddingNum(chars): """ Given a supported group of padding characters, return the amount of padding. :param chars: a supported group of padding characters (str) :return: int :raises: ValueError if unsupported padding character is detected """ try: return sum([PAD_MAP[char] for char in chars]) except KeyError: msg = "Detected an unsupported padding character: \"{}\"." msg += " Supported padding characters: {}." raise ValueError(msg.format(char, str(PAD_MAP.keys())))
def __init__(self, sequence): """Init the class """ sequence = utils.asString(sequence) if not hasattr(self, '_frameSet'): self._frameSet = None try: # the main case, padding characters in the path.1-100#.exr path, frames, self._pad, self._ext = SPLIT_RE.split( sequence, 1) self._dir, self._base = os.path.split(path) self._frameSet = FrameSet(frames) except ValueError: # edge case 1; we've got an invalid pad for placeholder in PAD_MAP.keys(): if placeholder in sequence: msg = "Failed to parse FileSequence: {0}" raise ParseException(msg.format(sequence)) # edge case 2; we've got a single frame of a sequence a_frame = DISK_RE.match(sequence) if a_frame: self._dir, self._base, frames, self._ext = a_frame.groups() # edge case 3: we've got a single versioned file, not a sequence if frames and not self._base.endswith('.'): self._base = self._base + frames self._pad = '' elif not frames: self._pad = '' self._frameSet = None else: self._frameSet = FrameSet(frames) if self._frameSet: self._pad = FileSequence.getPaddingChars( len(frames)) else: self._pad = '' self._frameSet = None # edge case 4; we've got a solitary file, not a sequence else: path, self._ext = os.path.splitext(sequence) self._dir, self._base = os.path.split(path) self._pad = '' if self._dir: self.setDirname(self._dir) self._zfill = self.__class__.getPaddingNum(self._pad)
def getPaddingNum(chars): """ Given a supported group of padding characters, return the amount of padding. :type chars: str :param chars: a supported group of padding characters :rtype: int :raises: ValueError if unsupported padding character is detected """ try: return sum([PAD_MAP[char] for char in chars]) except KeyError: msg = "Detected an unsupported padding character: \"{}\"." msg += " Supported padding characters: {}." raise ValueError(msg.format(char, str(PAD_MAP.keys())))
def getPaddingNum(chars): """ Given a supported group of padding characters, return the amount of padding. :type chars: str :param chars: a supported group of padding characters :rtype: int :raises: ValueError if unsupported padding character is detected """ match = PRINTF_SYNTAX_PADDING_RE.match(chars) if match: return int(match.group(1)) try: return sum([PAD_MAP[char] for char in chars]) except KeyError: msg = "Detected an unsupported padding character: \"{}\"." msg += " Supported padding characters: {} or printf syntax padding" msg += " %<int>d" raise ValueError(msg.format(char, str(PAD_MAP.keys())))
def isFrameRange(frange): """ Return true of the given string is a frame range. Any padding characters, such as '#' and '@' are ignored. :param frange: a frame range (str) to test :return: bool """ # we're willing to trim padding characters from consideration # this translation is orders of magnitude faster than prior method frange = str(frange).translate(None, ''.join(PAD_MAP.keys())) if not frange: return True for part in frange.split(','): if not part: continue try: FrameSet._parse_frange_part(part) except ParseException: return False return True
def isFrameRange(frange): """ Return True if the given string is a frame range. Any padding characters, such as '#' and '@' are ignored. :type frange: str :param frange: a frame range to test :rtype: bool """ # we're willing to trim padding characters from consideration # this translation is orders of magnitude faster than prior method frange = str(frange).translate(None, ''.join(PAD_MAP.keys())) if not frange: return True for part in frange.split(','): if not part: continue try: FrameSet._parse_frange_part(part) except ParseException: return False return True
def __init__(self, frange): # if the user provides anything but a string, short-circuit the build if not isinstance(frange, basestring): # if it's apparently a FrameSet already, short-circuit the build if set(dir(frange)).issuperset(self.__slots__): for attr in self.__slots__: setattr(self, attr, getattr(frange, attr)) return # if it's inherently disordered, sort and build elif isinstance(frange, Set): self._maxSizeCheck(frange) self._items = frozenset(map(int, frange)) self._order = tuple(sorted(self._items)) self._frange = FrameSet.framesToFrameRange(self._order, sort=False, compress=False) return # if it's ordered, find unique and build elif isinstance(frange, Sequence): self._maxSizeCheck(frange) items = set() order = unique(items, map(int, frange)) self._order = tuple(order) self._items = frozenset(items) self._frange = FrameSet.framesToFrameRange(self._order, sort=False, compress=False) return # in all other cases, cast to a string else: try: frange = str(frange) except Exception as err: msg = 'Could not parse "{0}": cast to string raised: {1}' raise ParseException(msg.format(frange, err)) # we're willing to trim padding characters from consideration # this translation is orders of magnitude faster than prior method self._frange = str(frange).translate(None, ''.join(PAD_MAP.keys())) # because we're acting like a set, we need to support the empty set if not self._frange: self._items = frozenset() self._order = tuple() return # build the mutable stores, then cast to immutable for storage items = set() order = [] maxSize = constants.MAX_FRAME_SIZE for part in self._frange.split(","): # this is to deal with leading / trailing commas if not part: continue # parse the partial range start, end, modifier, chunk = FrameSet._parse_frange_part(part) # handle batched frames (1-100x5) if modifier == 'x': frames = xfrange(start, end, chunk, maxSize=maxSize) frames = [f for f in frames if f not in items] self._maxSizeCheck(len(frames) + len(items)) order.extend(frames) items.update(frames) # handle staggered frames (1-100:5) elif modifier == ':': for stagger in xrange(chunk, 0, -1): frames = xfrange(start, end, stagger, maxSize=maxSize) frames = [f for f in frames if f not in items] self._maxSizeCheck(len(frames) + len(items)) order.extend(frames) items.update(frames) # handle filled frames (1-100y5) elif modifier == 'y': not_good = frozenset( xfrange(start, end, chunk, maxSize=maxSize)) frames = xfrange(start, end, 1, maxSize=maxSize) frames = (f for f in frames if f not in not_good) frames = [f for f in frames if f not in items] self._maxSizeCheck(len(frames) + len(items)) order.extend(frames) items.update(frames) # handle full ranges and single frames else: frames = xfrange(start, end, 1 if start < end else -1, maxSize=maxSize) frames = [f for f in frames if f not in items] self._maxSizeCheck(len(frames) + len(items)) order.extend(frames) items.update(frames) # lock the results into immutable internals # this allows for hashing and fast equality checking self._items = frozenset(items) self._order = tuple(order)
def __init__(self, frange): # if the user provides anything but a string, short-circuit the build if not isinstance(frange, basestring): # if it's apparently a FrameSet already, short-circuit the build if set(dir(frange)).issuperset(self.__slots__): for attr in self.__slots__: setattr(self, attr, getattr(frange, attr)) return # if it's inherently disordered, sort and build elif isinstance(frange, Set): self._items = frozenset(map(int, frange)) self._order = tuple(sorted(self._items)) self._frange = FrameSet.framesToFrameRange( self._order, sort=False, compress=False) return # if it's ordered, find unique and build elif isinstance(frange, Sequence): items = set() order = unique(items, map(int, frange)) self._order = tuple(order) self._items = frozenset(items) self._frange = FrameSet.framesToFrameRange( self._order, sort=False, compress=False) return # in all other cases, cast to a string else: try: frange = str(frange) except Exception as err: msg = 'Could not parse "{0}": cast to string raised: {1}' raise ParseException(msg.format(frange, err)) # we're willing to trim padding characters from consideration # this translation is orders of magnitude faster than prior method self._frange = str(frange).translate(None, ''.join(PAD_MAP.keys())) # because we're acting like a set, we need to support the empty set if not self._frange: self._items = frozenset() self._order = tuple() return # build the mutable stores, then cast to immutable for storage items = set() order = [] for part in self._frange.split(","): # this is to deal with leading / trailing commas if not part: continue # parse the partial range start, end, modifier, chunk = FrameSet._parse_frange_part(part) # handle batched frames (1-100x5) if modifier == 'x': frames = xfrange(start, end, chunk) frames = [f for f in frames if f not in items] order.extend(frames) items.update(frames) # handle staggered frames (1-100:5) elif modifier == ':': for stagger in xrange(chunk, 0, -1): frames = xfrange(start, end, stagger) frames = [f for f in frames if f not in items] order.extend(frames) items.update(frames) # handle filled frames (1-100y5) elif modifier == 'y': not_good = frozenset(xfrange(start, end, chunk)) frames = xfrange(start, end, 1) frames = (f for f in frames if f not in not_good) frames = [f for f in frames if f not in items] order.extend(frames) items.update(frames) # handle full ranges and single frames else: frames = xfrange(start, end, 1 if start < end else -1) frames = [f for f in frames if f not in items] order.extend(frames) items.update(frames) # lock the results into immutable internals # this allows for hashing and fast equality checking self._items = frozenset(items) self._order = tuple(order)