Struct.field_set - support setting subproperties (#92899)
Extend `Struct.field_set()` so that the `path` type can be a `dna.FieldPath`, to mirror `Struct.field_get`'s `path` type, and allow users to set file-block's subproperties. For example this allows setting `object_block[(b'id', 'name')]`. Also, along the way, added a test for getting subproperty value. Reviewed-on: https://projects.blender.org/blender/blender-asset-tracer/pulls/92899
This commit is contained in:
parent
c69612b264
commit
47c3e8d77f
@ -726,7 +726,7 @@ class BlendFileBlock:
|
||||
hsh = zlib.adler32(str(value).encode(), hsh)
|
||||
return hsh
|
||||
|
||||
def set(self, path: bytes, value):
|
||||
def set(self, path: dna.FieldPath, value):
|
||||
dna_struct = self.bfile.structs[self.sdna_index]
|
||||
self.bfile.mark_modified()
|
||||
self.bfile.fileobj.seek(self.file_offset, os.SEEK_SET)
|
||||
@ -835,7 +835,7 @@ class BlendFileBlock:
|
||||
def __getitem__(self, path: dna.FieldPath):
|
||||
return self.get(path)
|
||||
|
||||
def __setitem__(self, item: bytes, value) -> None:
|
||||
def __setitem__(self, item: dna.FieldPath, value) -> None:
|
||||
self.set(item, value)
|
||||
|
||||
def has_field(self, name: bytes) -> bool:
|
||||
|
||||
@ -310,7 +310,7 @@ class Struct:
|
||||
self,
|
||||
file_header: header.BlendFileHeader,
|
||||
fileobj: typing.IO[bytes],
|
||||
path: bytes,
|
||||
path: FieldPath,
|
||||
value: typing.Any,
|
||||
):
|
||||
"""Write a value to the blend file.
|
||||
@ -319,7 +319,6 @@ class Struct:
|
||||
struct on disk (e.g. the start of the BlendFileBlock containing the
|
||||
data).
|
||||
"""
|
||||
assert isinstance(path, bytes), "path should be bytes, but is %s" % type(path)
|
||||
|
||||
field, offset = self.field_from_path(file_header.pointer_size, path)
|
||||
|
||||
|
||||
@ -93,6 +93,10 @@ class StructTest(unittest.TestCase):
|
||||
self.s_ulong = dna.Struct(b"ulong", 8)
|
||||
self.s_uint64 = dna.Struct(b"uint64_t", 8)
|
||||
self.s_uint128 = dna.Struct(b"uint128_t", 16) # non-supported type
|
||||
self.s_substruct = dna.Struct(b"substruct")
|
||||
|
||||
self.f_substruct_name = dna.Field(self.s_char, dna.Name(b"name[10]"), 10, 0)
|
||||
self.s_substruct.append_field(self.f_substruct_name)
|
||||
|
||||
self.f_next = dna.Field(self.s, dna.Name(b"*next"), 8, 0)
|
||||
self.f_prev = dna.Field(self.s, dna.Name(b"*prev"), 8, 8)
|
||||
@ -109,6 +113,7 @@ class StructTest(unittest.TestCase):
|
||||
self.f_testint = dna.Field(self.s_int, dna.Name(b"testint"), 4, 4178)
|
||||
self.f_testfloat = dna.Field(self.s_float, dna.Name(b"testfloat"), 4, 4182)
|
||||
self.f_testulong = dna.Field(self.s_ulong, dna.Name(b"testulong"), 8, 4186)
|
||||
self.f_substruct = dna.Field(self.s_substruct, dna.Name(b"testsubstruct"), 10, 4194)
|
||||
|
||||
self.s.append_field(self.f_next)
|
||||
self.s.append_field(self.f_prev)
|
||||
@ -125,6 +130,7 @@ class StructTest(unittest.TestCase):
|
||||
self.s.append_field(self.f_testint)
|
||||
self.s.append_field(self.f_testfloat)
|
||||
self.s.append_field(self.f_testulong)
|
||||
self.s.append_field(self.f_substruct)
|
||||
|
||||
def test_autosize(self):
|
||||
with self.assertRaises(ValueError):
|
||||
@ -263,6 +269,19 @@ class StructTest(unittest.TestCase):
|
||||
self.assertAlmostEqual(2.79, val[1])
|
||||
fileobj.seek.assert_called_with(4144, os.SEEK_CUR)
|
||||
|
||||
def test_struct_field_get_subproperty(self):
|
||||
fileobj = mock.MagicMock(io.BufferedReader)
|
||||
fileobj.read.return_value = b"my_name"
|
||||
|
||||
_, val = self.s.field_get(
|
||||
self.FakeHeader(),
|
||||
fileobj,
|
||||
(b"testsubstruct", b"name"),
|
||||
as_str=True,
|
||||
)
|
||||
self.assertEqual("my_name", val)
|
||||
fileobj.seek.assert_called_with(4194, os.SEEK_CUR)
|
||||
|
||||
def test_char_field_set(self):
|
||||
fileobj = mock.MagicMock(io.BufferedReader)
|
||||
value = 255
|
||||
@ -344,3 +363,10 @@ class StructTest(unittest.TestCase):
|
||||
expected = struct.pack(b">f", value)
|
||||
self.s.field_set(self.FakeHeader(), fileobj, b"testfloat", value)
|
||||
fileobj.write.assert_called_with(expected)
|
||||
|
||||
def test_struct_field_set_subproperty(self):
|
||||
fileobj = mock.MagicMock(io.BufferedReader)
|
||||
expected = b"new_name\x00"
|
||||
|
||||
self.s.field_set(self.FakeHeader(), fileobj, (b"testsubstruct", b"name"), "new_name")
|
||||
fileobj.write.assert_called_with(expected)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user