Ejemplo n.º 1
0
    def assert_deps(self, blend_fname, expects: dict):
        for dep in trace.deps(self.blendfiles / blend_fname):
            actual_type = dep.block.dna_type.dna_type_id.decode()
            actual_full_field = self.field_name(dep.path_full_field)
            actual_dirname = self.field_name(dep.path_dir_field)
            actual_basename = self.field_name(dep.path_base_field)

            actual = Expect(actual_type, actual_full_field, actual_dirname,
                            actual_basename, dep.asset_path, dep.is_sequence)

            exp = expects.get(dep.block_name, None)
            if isinstance(exp, (set, list)):
                self.assertIn(actual, exp, msg='for block %s' % dep.block_name)
                exp.remove(actual)
                if not exp:
                    # Don't leave empty sets in expects.
                    del expects[dep.block_name]
            elif exp is None:
                self.assertIsNone(actual,
                                  msg='unexpected dependency of block %s' %
                                  dep.block_name)
                del expects[dep.block_name]
            else:
                self.assertEqual(exp,
                                 actual,
                                 msg='for block %s' % dep.block_name)
                del expects[dep.block_name]

        # All expected uses should have been seen.
        self.assertEqual(expects, {}, 'Expected results were not seen.')
Ejemplo n.º 2
0
    def test_seq_image_sequence(self):
        expects = {
            b'-unnamed-': [
                Expect('Strip', None, 'dir[768]', 'name[256]',
                       b'//imgseq/000210.png', True),

                # 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),
        }
        self.assert_deps('image_sequencer.blend', expects)

        # Test the filename expansion.
        expected = [
            self.blendfiles / ('imgseq/%06d.png' % num)
            for num in range(210, 215)
        ]
        for dep in trace.deps(self.blendfiles / 'image_sequencer.blend'):
            if dep.block_name != b'SQ000210.png':
                continue

            actual = list(dep.files())
            self.assertEqual(actual, expected)
Ejemplo n.º 3
0
    def test_usage_abspath(self):
        deps = [
            dep for dep in trace.deps(self.blendfiles / 'doubly_linked.blend')
            if dep.asset_path == b'//material_textures.blend'
        ]
        usage = deps[0]

        expect = self.blendfiles / 'material_textures.blend'
        self.assertEqual(expect, usage.abspath)
Ejemplo n.º 4
0
    def test_recursion_loop(self):
        infinite_bfile = self.blendfiles / 'recursive_dependency_1.blend'

        reclim = sys.getrecursionlimit()
        try:
            sys.setrecursionlimit(100)
            # This should finish without hitting the recursion limit.
            for _ in trace.deps(infinite_bfile):
                pass
        finally:
            sys.setrecursionlimit(reclim)
Ejemplo n.º 5
0
def report_json(bpath):
    import collections

    # Mapping from blend file to its dependencies.
    report = collections.defaultdict(set)

    for usage in trace.deps(bpath):
        filepath = usage.block.bfile.filepath.absolute()
        for assetpath in usage.files():
            assetpath = assetpath.resolve()
            report[str(filepath)].add(assetpath)

    json.dump(report, sys.stdout, cls=JSONSerialiser, indent=4)
Ejemplo n.º 6
0
    def strategise(self) -> None:
        """Determine what to do with the assets.

        Places an asset into one of these categories:
            - Can be copied as-is, nothing smart required.
            - Blend files referring to this asset need to be rewritten.

        This function does *not* expand globs. Globs are seen as single
        assets, and are only evaluated when performing the actual transfer
        in the execute() function.
        """

        # The blendfile that we pack is generally not its own dependency, so
        # we have to explicitly add it to the _packed_paths.
        bfile_path = bpathlib.make_absolute(self.blendfile)

        # Both paths have to be resolved first, because this also translates
        # network shares mapped to Windows drive letters back to their UNC
        # notation. Only resolving one but not the other (which can happen
        # with the abosolute() call above) can cause errors.
        bfile_pp = self._target_path / bfile_path.relative_to(
            bpathlib.make_absolute(self.project))
        self._output_path = bfile_pp

        self._progress_cb.pack_start()

        act = self._actions[bfile_path]
        act.path_action = PathAction.KEEP_PATH
        act.new_path = bfile_pp

        self._check_aborted()
        self._new_location_paths = set()
        for usage in trace.deps(self.blendfile, self._progress_cb):
            self._check_aborted()
            asset_path = usage.abspath
            if any(asset_path.match(glob) for glob in self._exclude_globs):
                log.info('Excluding file: %s', asset_path)
                continue

            if self.relative_only and not usage.asset_path.startswith(b'//'):
                log.info('Skipping absolute path: %s', usage.asset_path)
                continue

            if usage.is_sequence:
                self._visit_sequence(asset_path, usage)
            else:
                self._visit_asset(asset_path, usage)

        self._find_new_paths()
        self._group_rewrites()
Ejemplo n.º 7
0
def report_text(bpath, *, include_sha256: bool, show_timing: bool):
    reported_assets = set()  # type: typing.Set[pathlib.Path]
    last_reported_bfile = None
    shorten = functools.partial(common.shorten, pathlib.Path.cwd())

    time_spent_on_shasums = 0.0
    start_time = time.time()

    for usage in trace.deps(bpath):
        filepath = usage.block.bfile.filepath.absolute()
        if filepath != last_reported_bfile:
            if include_sha256:
                shasum, time_spent = calc_sha_sum(filepath)
                time_spent_on_shasums += time_spent
                print(shorten(filepath), shasum)
            else:
                print(shorten(filepath))

        last_reported_bfile = filepath

        for assetpath in usage.files():
            assetpath = bpathlib.make_absolute(assetpath)
            if assetpath in reported_assets:
                log.debug('Already reported %s', assetpath)
                continue

            if include_sha256:
                shasum, time_spent = calc_sha_sum(assetpath)
                time_spent_on_shasums += time_spent
                print('   ', shorten(assetpath), shasum)
            else:
                print('   ', shorten(assetpath))
            reported_assets.add(assetpath)

    if show_timing:
        duration = time.time() - start_time
        print('Spent %.2f seconds on producing this listing' % duration)
        if include_sha256:
            print('Spent %.2f seconds on calculating SHA sums' %
                  time_spent_on_shasums)
            percentage = time_spent_on_shasums / duration * 100
            print('  (that is %d%% of the total time' % percentage)
Ejemplo n.º 8
0
def trace_blend_file(blend_file_path, progress_cb=None):
    """ Finds all the dependencies for a given .blend file

    :param blend_file_path: the .blend file to inspect
    :type blend_file_path: str
    :param progress_cb: The progress reporting callback instance
    :type progress_cb: blender_asset_tracer.pack.progress.Callback
    :return: A dictionary of .blend files and their sets of dependencies
    :rtype: collections.defaultdict(set)
    """

    # the dependencies as a mapping from the blend file to its set of dependencies.
    dependencies = collections.defaultdict(set)

    # Find the dependencies
    for usage in trace.deps(pathlib.Path(blend_file_path), progress_cb):
        file_path = usage.block.bfile.filepath.absolute()
        for assetPath in usage.files():
            asset_path = assetPath.resolve()
            dependencies[str(file_path)].add(assetPath)

    return dependencies
Ejemplo n.º 9
0
    def test_alembic_sequence(self):
        self.assert_deps(
            'alembic-sequence-user.blend', {
                b'CFclothsim_alembic':
                Expect('CacheFile', 'filepath[1024]', None, None,
                       b'//clothsim.030.abc', True),
            })

        # Test the filename expansion.
        expected = [
            self.blendfiles / ('clothsim.%03d.abc' % num)
            for num in range(30, 36)
        ]
        performed_test = False
        for dep in trace.deps(self.blendfiles / 'alembic-sequence-user.blend'):
            if dep.block_name != b'CFclothsim_alembic':
                continue

            actual = list(dep.files())
            self.assertEqual(actual, expected)
            performed_test = True
        self.assertTrue(performed_test)
Ejemplo n.º 10
0
## list dependancies with BAT
import bpy
from blender_asset_tracer.trace import deps
from pathlib import Path

for lib in deps(Path(bpy.data.filepath)):
    # print(lib)
    if lib.asset_path.is_absolute():
        ## print abs lib only
        print(lib)
Ejemplo n.º 11
0
print('-' * 10, '\n' * 3)

# Set filepath here
fp = bpy.data.filepath

fp = Path(fp)

assert fp.exists

start = time()

absol = []
not_exists = []
errors = []

for lib in deps(fp):
    try:
        if not lib.abspath.exists():
            print('!! not found:', lib)
            not_exists.append(lib)
            continue

        if lib.asset_path.is_absolute():
            ## print abs lib only
            absol.append(lib)
            print('absolute', lib)

    except error as e:
        print('Error accessing:', lib)
        print(e)
        errors.append(lib)