Exemple #1
0
    def findSequenceOnDisk(pattern):
        """
        Search for a specific sequence on disk.

        :Example:
            >>> findSequenceOnDisk("seq/bar#.exr") # or any fileseq pattern

        :param pattern: the sequence pattern being searched for
        :rtype: str
        :raises: :class:`fileseq.exceptions.FileSeqException` if no sequence is found on disk
        """
        seq = FileSequence(pattern)

        if seq.frameRange() == '' and seq.padding() == '':
            if os.path.isfile(pattern):
                return seq

        patt = seq.format('{dirname}{basename}*{extension}')

        ext = seq.extension()
        basename = seq.basename()

        matches = FileSequence.yield_sequences_in_list(iglob(patt))
        for match in matches:
            if match.basename() == basename and match.extension() == ext:
                return match

        msg = 'no sequence found on disk matching {0}'
        raise FileSeqException(msg.format(pattern))
Exemple #2
0
    def findSequenceOnDisk(cls, pattern, strictPadding=False):
        """
        Search for a specific sequence on disk.

        The padding characters used in the `pattern` are used to filter the
        frame values of the files on disk (if `strictPadding` is True).

        Examples:
            Find sequence matching basename and extension, and a wildcard for
            any frame.
            returns bar.1.exr bar.10.exr, bar.100.exr, bar.1000.exr, inclusive

            >>> findSequenceOnDisk("seq/bar@@@@.exr")

            Find exactly 4-padded sequence, i.e. seq/bar1-100#.exr
            returns only frames bar1000.exr through bar9999.exr

            >>> findSequenceOnDisk("seq/bar#.exr", strictPadding=True)

        Args:
            pattern (str): the sequence pattern being searched for
            strictPadding (bool): if True, ignore files with padding length different from `pattern`

        Returns:
            str:

        Raises:
            :class:`.FileSeqException`: if no sequence is found on disk
        """
        seq = cls(pattern)

        if seq.frameRange() == '' and seq.padding() == '':
            if os.path.isfile(pattern):
                return seq

        patt = seq.format('{dirname}{basename}*{extension}')

        ext = seq.extension()
        basename = seq.basename()
        pad = seq.padding()

        globbed = iglob(patt)
        if pad and strictPadding:
            globbed = cls._filterByPaddingNum(globbed, seq.zfill())
            pad = cls.conformPadding(pad)

        matches = cls.yield_sequences_in_list(globbed)
        for match in matches:
            if match.basename() == basename and match.extension() == ext:
                if pad and strictPadding:
                    match.setPadding(pad)
                return match

        msg = 'no sequence found on disk matching {0}'
        raise FileSeqException(msg.format(pattern))
