def testHasFrameNoVersion(self): fs = FileSequence("/path/to/file.2.exr") self.assertEquals(fs.start(), 2) self.assertEquals(fs.end(), 2) self.assertEquals(fs.padding(), '@') self.assertEquals(fs.extension(), '.exr') self.assertEquals(str(fs), "/path/to/[email protected]")
def testSlicing(self): Case = namedtuple('Case', ['input', 'slice', 'expected']) table = [ Case('file.1-10#.ext', 1, 'file.0002.ext'), Case('file.1-10#.ext', -1, 'file.0010.ext'), Case('file.1-10#.ext', slice(3, 6), FileSequence('file.4-6#.ext')), Case('file.1-10#.ext', slice(None, 5), FileSequence('file.1-5#.ext')), Case('file.1-10#.ext', slice(5, None), FileSequence('file.6-10#.ext')), Case('file.1-10#.ext', slice(-3, None), FileSequence('file.8-10#.ext')), Case('file.1-10#.ext', slice(-6, None, 2), FileSequence('file.5-9x2#.ext')), Case('file.-5-30x3#.ext', slice(3, 8, 2), FileSequence('file.4-16x6#.ext')), Case('file.-5-30x3#.ext', slice(None, None, 2), FileSequence('file.-5-25x6#.ext')), ] for case in table: fs = FileSequence(case.input) actual = fs[case.slice] self.assertEqual(case.expected, actual) fs = FileSequence('file.1-10#.ext') raises = [-20, 20, slice(11, None), slice(-200, -100)] for case in raises: with self.assertRaises(IndexError): ret = fs.__getitem__(case) raise RuntimeError("expected case %s to raise an IndexError; got %s" % (case, ret))
def testHasVersionNoFrame(self): fs = FileSequence("/path/to/file_v2.exr") self.assertEquals(fs.start(), 0) self.assertEquals(fs.end(), 0) self.assertEquals(fs.padding(), '') self.assertEquals(fs.extension(), '.exr') self.assertEquals(str(fs), "/path/to/file_v2.exr")
def test_yield_sequences_in_list_using(self): paths = [ 'seq/file_0003.0001.exr', 'seq/file_0005.0001.exr', 'seq/file_0007.0001.exr', ] expects = [os.path.join("seq", "file_3-7x2#.0001.exr")] template = FileSequence('seq/file_@@.0001.exr') actual = { str(fs) for fs in FileSequence.yield_sequences_in_list(paths, using=template) } for expect in expects: self.assertIn(expect, actual) expects = [ "seq/file_0003.1#.exr", "seq/file_0005.1#.exr", "seq/file_0007.1#.exr", ] actual = { str(fs) for fs in FileSequence.yield_sequences_in_list(paths) } for expect in expects: self.assertIn(expect, actual)
def testSetPadding(self): seq = FileSequence("/foo/[email protected]") seq.setPadding("#") self.assertEquals("/foo/bong.0001.exr", seq[0]) seq.setPadding("%02d") self.assertEquals("/foo/bong.01.exr", seq[0])
def testIgnoreFrameSetStrings(self): for char in "xy:,".split(): fs = FileSequence("/path/to/file{0}1-1x1#.exr".format(char)) self.assertEquals(fs.basename(), "file{0}".format(char)) self.assertEquals(fs.start(), 1) self.assertEquals(fs.end(), 1) self.assertEquals(fs.padding(), '#') self.assertEquals(str(fs), "/path/to/file{0}1-1x1#.exr".format(char))
def testFormat(self): seq = FileSequence("/cheech/chong.1-10,30,40#.exr") self.assertEquals("chong.0001-0010,0030,0040#.exr", str(seq.format())) self.assertEquals("0011-0029,0031-0039", seq.format("{inverted}")) seq = findSequencesOnDisk("broken_seq")[0] self.assertEquals("0000-0002,0004,0006-0008", seq.format("{range}")) self.assertEquals("broke.0000-0002,0004,0006-0008#.exr", seq.format()) seq = findSequencesOnDisk("step_seq")[0] self.assertEquals("step_seq/step1.1-13x4,14-17#.exr", str(seq))
def testFrame(self): seq = FileSequence("/foo/bar/bing.#.exr") self.assertEquals("/foo/bar/bing.0001.exr", seq.frame(1)) self.assertNativeStr(seq.frame(1)) self.assertEquals("/foo/bar/bing.#.exr", seq.frame("#")) self.assertNativeStr(seq.frame("#")) seq = FileSequence("/foo/bar/bing.%04d.exr") self.assertEquals("/foo/bar/bing.0001.exr", seq.frame(1)) self.assertEquals("/foo/bar/bing.%04d.exr", seq.frame("%04d"))
def testNoPlaceholderNumExt(self): basename = 'file' exts = ('.7zip', '.mp4') for ext in exts: expected = basename + ext seqs = FileSequence(expected) self.assertEquals(ext, seqs.extension()) self.assertEquals(basename, seqs.basename()) self.assertEquals(expected, str(seqs))
def ringSubclasses(self): sep = lambda p: p.replace("/", os.sep) tests = [ ("/path/to/files.0001.ext", sep("/path/to/"), "files."), ("/path/to/files.1-100#.ext", sep("/path/to/"), "files."), ("/path/to/files.ext", sep("/path/to/"), "files"), ("/path/to/files", sep("/path/to/"), "files"), ] for path, dirname, basename in tests: fs = FileSequence(_CustomPathString(path)) self.assertTrue(fs.dirname() == dirname, "Expected '%s', got '%s' (with %s)" % (dirname, fs.dirname(), path)) self.assertTrue(fs.basename() == basename, "Expected '%s', got '%s' (with %s)" % (basename, fs.basename(), path))
def testStringSubclasses(self): sep = lambda p: p.replace("/", os.sep) tests = [ ("/path/to/files.0001.ext", sep("/path/to/"), "files."), ("/path/to/files.1-100#.ext", sep("/path/to/"), "files."), ("/path/to/files.ext", sep("/path/to/"), "files"), ("/path/to/files", sep("/path/to/"), "files"), ] for path, dirname, basename in tests: fs = FileSequence(_CustomPathString(path)) self.assertTrue(fs.dirname() == dirname, "Expected '%s', got '%s' (with %s)" % (dirname, fs.dirname(), path)) self.assertTrue(fs.basename() == basename, "Expected '%s', got '%s' (with %s)" % (basename, fs.basename(), path))
def testSerialization(self): fs = FileSequence("/path/to/file.1-100x2#.exr") s = pickle.dumps(fs, pickle.HIGHEST_PROTOCOL) fs2 = pickle.loads(s) self.assertEquals(str(fs), str(fs2)) self.assertEquals(len(fs), len(fs2)) fs = FileSequence("/path/to/file.1-100x2%04d.exr") s = pickle.dumps(fs, pickle.HIGHEST_PROTOCOL) fs2 = pickle.loads(s) self.assertEquals(str(fs), str(fs2)) self.assertEquals(len(fs), len(fs2))
def testSetDirname(self): seq = FileSequence("/foo/[email protected]") seq.setDirname("/bing/") self.assertEquals("/bing/bong.1.exr", seq[0]) seq = FileSequence("/foo/[email protected]") seq.setDirname("bing") self.assertEquals("bing/bong.1.exr", seq[0])
def parse_clip_path_or_seq_dir_path(self, path): parts = path.parts _, _, self._volume, self._classification, self._owner, self._show, self._scene, self._element_type,\ self._reel, clip_file_or_seq_dir = parts if not self._volume.startswith('jgoldstone'): raise RuntimeError( "sequence path volume must start with jgoldstone") if self._classification not in [ 'not_secret', 'arri_secret', 'other_secret' ]: raise RuntimeError( "classification not one of 'not_secret', 'arri_secret', or 'other_secret'" ) if self._element_type not in ['ocd', 'derived', 'etc']: raise RuntimeError( "element type must be one of 'ocd', 'derived', or 'etc'") if path.suffix in ['.mov', '.mxf']: raise RuntimeError( "cannot currently directly characterize QuickTime or MXF clips" ) if path.suffix == '.ari': raise RuntimeError( "cannot currently directly characterize ARRRIAW file") elif path.suffix == '.dpx': raise RuntimeError( "cannot currently directly characterize ARRRIAW file") if not path.is_dir(): raise RuntimeError( "Only supported input for characterization is directory of ACES container files" ) sequences = FileSequence.findSequencesOnDisk(str(path)) if not len(sequences): raise RuntimeError( "The nominal directory of frames to characterize is empty") self._sequences = sequences
def testIter(self): known = { "/cheech/chong.0001.exr", "/cheech/chong.0003.exr", "/cheech/chong.0005.exr" } seq = FileSequence("/cheech/chong.1,3,5#.exr") self.assertFalse(known.difference(seq))
def testEmptyBasename(self): seq = FileSequence("/path/to/1-5#.exr") self.assertEquals(seq.basename(), "") self.assertEquals(len(seq), 5) self.assertEquals(seq.padding(), '#') seq = FileSequence("/path/to/1-5%04d.exr") self.assertEquals(seq.basename(), "") self.assertEquals(len(seq), 5) self.assertEquals(seq.padding(), '%04d')
def testSeqGettersType2(self): seq = FileSequence("/foo/boo1-5#.exr") self.assertEquals(5, len(seq)) self.assertEquals("/foo/", seq.dirname()) self.assertEquals("boo", seq.basename()) self.assertEquals("#", seq.padding()) self.assertEquals(".exr", seq.extension()) self.assertEquals("/foo/boo9999.exr", seq.frame(9999)) self.assertEquals("/foo/boo0001.exr", seq[0]) self.assertEquals("/foo/boo0001.exr", seq.index(0))
def testSeqGettersPrintf(self): seq = FileSequence("/foo/boo.1-5%04d.exr") self.assertEquals(5, len(seq)) self.assertEquals("/foo/", seq.dirname()) self.assertEquals("boo.", seq.basename()) self.assertEquals("%04d", seq.padding()) self.assertEquals(".exr", seq.extension()) self.assertEquals("/foo/boo.9999.exr", seq.frame(9999)) self.assertEquals("/foo/boo.0001.exr", seq[0]) self.assertEquals("/foo/boo.0001.exr", seq.index(0))
def testSeqGettersHoudini(self): seq = FileSequence("/foo/boo.1-5$F.exr") self.assertEquals(5, len(seq)) self.assertEquals("/foo/", seq.dirname()) self.assertEquals("boo.", seq.basename()) self.assertEquals("$F", seq.padding()) self.assertEquals(".exr", seq.extension()) self.assertEquals("/foo/boo.9999.exr", seq.frame(9999)) self.assertEquals("/foo/boo.1.exr", seq[0]) self.assertEquals("/foo/boo.1.exr", seq.index(0))
def testFilterByPaddingNum(self): tests = [ (['file.1.ext'], 1, ['file.1.ext']), (['file.1.ext'], 2, []), ] for test in tests: source, pad, expected = test actual = list(FileSequence._filterByPaddingNum(source, pad)) self.assertEqual(actual, expected)
def testFormat(self): seq = FileSequence("/cheech/chong.1-10,30,40#.exr") self.assertEquals("chong.0001-0010,0030,0040#.exr", str(seq.format())) self.assertNativeStr(seq.format()) self.assertEquals("0011-0029,0031-0039", seq.format("{inverted}")) self.assertNativeStr(seq.format("{inverted}")) seq = findSequencesOnDisk("broken_seq")[0] self.assertEquals("0000-0002,0004,0006-0008", seq.format("{range}")) self.assertEquals("broke.0000-0002,0004,0006-0008#.exr", seq.format()) seq = findSequencesOnDisk("step_seq")[0] self.assertEquals("step_seq/step1.1-13x4,14-17#.exr", str(seq))
def testFormatInverted(self): _maxSize = constants.MAX_FRAME_SIZE try: maxSize = constants.MAX_FRAME_SIZE = 500 # Test catching error for large inverted range seq = FileSequence("/path/to/file.1,%d#.ext" % (constants.MAX_FRAME_SIZE+3)) self.assertRaises(exceptions.MaxSizeException, seq.format, '{inverted}') finally: constants.MAX_FRAME_SIZE = _maxSize
def _get_seq(self, path): """ Crate file sequence object by given a file sequence path such as /path/image.%04d.dpx :param path: (str) File sequence path :returns: File Sequence object """ s = re.sub(r'%[0-9]+d', '#', path) seq = FileSequence.findSequencesOnDisk(os.path.dirname(s))[0] return seq
def testFrame(self): seq = FileSequence("/foo/bar/bing.#.exr") self.assertEquals("/foo/bar/bing.0001.exr", seq.frame(1)) self.assertEquals("/foo/bar/bing.#.exr", seq.frame("#")) seq = FileSequence("/foo/bar/bing.%04d.exr") self.assertEquals("/foo/bar/bing.0001.exr", seq.frame(1)) self.assertEquals("/foo/bar/bing.%04d.exr", seq.frame("%04d"))
def testConformPadding(self): """ Ensure that alternate padding formats are conformed to a primary PAD_MAP format """ class Case(object): def __init__(self, src, expected, error=False): self.src = src self.expected = expected self.error = error tests = [ Case('#', '#',), Case('#@', '#@'), Case('@@@@', '@@@@'), Case('@@@', '@@@'), Case('@@', '@@'), Case('@', '@'), Case('%08d', '##'), Case('%05d', '@@@@@'), Case('%04d', '#'), Case('%03d', '@@@'), Case('%02d', '@@'), Case('%01d', '@'), Case('', ''), Case('foo', 'foo', error=True), ] for case in tests: if case.error: with self.assertRaises(ValueError): FileSequence.conformPadding(case.src) continue actual = FileSequence.conformPadding(case.src) self.assertEqual(actual, case.expected)
def testSetBasename(self): seq = FileSequence("/foo/[email protected]") seq.setBasename("bar.") self.assertEquals("/foo/bar.1.exr", seq[0])
def testNoFrameNoVersionNoExt(self): fs = FileSequence("/path/to/file") self.assertEquals(fs.start(), 0) self.assertEquals(fs.end(), 0) self.assertEquals(fs.padding(), '') self.assertEquals(fs.dirname(), '/path/to/') self.assertEquals(fs.basename(), 'file') self.assertEquals(fs.extension(), '') self.assertEquals(str(fs), "/path/to/file") fs = FileSequence("file") self.assertEquals(fs.start(), 0) self.assertEquals(fs.end(), 0) self.assertEquals(fs.padding(), '') self.assertEquals(fs.dirname(), '') self.assertEquals(fs.basename(), 'file') self.assertEquals(fs.extension(), '') self.assertEquals(str(fs), "file")
def testNumericFilename(self): seqs = FileSequence("/path/to/1-10#.exr") self.assertEquals("/path/to/0001.exr", seqs.index(0)) seqs = FileSequence("/path/to/1-10%04d.exr") self.assertEquals("/path/to/0001.exr", seqs.index(0))
def test_yield_sequences_in_list(self): paths = [ '/path/to/file20.v123.5.png', '/path/to/file20.v123.1.exr', '/path/to/file20.v123.2.exr', '/path/to/file20.v123.3.exr', '/path/to/.cruft.file', '/path/to/.cruft', '/path/to/file2.exr', '/path/to/file2.7zip', '/path/to/file.2.7zip', '/path/to/file.3.7zip', '/path/to/file.4.7zip', '/path/to/file.4.mp4', '', # empty path test "mixed_seqs/file5.ext", "mixed_seqs/file20.ext", "mixed_seqs/file30.ext", "mixed_seqs/no_ext", "mixed_seqs/no_ext.200,300@@@", "mixed_seqs/no_ext_10", "mixed_seqs/not_a_seq.ext", "mixed_seqs/seq.0001.ext", "mixed_seqs/seq.0002.ext", "mixed_seqs/seq.0003.ext", "mixed_seqs/seq2a.1.ext", "mixed_seqs/seq2a.2.ext", "mixed_seqs/seq2a.3.ext", "/path/to/file4-4.exr", "/path/to/file4-5.exr", "/path/to/file--4.exr", "path/01.exr", "path/02.exr", "path/03.exr", "path/001.file", "path/002.file", "path/003.file", "path/0001.jpg", "path/0002.jpg", "path/0003.jpg", "2frames.01.jpg", "2frames.02.jpg", '8frames.01.jpg', '8frames.02.jpg', '8frames.05.jpg', '8frames.07.jpg', '8frames.08.jpg', '8frames.10.jpg', '8frames.11.jpg', ] expected = { '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/.cruft.file', '/path/to/.cruft', '/path/to/[email protected]', "mixed_seqs/file5,20,[email protected]", "mixed_seqs/[email protected]", "mixed_seqs/seq.1-3#.ext", "mixed_seqs/not_a_seq.ext", "mixed_seqs/no_ext", "mixed_seqs/no_ext_10@@", "mixed_seqs/no_ext.200,300@@@", '/path/to/file4-5--4@@.exr', '/path/to/file--4@@.exr', 'path/1-3@@.exr', 'path/1-3@@@.file', 'path/1-3#.jpg', '2frames.1-2@@.jpg', '8frames.1-2,5,7-8,10-11@@.jpg', } actual = set(str(fs) for fs in FileSequence.yield_sequences_in_list(paths)) self.assertEquals(actual, expected) paths = imap(_CustomPathString, paths) actual = set(str(fs) for fs in FileSequence.yield_sequences_in_list(paths)) self.assertEquals(actual, {str(_CustomPathString(p)) for p in expected})
def testSplitXY(self): seqs = FileSequence("/cheech/0-9x1/chong.1-10#.exr") self.assertEquals("/cheech/0-9x1/chong.0001.exr", seqs.index(0))
def testNoPlaceholder(self): expected = "/path/to/file.mov" seqs = FileSequence(expected) self.assertEquals(expected, seqs.index(0)) self.assertEquals(expected, seqs.frame(0)) self.assertEquals(expected, seqs[0]) self.assertEquals(None, seqs.frameSet()) self.assertEquals("", seqs.frameRange()) self.assertEquals("", seqs.invertedFrameRange()) self.assertEquals(1, len(seqs)) seqs.setFrameRange("1-100") for i in range(0, 100): self.assertEquals(expected, seqs.index(i)) self.assertEquals(expected, seqs.frame(i + 1)) self.assertEquals(expected, seqs[i]) self.assertEquals(1, len(seqs)) seqs.setPadding("#") self.assertEquals(100, len(seqs))
def testSplit(self): seqs = FileSequence("/cheech/chong.1-10,30,40#.exr").split() self.assertEquals("/cheech/chong.0001-0010#.exr", str(seqs[0])) self.assertEquals("/cheech/chong.0030#.exr", str(seqs[1])) self.assertEquals("/cheech/chong.0040#.exr", str(seqs[2]))
def testMissingPeriods(self): seqs = FileSequence("/path/to/something_1-10#_exr") self.assertEquals("/path/to/something_0001_exr", seqs.index(0)) seqs = FileSequence("/path/to/something_1-10%04d_exr") self.assertEquals("/path/to/something_0001_exr", seqs.index(0))
def testSetFrameRange(self): seq = FileSequence("/cheech/chong.1-5#.exr") seq.setFrameRange("10-20") self.assertEquals("/cheech/chong.10-20#.exr", str(seq))
def _test_yield_sequences_in_list(self, sep='/'): paths = [ '/path/to/file20.v123.5.png', '/path/to/file20.v123.1.exr', '/path/to/file20.v123.2.exr', '/path/to/file20.v123.3.exr', '/path/to/.cruft.file', '/path/to/.cruft', '/path/to/file2.exr', '/path/to/file2.7zip', '/path/to/file.2.7zip', '/path/to/file.3.7zip', '/path/to/file.4.7zip', '/path/to/file.4.mp4', '', # empty path test "mixed_seqs/file5.ext", "mixed_seqs/file20.ext", "mixed_seqs/file30.ext", "mixed_seqs/no_ext", "mixed_seqs/no_ext.200,300@@@", "mixed_seqs/no_ext_10", "mixed_seqs/not_a_seq.ext", "mixed_seqs/seq.0001.ext", "mixed_seqs/seq.0002.ext", "mixed_seqs/seq.0003.ext", "mixed_seqs/seq2a.1.ext", "mixed_seqs/seq2a.2.ext", "mixed_seqs/seq2a.3.ext", "/path/to/file4-4.exr", "/path/to/file4-5.exr", "/path/to/file--4.exr", "path/01.exr", "path/02.exr", "path/03.exr", "path/001.file", "path/002.file", "path/003.file", "path/0001.jpg", "path/0002.jpg", "path/0003.jpg", "2frames.01.jpg", "2frames.02.jpg", '8frames.01.jpg', '8frames.02.jpg', '8frames.05.jpg', '8frames.07.jpg', '8frames.08.jpg', '8frames.10.jpg', '8frames.11.jpg', ] expected = { '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/[email protected]', '/path/to/.cruft.file', '/path/to/.cruft', '/path/to/[email protected]', "mixed_seqs/file5,20,[email protected]", "mixed_seqs/[email protected]", "mixed_seqs/seq.1-3#.ext", "mixed_seqs/not_a_seq.ext", "mixed_seqs/no_ext", "mixed_seqs/no_ext_10@@", "mixed_seqs/no_ext.200,300@@@", '/path/to/file4-5--4@@.exr', '/path/to/file--4@@.exr', 'path/1-3@@.exr', 'path/1-3@@@.file', 'path/1-3#.jpg', '2frames.1-2@@.jpg', '8frames.1-2,5,7-8,10-11@@.jpg', } sub = self.RX_PATHSEP.sub paths = [sub(sep, p) for p in paths] expected = {sub(sep, p) for p in expected} actual = set( str(fs) for fs in FileSequence.yield_sequences_in_list(paths)) self.assertEquals(expected, actual) paths = list(map(_CustomPathString, paths)) actual = set( str(fs) for fs in FileSequence.yield_sequences_in_list(paths)) self.assertEquals({str(_CustomPathString(p)) for p in expected}, actual)
def testNoPlaceholder(self): expected = "/path/to/file.mov" seqs = FileSequence(expected) self.assertEquals(expected, seqs.index(0)) self.assertEquals(expected, seqs.frame(0)) self.assertEquals(expected, seqs[0]) self.assertEquals(None, seqs.frameSet()) self.assertEquals("", seqs.frameRange()) self.assertEquals("", seqs.invertedFrameRange()) self.assertEquals(1, len(seqs)) seqs.setFrameRange("1-100") for i in xrange(0,100): self.assertEquals(expected, seqs.index(i)) self.assertEquals(expected, seqs.frame(i+1)) self.assertEquals(expected, seqs[i]) self.assertEquals(1, len(seqs)) seqs.setPadding("#") self.assertEquals(100, len(seqs))