875 lines
20 KiB
Python
875 lines
20 KiB
Python
import io
|
|
import random
|
|
import unittest
|
|
|
|
from arcadeutils import FileBytes
|
|
|
|
|
|
class TestFileBytes(unittest.TestCase):
|
|
|
|
def test_read_only_operations(self) -> None:
|
|
b = b"0123456789"
|
|
fb = FileBytes(io.BytesIO(b))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
len(b),
|
|
)
|
|
|
|
# Basic index lookup.
|
|
self.assertEqual(
|
|
fb[5],
|
|
b[5],
|
|
)
|
|
|
|
# Make sure negative indexing works.
|
|
self.assertEqual(
|
|
fb[-2],
|
|
b[-2],
|
|
)
|
|
|
|
# Indexing outside of the length as an individual lookup
|
|
# should cause an IndexError.
|
|
with self.assertRaises(IndexError):
|
|
fb[10]
|
|
|
|
# Basic start:end lookups.
|
|
self.assertEqual(
|
|
fb[3:7],
|
|
b[3:7],
|
|
)
|
|
|
|
# Leave out the start or end.
|
|
self.assertEqual(
|
|
fb[3:],
|
|
b[3:],
|
|
)
|
|
self.assertEqual(
|
|
fb[:5],
|
|
b[:5],
|
|
)
|
|
self.assertEqual(
|
|
fb[-2:],
|
|
b[-2:],
|
|
)
|
|
self.assertEqual(
|
|
fb[:-8],
|
|
b[:-8]
|
|
)
|
|
|
|
# Mixed positive and negative indexes.
|
|
self.assertEqual(
|
|
fb[3:-2],
|
|
b[3:-2],
|
|
)
|
|
self.assertEqual(
|
|
fb[-8:5],
|
|
b[-8:5],
|
|
)
|
|
|
|
# Resulting in no data.
|
|
self.assertEqual(
|
|
fb[3:3],
|
|
b[3:3],
|
|
)
|
|
self.assertEqual(
|
|
fb[5:3],
|
|
fb[5:3],
|
|
)
|
|
|
|
# Out of range.
|
|
self.assertEqual(
|
|
fb[5:15],
|
|
b[5:15],
|
|
)
|
|
|
|
# Copy
|
|
self.assertEqual(
|
|
fb[:],
|
|
b,
|
|
)
|
|
|
|
# Indexing with a zero step should raise a ValueError.
|
|
with self.assertRaises(ValueError):
|
|
fb[3:5:0]
|
|
|
|
# Lookups with a step.
|
|
self.assertEqual(
|
|
fb[3:7:2],
|
|
b[3:7:2],
|
|
)
|
|
self.assertEqual(
|
|
fb[7:3:-2],
|
|
b[7:3:-2],
|
|
)
|
|
|
|
# Reverse copy.
|
|
self.assertEqual(
|
|
fb[::-1],
|
|
b[::-1],
|
|
)
|
|
|
|
# Provide default explicitly.
|
|
self.assertEqual(
|
|
fb[3:7:1],
|
|
b[3:7:1],
|
|
)
|
|
|
|
# Negative single step.
|
|
self.assertEqual(
|
|
fb[7:3:-1],
|
|
b[7:3:-1],
|
|
)
|
|
|
|
# Lookups that result in no data.
|
|
self.assertEqual(
|
|
fb[3:7:-1],
|
|
b[3:7:-1],
|
|
)
|
|
self.assertEqual(
|
|
fb[7:3:1],
|
|
b[7:3:1],
|
|
)
|
|
|
|
# Make sure that a clone of this object doesn't get any file changes
|
|
# and that it is identical.
|
|
self.assertEqual(
|
|
fb.clone()[:],
|
|
b,
|
|
)
|
|
|
|
# Attempt to serialize out the data and make sure it did not change
|
|
# before calling write.
|
|
handle = fb.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b,
|
|
)
|
|
|
|
# Make sure that the data is identical after calling write as well.
|
|
fb.write_changes()
|
|
handle = fb.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b,
|
|
)
|
|
|
|
def test_read_after_modify(self) -> None:
|
|
b = b"012a456bc9"
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Do some simple modifications.
|
|
fb[3] = 97
|
|
fb[7:9] = b"bc"
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
len(b),
|
|
)
|
|
|
|
# Basic index lookup.
|
|
self.assertEqual(
|
|
fb[5],
|
|
b[5],
|
|
)
|
|
|
|
# Make sure negative indexing works.
|
|
self.assertEqual(
|
|
fb[-2],
|
|
b[-2],
|
|
)
|
|
|
|
# Indexing outside of the length as an individual lookup
|
|
# should cause an IndexError.
|
|
with self.assertRaises(IndexError):
|
|
fb[10]
|
|
|
|
# Basic start:end lookups.
|
|
self.assertEqual(
|
|
fb[3:7],
|
|
b[3:7],
|
|
)
|
|
|
|
# Leave out the start or end.
|
|
self.assertEqual(
|
|
fb[3:],
|
|
b[3:],
|
|
)
|
|
self.assertEqual(
|
|
fb[:5],
|
|
b[:5],
|
|
)
|
|
self.assertEqual(
|
|
fb[-2:],
|
|
b[-2:],
|
|
)
|
|
self.assertEqual(
|
|
fb[:-8],
|
|
b[:-8]
|
|
)
|
|
|
|
# Mixed positive and negative indexes.
|
|
self.assertEqual(
|
|
fb[3:-2],
|
|
b[3:-2],
|
|
)
|
|
self.assertEqual(
|
|
fb[-8:5],
|
|
b[-8:5],
|
|
)
|
|
|
|
# Resulting in no data.
|
|
self.assertEqual(
|
|
fb[3:3],
|
|
b[3:3],
|
|
)
|
|
self.assertEqual(
|
|
fb[5:3],
|
|
fb[5:3],
|
|
)
|
|
|
|
# Out of range.
|
|
self.assertEqual(
|
|
fb[5:15],
|
|
b[5:15],
|
|
)
|
|
|
|
# Copy
|
|
self.assertEqual(
|
|
fb[:],
|
|
b,
|
|
)
|
|
|
|
# Indexing with a zero step should raise a ValueError.
|
|
with self.assertRaises(ValueError):
|
|
fb[3:5:0]
|
|
|
|
# Lookups with a step.
|
|
self.assertEqual(
|
|
fb[3:7:2],
|
|
b[3:7:2],
|
|
)
|
|
self.assertEqual(
|
|
fb[7:3:-2],
|
|
b[7:3:-2],
|
|
)
|
|
|
|
# Reverse copy.
|
|
self.assertEqual(
|
|
fb[::-1],
|
|
b[::-1],
|
|
)
|
|
|
|
# Provide default explicitly.
|
|
self.assertEqual(
|
|
fb[3:7:1],
|
|
b[3:7:1],
|
|
)
|
|
|
|
# Negative single step.
|
|
self.assertEqual(
|
|
fb[7:3:-1],
|
|
b[7:3:-1],
|
|
)
|
|
|
|
# Lookups that result in no data.
|
|
self.assertEqual(
|
|
fb[3:7:-1],
|
|
b[3:7:-1],
|
|
)
|
|
self.assertEqual(
|
|
fb[7:3:1],
|
|
b[7:3:1],
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
fb.write_changes()
|
|
handle = fb.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b,
|
|
)
|
|
|
|
def test_read_after_append(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Do some simple appending.
|
|
fb.append(b"abcdef")
|
|
|
|
# Now try to read over the boundary.
|
|
self.assertEqual(
|
|
fb[5:15],
|
|
b"56789abcde",
|
|
)
|
|
|
|
def test_modify_variants(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
fb[3] = 97
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012a456789",
|
|
)
|
|
|
|
fb[7:9] = b"bc"
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012a456bc9",
|
|
)
|
|
|
|
fb[4:8:2] = b"de"
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012ad5ebc9",
|
|
)
|
|
fb[-1] = 102
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012ad5ebcf",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
fb.write_changes()
|
|
handle = fb.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"012ad5ebcf",
|
|
)
|
|
|
|
fb[7:3:-2] = b"gh"
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012adhegcf",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
fb.write_changes()
|
|
handle = fb.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"012adhegcf",
|
|
)
|
|
|
|
def test_resize_fail(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
with self.assertRaises(NotImplementedError):
|
|
fb[3:4] = b"long"
|
|
with self.assertRaises(NotImplementedError):
|
|
fb[3:7] = b""
|
|
|
|
def test_append_null(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
fb.append(b"")
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
fb.write_changes()
|
|
handle = fb.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"0123456789",
|
|
)
|
|
|
|
def test_append_modify(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
# Clone this so we can verify that clones don't receive additional modifications.
|
|
clone = fb.clone()
|
|
clone.append(b"abc")
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
13,
|
|
)
|
|
|
|
# Verify additional appends work.
|
|
clone.append(b"def")
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
16,
|
|
)
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456789abcdef",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
clone.write_changes()
|
|
handle = clone.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"0123456789abcdef",
|
|
)
|
|
|
|
def test_modify_writeback_clones_unsafe(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
clone = fb.clone()
|
|
clone.append(b"abcdef")
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456789abcdef",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
clone.write_changes()
|
|
handle = clone.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"0123456789abcdef",
|
|
)
|
|
|
|
# Verify that accessing the clone data works.
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456789abcdef",
|
|
)
|
|
clone[0:1] = b"z"
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"z123456789abcdef",
|
|
)
|
|
|
|
# Verify that attempting to read or modify the original raises
|
|
# an error since we wrote the clone back to the original file.
|
|
with self.assertRaisesRegex(Exception, "Another FileBytes instance representing the same file was written back!"):
|
|
fb[:]
|
|
with self.assertRaisesRegex(Exception, "Another FileBytes instance representing the same file was written back!"):
|
|
fb[5] = 2
|
|
|
|
# Verify that making a new clone works properly.
|
|
newclone = fb.clone()
|
|
self.assertEqual(
|
|
newclone[:],
|
|
b"0123456789abcdef",
|
|
)
|
|
|
|
def test_add(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
# Create a copy by adding to the original.
|
|
clone = fb + b"abc"
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
13,
|
|
)
|
|
|
|
# Verify additional appends work including from FileBytes.
|
|
clone = clone + FileBytes(io.BytesIO(b"def"))
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
16,
|
|
)
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456789abcdef",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
clone.write_changes()
|
|
handle = clone.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"0123456789abcdef",
|
|
)
|
|
|
|
def test_truncate_noop(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
# Create a copy by adding to the original.
|
|
clone = fb.clone()
|
|
clone.truncate(15)
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
10,
|
|
)
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456789",
|
|
)
|
|
|
|
def test_truncate_simple(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
# Create a copy by adding to the original.
|
|
clone = fb.clone()
|
|
clone.truncate(5)
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
5,
|
|
)
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"01234",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
clone.write_changes()
|
|
handle = clone.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"01234",
|
|
)
|
|
|
|
# Verify everything is good after writeback.
|
|
self.assertEqual(
|
|
len(clone),
|
|
5,
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"01234",
|
|
)
|
|
|
|
def test_truncate_only_patches(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
# Create a copy by adding to the original.
|
|
clone = fb.clone()
|
|
clone.append(b"abcdef")
|
|
clone.truncate(13)
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
13,
|
|
)
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456789abc",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
clone.write_changes()
|
|
handle = clone.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"0123456789abc",
|
|
)
|
|
|
|
# Verify that everything looks good still.
|
|
self.assertEqual(
|
|
len(clone),
|
|
13,
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456789abc",
|
|
)
|
|
|
|
def test_truncate_overlap(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
# Length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
|
|
# Create a copy by adding to the original.
|
|
clone = fb.clone()
|
|
clone.append(b"abcdef")
|
|
clone.truncate(7)
|
|
|
|
# New length check.
|
|
self.assertEqual(
|
|
len(fb),
|
|
10,
|
|
)
|
|
self.assertEqual(
|
|
len(clone),
|
|
7,
|
|
)
|
|
|
|
# Verify modification stuck.
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"0123456789",
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly.
|
|
clone.write_changes()
|
|
handle = clone.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"0123456",
|
|
)
|
|
|
|
# Verify that everything looks good still.
|
|
self.assertEqual(
|
|
len(clone),
|
|
7,
|
|
)
|
|
self.assertEqual(
|
|
clone[:],
|
|
b"0123456",
|
|
)
|
|
|
|
def test_search_basic(self) -> None:
|
|
fb = FileBytes(io.BytesIO((b"\0" * 54321) + (b"0123456789") + (b"\0" * 54321)))
|
|
self.assertEqual(
|
|
fb.search(b"0123456789"),
|
|
54321,
|
|
)
|
|
self.assertEqual(
|
|
fb.search(b"4567"),
|
|
54325,
|
|
)
|
|
self.assertEqual(
|
|
fb.search(b"abcde"),
|
|
None,
|
|
)
|
|
|
|
def test_search_bounds(self) -> None:
|
|
fb = FileBytes(io.BytesIO((b"\0" * 5) + (b"0123456789") + (b"\0" * 5)))
|
|
self.assertEqual(
|
|
fb.search(b"0123456789", start=5),
|
|
5,
|
|
)
|
|
self.assertEqual(
|
|
fb.search(b"0123456789", start=6),
|
|
None,
|
|
)
|
|
self.assertEqual(
|
|
fb.search(b"0123456789", end=15),
|
|
5,
|
|
)
|
|
self.assertEqual(
|
|
fb.search(b"0123456789", end=14),
|
|
None,
|
|
)
|
|
self.assertEqual(
|
|
fb.search(b"0123456789", start=3, end=18),
|
|
5,
|
|
)
|
|
self.assertEqual(
|
|
fb.search(b"0123456789", start=5, end=15),
|
|
5,
|
|
)
|
|
|
|
def test_search_edges(self) -> None:
|
|
fb = FileBytes(io.BytesIO((b"\0" * 5) + (b"0123456789")))
|
|
self.assertEqual(
|
|
fb.search(b"0123456789"),
|
|
5,
|
|
)
|
|
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
self.assertEqual(
|
|
fb.search(b"0123456789"),
|
|
0,
|
|
)
|
|
|
|
fb = FileBytes(io.BytesIO(b"0123456789" + (b"\0" * 5)))
|
|
self.assertEqual(
|
|
fb.search(b"0123456789"),
|
|
0,
|
|
)
|
|
|
|
def test_search_random(self) -> None:
|
|
for _ in range(25):
|
|
location = random.randint(1, 2000)
|
|
fb = FileBytes(io.BytesIO((b"\0" * location) + (b"12345") + (b"\0" * random.randint(1, 2000))))
|
|
self.assertEqual(
|
|
fb.search(b"12345"),
|
|
location,
|
|
)
|
|
|
|
def test_write_new_file(self) -> None:
|
|
fb = FileBytes(io.BytesIO(b"0123456789"))
|
|
|
|
fb[3] = 97
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012a456789",
|
|
)
|
|
|
|
fb[7:9] = b"bc"
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012a456bc9",
|
|
)
|
|
|
|
fb[4:8:2] = b"de"
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012ad5ebc9",
|
|
)
|
|
fb[-1] = 102
|
|
self.assertEqual(
|
|
fb[:],
|
|
b"012ad5ebcf",
|
|
)
|
|
|
|
# Verify that it gets serialized correctly to a new file.
|
|
new_file = io.BytesIO(b"")
|
|
|
|
fb.write_changes(new_file)
|
|
handle = fb.handle
|
|
if not isinstance(handle, io.BytesIO):
|
|
raise Exception("File handle changed type somehow!")
|
|
|
|
# Make sure original file didn't get modified.
|
|
self.assertEqual(
|
|
handle.getvalue(),
|
|
b"0123456789",
|
|
)
|
|
|
|
# Make sure new file did get modified.
|
|
self.assertEqual(
|
|
new_file.getvalue(),
|
|
b"012ad5ebcf",
|
|
)
|