Exemple #3
0
    def getPaddingChars(cls, num, pad_style=PAD_STYLE_DEFAULT):
        """
        Given a particular amount of padding, return the proper padding characters.

        Args:
            num (int): required width of string with padding
            pad_style (`.PAD_STYLE_DEFAULT` or `.PAD_STYLE_HASH1` or `.PAD_STYLE_HASH4`): padding style

        Returns:
            str:
        """
        num = max(1, num)
        reverse_pad_map = cls.REVERSE_PAD_MAP[pad_style]

        # Find the widest padding character that can be used alone
        for width in sorted(reverse_pad_map, reverse=True):
            if num % width == 0:
                return reverse_pad_map[width] * (num // width)

        # Should never reach here as all styles should have an entry for width 1
        raise FileSeqException('REVERSE_PAD_MAP missing pad character for width 1')
Exemple #4
0
    def findSequencesOnDisk(cls,
                            pattern,
                            include_hidden=False,
                            strictPadding=False,
                            pad_style=PAD_STYLE_DEFAULT,
                            allow_subframes=False):
        """
        Yield the sequences found in the given directory.

        Examples::

            FileSequence.findSequencesOnDisk('/path/to/files')

        The `pattern` can also specify glob-like shell wildcards including the following:
            * ``?``         - 1 wildcard character
            * ``*``         - 1 or more wildcard character
            * ``{foo,bar}`` - either 'foo' or 'bar'

        Exact frame ranges are not considered, and padding characters are converted to
        wildcards (``#`` or ``@``)

        Examples::

            FileSequence.findSequencesOnDisk('/path/to/files/image_stereo_{left,right}.#.jpg')
            FileSequence.findSequencesOnDisk('/path/to/files/imag?_*_{left,right}.@@@.jpg', strictPadding=True)

        Args:
            pattern (str): directory to scan, or pattern to filter in directory
            include_hidden (bool): if true, show .hidden files as well
            strictPadding (bool): if True, ignore files with padding length different from pattern
            pad_style (`.PAD_STYLE_DEFAULT` or `.PAD_STYLE_HASH1` or `.PAD_STYLE_HASH4`): padding style
            allow_subframes (bool): if True, handle subframe filenames

        Returns:
            list:
        """
        # reserve some functions we're going to need quick access to
        _not_hidden = lambda f: not f.startswith('.')
        _match_pattern = None
        _filter_padding = None
        _join = os.path.join

        seq = None
        dirpath = pattern

        # Support the pattern defining a filter for the files
        # in the existing directory
        if not os.path.isdir(pattern):
            dirpath, filepat = os.path.split(pattern)

            if not os.path.isdir(dirpath):
                return []

            # Start building a regex for filtering files
            seq = cls(filepat,
                      pad_style=pad_style,
                      allow_subframes=allow_subframes)
            patt = r'\A'
            patt += cls._globCharsToRegex(seq.basename())
            if seq.padding():
                patt += '('
                if seq.framePadding():
                    patt += r'\d+'
                    if seq.subframePadding():
                        patt += r'\.\d+'
                patt += ')'
            if seq.extension():
                patt += cls._globCharsToRegex(seq.extension())

            # Convert braces groups into regex capture groups
            matches = re.finditer(r'{(.*?)(?:,(.*?))*}', patt)
            for match in reversed(list(matches)):
                i, j = match.span()
                regex = '(?:%s)' % '|'.join(
                    [m.strip() for m in match.groups()])
                patt = "".join((patt[0:i], regex, patt[j:]))
            patt += r'\Z'
            try:
                _match_pattern = re.compile(patt).match
            except re.error:
                msg = 'Invalid file pattern: {!r}'.format(filepat)
                raise FileSeqException(msg)

            if seq.padding() and strictPadding:
                get_frame = lambda f: _match_pattern(f).group(1)
                _filter_padding = functools.partial(
                    cls._filterByPaddingNum,
                    zfill=seq.zfill(),
                    decimal_places=seq.decimalPlaces(),
                    get_frame=get_frame)

        # Get just the immediate files under the dir.
        # Avoids testing the os.listdir() for files as
        # a second step.
        ret = next(os.walk(dirpath), None)
        files = ret[-1] if ret else []

        # collapse some generators to get us the files that match our regex
        if not include_hidden:
            files = filter(_not_hidden, files)

        # Filter by files that match the provided file pattern
        if _match_pattern:
            files = filter(_match_pattern, files)

        # Filter by files that match the frame padding in the file pattern
        if _filter_padding:
            # returns a generator
            files = _filter_padding(files)

        # Ensure our dirpath ends with a path separator, so
        # that we can control which sep is used during the
        # os.path.join
        sep = utils._getPathSep(dirpath)
        if not dirpath.endswith(sep):
            dirpath += sep

        files = [_join(dirpath, f) for f in files]

        seqs = list(
            cls.yield_sequences_in_list(files,
                                        pad_style=pad_style,
                                        allow_subframes=allow_subframes))

        if _filter_padding and seq:
            frame_pad = cls.conformPadding(seq.framePadding(),
                                           pad_style=pad_style)
            subframe_pad = cls.conformPadding(seq.subframePadding(),
                                              pad_style=pad_style)
            # strict padding should preserve the original padding
            # characters in the found sequences.
            for s in seqs:
                s.setFramePadding(frame_pad)
                s.setSubframePadding(subframe_pad)

        return seqs
Exemple #5
0
    def findSequenceOnDisk(cls,
                           pattern,
                           strictPadding=False,
                           pad_style=PAD_STYLE_DEFAULT,
                           allow_subframes=False):
        """
        Search for a specific sequence on disk.

        The padding characters used in the `pattern` are used to filter the
        frame values of the files on disk (if `strictPadding` is True).

        Examples:
            Find sequence matching basename and extension, and a wildcard for
            any frame.
            returns bar.1.exr bar.10.exr, bar.100.exr, bar.1000.exr, inclusive

            ``FileSequence.findSequenceOnDisk("seq/bar@@@@.exr")``

            Find exactly 4-padded sequence, i.e. seq/bar1-100#.exr
            returns only frames bar1000.exr through bar9999.exr

            ``FileSequence.findSequenceOnDisk("seq/bar#.exr", strictPadding=True)``

        Args:
            pattern (str): the sequence pattern being searched for
            strictPadding (bool): if True, ignore files with padding length different from `pattern`
            pad_style (`.PAD_STYLE_DEFAULT` or `.PAD_STYLE_HASH1` or `.PAD_STYLE_HASH4`): padding style
            allow_subframes (bool): if True, handle subframe filenames

        Returns:
            str:

        Raises:
            :class:`.FileSeqException`: if no sequence is found on disk
        """
        seq = cls(pattern,
                  allow_subframes=allow_subframes,
                  pad_style=pad_style)

        if seq.frameRange() == '' and seq.padding() == '':
            if os.path.isfile(pattern):
                return seq

        patt = seq.format('{dirname}{basename}*{extension}')

        dirname = seq.dirname()
        basename = seq.basename()
        ext = seq.extension()
        pad = seq.padding()
        frame_pad = seq.framePadding()
        subframe_pad = seq.subframePadding()

        globbed = iglob(patt)
        if pad:
            patt = r'\A'
            if dirname:
                patt = r'.*[/\\]'
            patt += re.escape(basename) + '(.*)' + re.escape(ext) + r'\Z'
            get_frame = lambda f: re.match(patt, f).group(1)

            if strictPadding:
                globbed = cls._filterByPaddingNum(
                    globbed,
                    seq.zfill(),
                    decimal_places=seq.decimalPlaces(),
                    get_frame=get_frame)
                frame_pad = cls.conformPadding(frame_pad, pad_style=pad_style)
                subframe_pad = cls.conformPadding(subframe_pad,
                                                  pad_style=pad_style)
            else:
                globbed = cls._filterByPaddingNum(
                    globbed,
                    None,
                    decimal_places=seq.decimalPlaces(),
                    get_frame=get_frame)

        sequences = []
        allow_subframes = bool(seq.decimalPlaces())
        for match in cls.yield_sequences_in_list(
                globbed,
                using=seq,
                pad_style=pad_style,
                allow_subframes=allow_subframes):
            if match.basename() == basename and match.extension() == ext:
                if pad and strictPadding:
                    match.setFramePadding(frame_pad)
                    match.setSubframePadding(subframe_pad)
                sequences.append(match)

        if len(sequences) == 1:
            return sequences[0]
        elif not sequences:
            msg = 'no sequence found on disk matching {0}'
        else:
            msg = 'multiple sequences found on disk matching {0}'
        raise FileSeqException(msg.format(pattern))
Exemple #6
0
    def findSequencesOnDisk(cls,
                            pattern,
                            include_hidden=False,
                            strictPadding=False):
        """
        Yield the sequences found in the given directory.

        Example::
            findSequencesOnDisk('/path/to/files')

        The pattern can also specify glob-like shell wildcards including the following:
            ?         - 1 wildcard character
            *         - 1 or more wildcard character
            {foo,bar} - either 'foo' or 'bar'

        Exact frame ranges are not considered, and padding characters are converted to
        wildcards (# or @)

        Example::
            findSequencesOnDisk('/path/to/files/image_stereo_{left,right}.#.jpg')
            findSequencesOnDisk('/path/to/files/imag?_*_{left,right}.@@@.jpg', strictPadding=True)

        :param pattern: directory to scan, or pattern to filter in directory
        :type include_hidden: bool
        :param include_hidden: if true, show .hidden files as well
        :type strictPadding: bool
        :param strictPadding: if True, ignore files with padding length different from pattern
        :rtype: list
        """
        # reserve some functions we're going to need quick access to
        _not_hidden = lambda f: not f.startswith('.')
        _match_pattern = None
        _filter_padding = None
        _join = os.path.join

        dirpath, filepat = pattern, None

        # Support the pattern defining a filter for the files
        # in the existing directory
        if not os.path.isdir(pattern):
            dirpath, filepat = os.path.split(pattern)

            if not os.path.isdir(dirpath):
                return []

            # Start building a regex for filtering files
            seq = cls(filepat)
            patt = seq.basename().replace('.', r'\.')
            if seq.padding():
                patt += '\d+'
            if seq.extension():
                patt += seq.extension()

            # Convert braces groups into regex capture groups
            view = bytearray(patt)
            matches = re.finditer(r'{(.*?)(?:,(.*?))*}', patt)
            for match in reversed(list(matches)):
                i, j = match.span()
                view[i:j] = '(%s)' % '|'.join(
                    [m.strip() for m in match.groups()])
            view = view.replace('*', '.*')
            view = view.replace('?', '.')
            view += '$'
            print(view)
            try:
                _match_pattern = re.compile(str(view)).match
            except re.error:
                msg = 'Invalid file pattern: {}'.format(filepat)
                raise FileSeqException(msg)

            if seq.padding() and strictPadding:
                _filter_padding = functools.partial(cls._filterByPaddingNum,
                                                    num=seq.zfill())

        # Get just the immediate files under the dir.
        # Avoids testing the os.listdir() for files as
        # a second step.
        ret = next(os.walk(dirpath), None)
        files = ret[-1] if ret else []

        # collapse some generators to get us the files that match our regex
        if not include_hidden:
            files = filter(_not_hidden, files)

        # Filter by files that match the provided file pattern
        if _match_pattern:
            files = filter(_match_pattern, files)

        # Filter by files that match the frame padding in the file pattern
        if _filter_padding:
            # returns a generator
            files = _filter_padding(files)

        # Ensure our dirpath ends with a path separator, so
        # that we can control which sep is used during the
        # os.path.join
        sep = utils._getPathSep(dirpath)
        if not dirpath.endswith(sep):
            dirpath += sep

        files = (_join(dirpath, f) for f in files)
        files = list(files)

        return list(FileSequence.yield_sequences_in_list(files))