def invertedFrameRange(self, zfill=0, decimal_places=None): """ Return the inverse of the :class:`FrameSet` 's frame range, padded if desired. The inverse is every frame within the full extent of the range. Examples: >>> FrameSet('1-100x2').invertedFrameRange() '2-98x2' >>> FrameSet('1-100x2').invertedFrameRange(5) '00002-00098x2' If the inverted frame size exceeds ``fileseq.constants.MAX_FRAME_SIZE``, a ``MaxSizeException`` will be raised. Args: zfill (int): the width to use to zero-pad the frame range string decimal_places (int or None): the number of decimal places to use in frame range string Returns: str: Raises: :class:`fileseq.exceptions.MaxSizeException`: """ # No inverted frame range when range includes subframes for frame in self.items: if not isinstance(frame, futils.integer_types): return '' result = [] frames = sorted(self.items) for idx, frame in enumerate(frames[:-1]): next_frame = frames[idx + 1] if next_frame - frame != 1: r = range(frame + 1, next_frame) # Check if the next update to the result set # will exceed out max frame size. # Prevent memory overflows. self._maxSizeCheck(len(r) + len(result)) result += r if not result: return '' return self.framesToFrameRange( result, zfill=zfill, sort=False, compress=False)
def invertedFrameRange(self, zfill=0): """ Return the inverse of the :class:`FrameSet` 's frame range, padded if desired. The inverse is every frame within the full extent of the range. Examples: >>> FrameSet('1-100x2').invertedFrameRange() '2-98x2' >>> FrameSet('1-100x2').invertedFrameRange(5) '00002-00098x2' If the inverted frame size exceeds `fileseq.constants.MAX_FRAME_SIZE`, a ``MaxSizeException`` will be raised. Args: zfill (int): the width to use to zero-pad the frame range string Returns: str: Raises: :class:`fileseq.exceptions.MaxSizeException`: """ result = [] frames = sorted(self.items) for idx, frame in enumerate(frames[:-1]): next_frame = frames[idx + 1] if next_frame - frame != 1: r = range(frame + 1, next_frame) # Check if the next update to the result set # will exceed out max frame size. # Prevent memory overflows. self._maxSizeCheck(len(r) + len(result)) result += r if not result: return u'' return FrameSet.framesToFrameRange( result, zfill=zfill, sort=False, compress=False)
def invertedFrameRange(self, zfill=0): """ Return the inverse of the :class:`FrameSet` 's frame range, padded if desired. The inverse is every frame within the full extent of the range. :Example: >>> FrameSet('1-100x2').invertedFrameRange() '2-98x2' >>> FrameSet('1-100x2').invertedFrameRange(5) '00002-00098x2' If the inverted frame size exceeds `fileseq.constants.MAX_FRAME_SIZE`, a ``MaxSizeException`` will be raised. :type zfill: int :param zfill: the width to use to zero-pad the frame range string :rtype: str :raises: :class:`fileseq.exceptions.MaxSizeException` """ result = [] frames = sorted(self.items) for idx, frame in enumerate(frames[:-1]): next_frame = frames[idx + 1] if next_frame - frame != 1: r = range(frame + 1, next_frame) # Check if the next update to the result set # will exceed out max frame size. # Prevent memory overflows. self._maxSizeCheck(len(r) + len(result)) result += r if not result: return '' return FrameSet.framesToFrameRange(result, zfill=zfill, sort=False, compress=False)
def __init__(self, frange): """Initialize the :class:`FrameSet` object. """ # if the user provides anything but a string, short-circuit the build if not isinstance(frange, futils.string_types): # 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(normalizeFrames(frange)) self._order = tuple(sorted(self._items)) self._frange = self.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, normalizeFrames(frange)) self._order = tuple(order) self._items = frozenset(items) self._frange = self.framesToFrameRange( self._order, sort=False, compress=False) return # if it's an individual number build directly elif isinstance(frange, futils.integer_types + (float, decimal.Decimal)): frame = normalizeFrame(frange) self._order = (frame, ) self._items = frozenset([frame]) self._frange = self.framesToFrameRange( self._order, sort=False, compress=False) # in all other cases, cast to a string else: try: frange = asString(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 if futils.PY2: frange = bytes(frange).translate(None, ''.join(self.PAD_MAP.keys())) self._frange = asString(frange) else: frange = str(frange) for key in self.PAD_MAP: frange = frange.replace(key, '') self._frange = asString(frange) # 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 frange_parts = [] frange_types = [] 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 = self._parse_frange_part(part) frange_parts.append((start, end, modifier, chunk)) frange_types.extend(map(type, (start, end, chunk))) # Determine best type for numbers in range. Note that # _parse_frange_part will always return decimal.Decimal for subframes FrameType = int if decimal.Decimal in frange_types: FrameType = decimal.Decimal for start, end, modifier, chunk in frange_parts: # handle batched frames (1-100x5) if modifier == 'x': frames = xfrange(start, end, chunk, maxSize=maxSize) frames = [FrameType(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 == ':': if '.' in futils.native_str(chunk): raise ValueError("Unable to stagger subframes") for stagger in range(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': if '.' in futils.native_str(chunk): raise ValueError("Unable to fill subframes") 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 = [FrameType(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): """Initialize the :class:`FrameSet` object. """ # if the user provides anything but a string, short-circuit the build if not isinstance(frange, future.utils.string_types): # 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 = utils.asString(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 if future.utils.PY2: frange = bytes(frange).translate(None, ''.join(PAD_MAP.keys())) self._frange = utils.asString(frange) else: frange = str(frange) for key in PAD_MAP: frange = frange.replace(key, u'') self._frange = utils.asString(frange) # 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 range(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, str): # 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( str.maketrans('', '', ''.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 range(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)