Ported get_data_hash() and renamed to hash()
This commit is contained in:
parent
db14cc5074
commit
55075c09b6
@ -456,22 +456,26 @@ class BlendFileBlock:
|
||||
yield from self.get_recursive_iter(f.name.name_only, path_full, default=default,
|
||||
null_terminated=null_terminated, as_str=as_str)
|
||||
|
||||
def get_data_hash(self): # TODO(Sybren): port to BAT
|
||||
def hash(self) -> int:
|
||||
"""Generate a pointer-independent hash for the block.
|
||||
|
||||
Generates a 'hash' that can be used instead of addr_old as block id,
|
||||
which should be 'stable' across .blend file load & save (i.e. it does
|
||||
not changes due to pointer addresses variations).
|
||||
"""
|
||||
Generates a 'hash' that can be used instead of addr_old as block id, and that should be 'stable' across .blend
|
||||
file load & save (i.e. it does not changes due to pointer addresses variations).
|
||||
"""
|
||||
# TODO This implementation is most likely far from optimal... and CRC32 is not renown as the best hashing
|
||||
# algo either. But for now does the job!
|
||||
# TODO This implementation is most likely far from optimal... and CRC32
|
||||
# is not kown as the best hashing algo either. But for now does the job!
|
||||
import zlib
|
||||
def _is_pointer(self, k):
|
||||
return self.file.structs[self.sdna_index].field_from_path(
|
||||
self.file.header, self.file.handle, k).dna_name.is_pointer
|
||||
|
||||
dna_type = self.dna_type
|
||||
pointer_size = self.bfile.header.pointer_size
|
||||
|
||||
hsh = 1
|
||||
for k, v in self.items_recursive():
|
||||
if not _is_pointer(self, k):
|
||||
hsh = zlib.adler32(str(v).encode(), hsh)
|
||||
for path, value in self.items_recursive():
|
||||
field, _ = dna_type.field_from_path(pointer_size, path)
|
||||
if field.name.is_pointer:
|
||||
continue
|
||||
hsh = zlib.adler32(str(value).encode(), hsh)
|
||||
return hsh
|
||||
|
||||
def set(self, path: dna.FieldPath, value): # TODO(Sybren): port to BAT
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
from shutil import copyfile
|
||||
|
||||
import os
|
||||
|
||||
from blender_asset_tracer import blendfile
|
||||
from abstract_test import AbstractBlendFileTest
|
||||
|
||||
@ -25,14 +27,35 @@ class ModifyUncompressedTest(AbstractBlendFileTest):
|
||||
library[b'filepath'] = b'//basic_file.blend'
|
||||
library[b'name'] = b'//basic_file.blend'
|
||||
|
||||
# Reload the blend file to inspect that it was written properly.
|
||||
self.bf.close()
|
||||
self.bf = blendfile.BlendFile(self.to_modify, mode='r+b')
|
||||
self.reload()
|
||||
|
||||
library = self.bf.code_index[b'LI'][0]
|
||||
self.assertEqual(b'//basic_file.blend', library[b'filepath'])
|
||||
self.assertEqual(b'//basic_file.blend', library[b'name'])
|
||||
|
||||
def test_block_hash(self):
|
||||
scene = self.bf.code_index[b'SC'][0]
|
||||
assert isinstance(scene, blendfile.BlendFileBlock)
|
||||
|
||||
pre_hash = scene.hash()
|
||||
self.assertIsInstance(pre_hash, int)
|
||||
|
||||
# Change the 'ed' pointer to some arbitrary value by hacking the blend file.
|
||||
psize = self.bf.header.pointer_size
|
||||
field, field_offset = scene.dna_type.field_from_path(psize, b'ed')
|
||||
self.bf.fileobj.seek(scene.file_offset + field_offset, os.SEEK_SET)
|
||||
self.bf.fileobj.write(b'12345678'[:psize])
|
||||
|
||||
self.reload()
|
||||
|
||||
scene = self.bf.code_index[b'SC'][0]
|
||||
post_hash = scene.hash()
|
||||
self.assertEqual(pre_hash, post_hash)
|
||||
|
||||
def reload(self):
|
||||
self.bf.close()
|
||||
self.bf = blendfile.BlendFile(self.to_modify, mode='r+b')
|
||||
|
||||
|
||||
class ModifyCompressedTest(AbstractBlendFileTest):
|
||||
def setUp(self):
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user