From e2123f8090c59a43dc4a8d989ce82cb049726a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sybren=20A=2E=20St=C3=BCvel?= Date: Tue, 6 Mar 2018 16:41:16 +0100 Subject: [PATCH] Path rewriting for sequences seems to be working too. --- blender_asset_tracer/pack/__init__.py | 35 ++++++++++++++++---- blender_asset_tracer/tracer/blocks2assets.py | 2 +- blender_asset_tracer/tracer/file_sequence.py | 8 ++--- blender_asset_tracer/tracer/result.py | 12 +++++-- tests/test_tracer.py | 27 +++++++-------- tests/test_tracer_file_sequence.py | 6 ---- 6 files changed, 56 insertions(+), 34 deletions(-) diff --git a/blender_asset_tracer/pack/__init__.py b/blender_asset_tracer/pack/__init__.py index 0d8b824..62557e8 100644 --- a/blender_asset_tracer/pack/__init__.py +++ b/blender_asset_tracer/pack/__init__.py @@ -173,10 +173,23 @@ class Packer: # Find the same block in the newly copied file. block = bfile.dereference_pointer(usage.block.addr_old) - log.info(' - updating field %s of block %s', - usage.path_full_field.name.name_only, block) - written = block.set(usage.path_full_field.name.name_only, relpath) - log.info(' - written %d bytes', written) + if usage.path_full_field is None: + log.info(' - updating field %s of block %s', + usage.path_dir_field.name.name_only, block) + reldir = bpathlib.BlendPath.mkrelative(asset_pp.parent, bfile_pp) + written = block.set(usage.path_dir_field.name.name_only, reldir) + log.info(' - written %d bytes', written) + + # BIG FAT ASSUMPTION that the filename (e.g. basename + # without path) does not change. This makes things much + # easier, as in the sequence editor the directory and + # filename fields are in different blocks. See the + # blocks2assets.scene() function for the implementation. + else: + log.info(' - updating field %s of block %s', + usage.path_full_field.name.name_only, block) + written = block.set(usage.path_full_field.name.name_only, relpath) + log.info(' - written %d bytes', written) bfile.fileobj.flush() def _copy_asset_and_deps(self, asset_path: pathlib.Path, action: AssetAction): @@ -188,9 +201,19 @@ class Packer: # Copy its dependencies. for usage in action.usages: + if not usage.is_sequence: + self._copy_to_target(usage.abspath, packed_path) + continue + + first_pp = self._packed_paths[usage.abspath] + + # In case of globbing, we only support globbing by filename, + # and not by directory. + assert '*' not in str(first_pp) or '*' in first_pp.name + + packed_base_dir = first_pp.parent for file_path in usage.files(): - # TODO(Sybren): handle sequences properly! - packed_path = self._packed_paths[file_path] + packed_path = packed_base_dir / file_path.name self._copy_to_target(file_path, packed_path) def _copy_to_target(self, asset_path: pathlib.Path, target: pathlib.Path): diff --git a/blender_asset_tracer/tracer/blocks2assets.py b/blender_asset_tracer/tracer/blocks2assets.py index d537c24..f9a4fde 100644 --- a/blender_asset_tracer/tracer/blocks2assets.py +++ b/blender_asset_tracer/tracer/blocks2assets.py @@ -156,7 +156,7 @@ def scene(block: blendfile.BlendFileBlock) -> typing.Iterator[result.BlockUsage] asset_path = bpathlib.BlendPath(dirname) / basename is_sequence = seq_type not in single_asset_types - yield result.BlockUsage(seq, asset_path, + yield result.BlockUsage(seq_strip, asset_path, is_sequence=is_sequence, path_dir_field=dn_field, path_base_field=bn_field) diff --git a/blender_asset_tracer/tracer/file_sequence.py b/blender_asset_tracer/tracer/file_sequence.py index 54816a4..0885493 100644 --- a/blender_asset_tracer/tracer/file_sequence.py +++ b/blender_asset_tracer/tracer/file_sequence.py @@ -16,8 +16,8 @@ class DoesNotExist(OSError): def expand_sequence(path: pathlib.Path) -> typing.Iterator[pathlib.Path]: """Expand a file sequence path into the actual file paths. - :param path: can be either a glob pattern (must contain a * character), - a directory, or the path of the first file in the sequence. + :param path: can be either a glob pattern (must contain a * character) + or the path of the first file in the sequence. """ if '*' in str(path): # assume it is a glob @@ -31,9 +31,7 @@ def expand_sequence(path: pathlib.Path) -> typing.Iterator[pathlib.Path]: raise DoesNotExist(path) if path.is_dir(): - log.debug('expanding directory %s', path) - yield from sorted(path.rglob('*')) - return + raise TypeError('path is a directory: %s' % path) log.debug('expanding file sequence %s', path) diff --git a/blender_asset_tracer/tracer/result.py b/blender_asset_tracer/tracer/result.py index e26da08..da68350 100644 --- a/blender_asset_tracer/tracer/result.py +++ b/blender_asset_tracer/tracer/result.py @@ -16,8 +16,8 @@ class BlockUsage: name of the block. :ivar block: :ivar asset_path: The path of the asset, if is_sequence=False. Otherwise - it can be either a glob pattern (must contain a * byte), a directory, - or the path of the first file in the sequence. + it can be either a glob pattern (must contain a * byte) or the path of + the first file in the sequence. :ivar is_sequence: Indicates whether this file is alone (False), the first of a sequence (True, and the path points to a file), or a directory containing a sequence (True, and path points to a directory). @@ -82,9 +82,15 @@ class BlockUsage: return b'-unnamed-' def __repr__(self): + if self.path_full_field is None: + field_name = self.path_dir_field.name.name_full.decode() + \ + '/' + \ + self.path_base_field.name.name_full.decode() + else: + field_name = self.path_full_field.name.name_full.decode() return '' % ( self.block_name, self.block.dna_type_name, - self.path_full_field.name.name_full.decode(), self.asset_path, + field_name, self.asset_path, ' sequence' if self.is_sequence else '' ) diff --git a/tests/test_tracer.py b/tests/test_tracer.py index e32394a..bafd0b1 100644 --- a/tests/test_tracer.py +++ b/tests/test_tracer.py @@ -80,15 +80,15 @@ class DepsTest(AbstractTracerTest): actual = Expect(actual_type, actual_full_field, actual_dirname, actual_basename, dep.asset_path, dep.is_sequence) - exp = expects[dep.block_name] - if isinstance(exp, set): + exp = expects.get(dep.block_name, None) + if isinstance(exp, (set, list)): self.assertIn(actual, exp, msg='for block %s' % dep.block_name) - exp.discard(actual) + exp.remove(actual) if not exp: # Don't leave empty sets in expects. del expects[dep.block_name] else: - self.assertEqual(exp, actual, msg='for block %s' % dep.block_name) + self.assertEqual(actual, exp, msg='for block %s' % dep.block_name) del expects[dep.block_name] # All expected uses should have been seen. @@ -118,16 +118,17 @@ class DepsTest(AbstractTracerTest): def test_seq_image_sequence(self): expects = { - b'SQ000210.png': Expect( - 'Sequence', None, 'dir[768]', 'name[256]', b'//imgseq/000210.png', True), - b'SQvideo-tiny.mkv': Expect( - 'Sequence', None, 'dir[768]', 'name[256]', - b'//../../../../cloud/pillar/testfiles/video-tiny.mkv', False), + b'-unnamed-': [ + Expect('Strip', None, 'dir[768]', 'name[256]', b'//imgseq/000210.png', True), - # The sound will be referenced twice, from the sequence strip and an SO data block. - b'SQvideo-tiny.001': Expect( - 'Sequence', None, 'dir[768]', 'name[256]', - b'//../../../../cloud/pillar/testfiles/video-tiny.mkv', False), + # Video strip reference. + Expect('Strip', None, 'dir[768]', 'name[256]', + b'//../../../../cloud/pillar/testfiles/video-tiny.mkv', False), + + # The sound will be referenced twice, from the sequence strip and an SO data block. + Expect('Strip', None, 'dir[768]', 'name[256]', + b'//../../../../cloud/pillar/testfiles/video-tiny.mkv', False), + ], b'SOvideo-tiny.mkv': Expect( 'bSound', 'name[1024]', None, None, b'//../../../../cloud/pillar/testfiles/video-tiny.mkv', False), diff --git a/tests/test_tracer_file_sequence.py b/tests/test_tracer_file_sequence.py index 47f1730..ea7590a 100644 --- a/tests/test_tracer_file_sequence.py +++ b/tests/test_tracer_file_sequence.py @@ -14,12 +14,6 @@ class ExpandFileSequenceTest(AbstractBlendFileTest): actual = list(file_sequence.expand_sequence(path)) self.assertEqual(self.imgseq, actual) - def test_directory(self): - path = self.blendfiles / 'imgseq' - actual = list(file_sequence.expand_sequence(path)) - expected = self.imgseq + [self.blendfiles / 'imgseq/LICENSE.txt'] - self.assertEqual(expected, actual) - def test_first_file(self): path = self.blendfiles / 'imgseq/000210.png' actual = list(file_sequence.expand_sequence(path))