Cache open blend files
This simplifies blend file handling, ensuring that blend files are only opened once. Otherwise it would be harder to handle things like dependency diamonds (libraries that are referenced via multiple paths through multiple other libraries).
This commit is contained in:
parent
c5a02423cb
commit
09a0866c14
@ -20,6 +20,7 @@
|
|||||||
# (c) 2014, Blender Foundation - Campbell Barton
|
# (c) 2014, Blender Foundation - Campbell Barton
|
||||||
# (c) 2018, Blender Foundation - Sybren A. Stüvel
|
# (c) 2018, Blender Foundation - Sybren A. Stüvel
|
||||||
|
|
||||||
|
import atexit
|
||||||
import collections
|
import collections
|
||||||
import gzip
|
import gzip
|
||||||
import logging
|
import logging
|
||||||
@ -27,6 +28,8 @@ import os
|
|||||||
import struct
|
import struct
|
||||||
import pathlib
|
import pathlib
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
|
import functools
|
||||||
import typing
|
import typing
|
||||||
|
|
||||||
from . import exceptions, dna_io, dna, header
|
from . import exceptions, dna_io, dna, header
|
||||||
@ -39,6 +42,29 @@ FILE_BUFFER_SIZE = 1024 * 1024
|
|||||||
BLENDFILE_MAGIC = b'BLENDER'
|
BLENDFILE_MAGIC = b'BLENDER'
|
||||||
GZIP_MAGIC = b'\x1f\x8b'
|
GZIP_MAGIC = b'\x1f\x8b'
|
||||||
|
|
||||||
|
_cached_bfiles = {}
|
||||||
|
|
||||||
|
|
||||||
|
def open_cached(path: pathlib.Path, mode='rb') -> 'BlendFile':
|
||||||
|
"""Open a blend file, ensuring it is only opened once."""
|
||||||
|
bfile_path = path.absolute().resolve()
|
||||||
|
try:
|
||||||
|
return _cached_bfiles[bfile_path]
|
||||||
|
except KeyError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
bfile = BlendFile(path, mode=mode)
|
||||||
|
_cached_bfiles[bfile_path] = bfile
|
||||||
|
return bfile
|
||||||
|
|
||||||
|
|
||||||
|
@atexit.register
|
||||||
|
def close_all_cached():
|
||||||
|
log.info('Closing all blend files')
|
||||||
|
for bfile in _cached_bfiles.values():
|
||||||
|
bfile.close()
|
||||||
|
_cached_bfiles.clear()
|
||||||
|
|
||||||
|
|
||||||
class BlendFile:
|
class BlendFile:
|
||||||
"""Representation of a blend file.
|
"""Representation of a blend file.
|
||||||
|
|||||||
@ -23,7 +23,7 @@ def deps(bfilepath: pathlib.Path) -> typing.Iterator[result.BlockUsage]:
|
|||||||
:param bfilepath: File to open.
|
:param bfilepath: File to open.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
with blendfile.BlendFile(bfilepath) as bfile:
|
bfile = blendfile.open_cached(bfilepath)
|
||||||
for block in asset_holding_blocks(file2blocks.iter_blocks(bfile)):
|
for block in asset_holding_blocks(file2blocks.iter_blocks(bfile)):
|
||||||
yield from blocks2assets.iter_assets(block)
|
yield from blocks2assets.iter_assets(block)
|
||||||
|
|
||||||
|
|||||||
@ -86,8 +86,7 @@ class _BlockIterator:
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
log.debug('Expanding %d blocks in %s', len(idblocks), lib_path)
|
log.debug('Expanding %d blocks in %s', len(idblocks), lib_path)
|
||||||
|
libfile = blendfile.open_cached(lib_path)
|
||||||
with blendfile.BlendFile(lib_path) as libfile:
|
|
||||||
yield from self.iter_blocks(libfile, idblocks)
|
yield from self.iter_blocks(libfile, idblocks)
|
||||||
|
|
||||||
def _queue_all_blocks(self, bfile: blendfile.BlendFile):
|
def _queue_all_blocks(self, bfile: blendfile.BlendFile):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user