From 385e10a9b9cd042465173bcb1dafded02319bc23 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Sat, 7 Oct 2023 11:49:44 +0200 Subject: [PATCH 01/10] Add optional `padding` parameter to `chunks` If `padding` is given, the first and final chunks are padded to conform to `size` and `alignment`, which is otherwise not guaranteed. --- bincopy.py | 27 ++++++++++++++++++--------- tests/test_bincopy.py | 11 +++++++++++ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/bincopy.py b/bincopy.py index c26b486..700f0ea 100755 --- a/bincopy.py +++ b/bincopy.py @@ -361,22 +361,31 @@ def __init__(self, minimum_address, maximum_address, data, word_size_bytes): def address(self): return self.minimum_address // self.word_size_bytes - def chunks(self, size=32, alignment=1): + def chunks(self, size=32, alignment=1, padding=b''): """Return chunks of the data aligned as given by `alignment`. `size` - must be a multiple of `alignment`. Each chunk is itself a Segment. - Both `size` and `alignment` are in words. + must be a multiple of `alignment`. Optionally, the first and final + chunks can be padded to make them conform to `size` and `alignment`. + Each chunk is itself a Segment. Both `size` and `alignment` are in + words, `padding` is a single byte or empty. """ if (size % alignment) != 0: raise Error(f'size {size} is not a multiple of alignment {alignment}') + + if len(padding) > 1: + raise Error('padding must be a single byte value or empty') size *= self.word_size_bytes alignment *= self.word_size_bytes - address = self.minimum_address - data = self.data - - # First chunk may be shorter than `size` due to alignment. + align_offset = self.minimum_address % alignment * len(padding) + address = self.minimum_address - align_offset + # Align first chunk if padding is non-empty. + data = align_offset * padding + self.data + # Pad final chunk to `size` if padding is non-empty. + data += padding * ((size - (len(data) % size)) % size) + + # First chunk may be non-aligned and shorter than `size` if padding is empty. chunk_offset = (address % alignment) if chunk_offset != 0: @@ -632,7 +641,7 @@ def remove(self, minimum_address, maximum_address): self._list = new_list - def chunks(self, size=32, alignment=1): + def chunks(self, size=32, alignment=1, padding=b''): """Iterate over all segments and return chunks of the data aligned as given by `alignment`. `size` must be a multiple of `alignment`. Each chunk is in turn a smaller Segment. Both `size` and @@ -644,7 +653,7 @@ def chunks(self, size=32, alignment=1): raise Error(f'size {size} is not a multiple of alignment {alignment}') for segment in self: - for chunk in segment.chunks(size, alignment): + for chunk in segment.chunks(size, alignment, padding): yield chunk def __len__(self): diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 3a81584..49a53e3 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -1863,6 +1863,17 @@ def test_add_microchip_hex_record(self): first_word = int.from_bytes(binfile[:binfile.minimum_address + 1], 'little') self.assertEqual(0xC9E4, first_word) + def test_chunk_padding(self): + records = (':02000004000AF0\n' + ':10B8440000000000000000009630000007770000B0\n') + hexfile = bincopy.BinFile() + hexfile.add_ihex(records) + align = 8 + size = 16 + chunks = hexfile.segments.chunks(size=16, alignment=align, padding=b'\xff') + chunks = list(chunks) + assert not any(c.address % align for c in chunks) + assert all(len(c) == size for c in chunks) if __name__ == '__main__': unittest.main() From dcae45659f4e18663807f5d9e7481cdb74ada22e Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Sat, 7 Oct 2023 14:25:12 +0200 Subject: [PATCH 02/10] Add test for padding parameter --- bincopy.py | 17 +++++++++++------ tests/test_bincopy.py | 6 ++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/bincopy.py b/bincopy.py index 700f0ea..ea36162 100755 --- a/bincopy.py +++ b/bincopy.py @@ -362,7 +362,7 @@ def address(self): return self.minimum_address // self.word_size_bytes def chunks(self, size=32, alignment=1, padding=b''): - """Return chunks of the data aligned as given by `alignment`. `size` + """Yield chunks of the data aligned as given by `alignment`. `size` must be a multiple of `alignment`. Optionally, the first and final chunks can be padded to make them conform to `size` and `alignment`. Each chunk is itself a Segment. Both `size` and `alignment` are in @@ -372,7 +372,7 @@ def chunks(self, size=32, alignment=1, padding=b''): if (size % alignment) != 0: raise Error(f'size {size} is not a multiple of alignment {alignment}') - + if len(padding) > 1: raise Error('padding must be a single byte value or empty') @@ -642,16 +642,21 @@ def remove(self, minimum_address, maximum_address): self._list = new_list def chunks(self, size=32, alignment=1, padding=b''): - """Iterate over all segments and return chunks of the data aligned as - given by `alignment`. `size` must be a multiple of - `alignment`. Each chunk is in turn a smaller Segment. Both `size` and - `alignment` are in words. + """Iterate over all segments and yield chunks of the data aligned as + given by `alignment`. Optionally, the first and final chunks can be + padded to make them conform to `size` and `alignment`. `size` must be + a multiple of `alignment`. Each chunk is in turn a smaller Segment. + Both `size` and `alignment` are in words, `padding` is a single byte + or empty. """ if (size % alignment) != 0: raise Error(f'size {size} is not a multiple of alignment {alignment}') + if len(padding) > 1: + raise Error('padding must be a single byte value or empty') + for segment in self: for chunk in segment.chunks(size, alignment, padding): yield chunk diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 49a53e3..2a55092 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -910,6 +910,12 @@ def test_chunks_bad_arguments(self): self.assertEqual(str(cm.exception), 'size 4 is not a multiple of alignment 8') + with self.assertRaises(bincopy.Error) as cm: + list(binfile.segments.chunks(padding=b'\xff\x00')) + + self.assertEqual(str(cm.exception), + 'padding must be a single byte value or empty') + def test_segment(self): binfile = bincopy.BinFile() binfile.add_binary(b'\x00\x01\x02\x03\x04', 2) From 9331d5536c6a098b2c399b40ef9fb3d04980f061 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Sun, 8 Oct 2023 20:04:34 +0200 Subject: [PATCH 03/10] Make chunk padding word sized --- bincopy.py | 56 +++++++++++++++++++++++++++---------------- tests/test_bincopy.py | 8 +++---- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/bincopy.py b/bincopy.py index ea36162..ab1c563 100755 --- a/bincopy.py +++ b/bincopy.py @@ -362,28 +362,35 @@ def address(self): return self.minimum_address // self.word_size_bytes def chunks(self, size=32, alignment=1, padding=b''): - """Yield chunks of the data aligned as given by `alignment`. `size` - must be a multiple of `alignment`. Optionally, the first and final - chunks can be padded to make them conform to `size` and `alignment`. - Each chunk is itself a Segment. Both `size` and `alignment` are in - words, `padding` is a single byte or empty. + """Yield data chunks of `size` words, aligned as given by `alignment`. + + Each chunk is itself a Segment. + + `size` and `alignment` are in words. `size` must be a multiple of + `alignment`. + + If `padding` is set, the first and final chunks are padded so that: + 1. The first chunk is aligned even if the segment itself is not. + 2. The final chunk's size is a multiple of `alignment`. """ if (size % alignment) != 0: raise Error(f'size {size} is not a multiple of alignment {alignment}') - if len(padding) > 1: - raise Error('padding must be a single byte value or empty') + if padding and len(padding) != self.word_size_bytes: + raise Error(f'padding must be same length as word ({self.word_size_bytes})') size *= self.word_size_bytes alignment *= self.word_size_bytes - align_offset = self.minimum_address % alignment * len(padding) - address = self.minimum_address - align_offset - # Align first chunk if padding is non-empty. - data = align_offset * padding + self.data - # Pad final chunk to `size` if padding is non-empty. - data += padding * ((size - (len(data) % size)) % size) + address = self.minimum_address + data = self.data + + # Apply padding to first and final chunk, if padding is non-empty. + align_offset = address % alignment + address -= align_offset * bool(padding) + data = align_offset // self.word_size_bytes * padding + data + data += (alignment - len(data)) % alignment // self.word_size_bytes * padding # First chunk may be non-aligned and shorter than `size` if padding is empty. chunk_offset = (address % alignment) @@ -642,20 +649,27 @@ def remove(self, minimum_address, maximum_address): self._list = new_list def chunks(self, size=32, alignment=1, padding=b''): - """Iterate over all segments and yield chunks of the data aligned as - given by `alignment`. Optionally, the first and final chunks can be - padded to make them conform to `size` and `alignment`. `size` must be - a multiple of `alignment`. Each chunk is in turn a smaller Segment. - Both `size` and `alignment` are in words, `padding` is a single byte - or empty. + """Iterate over all segments and yield chunks of the data. + + The chunks are `size` words long, aligned as given by `alignment`. + + Each chunk is itself a Segment. + + `size` and `alignment` are in words. `size` must be a multiple of + `alignment`. + + If `padding` is set, the first and final chunks of each segment are + padded so that: + 1. The first chunk is aligned even if the segment itself is not. + 2. The final chunk's size is a multiple of `alignment`. """ if (size % alignment) != 0: raise Error(f'size {size} is not a multiple of alignment {alignment}') - if len(padding) > 1: - raise Error('padding must be a single byte value or empty') + if padding and len(padding) != self.word_size_bytes: + raise Error(f'padding must be same length as word ({self.word_size_bytes})') for segment in self: for chunk in segment.chunks(size, alignment, padding): diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 2a55092..a16d453 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -911,10 +911,10 @@ def test_chunks_bad_arguments(self): 'size 4 is not a multiple of alignment 8') with self.assertRaises(bincopy.Error) as cm: - list(binfile.segments.chunks(padding=b'\xff\x00')) + list(binfile.segments.chunks(padding=b'\xff\xff')) self.assertEqual(str(cm.exception), - 'padding must be a single byte value or empty') + 'padding must be same length as word (1)') def test_segment(self): binfile = bincopy.BinFile() @@ -1876,10 +1876,10 @@ def test_chunk_padding(self): hexfile.add_ihex(records) align = 8 size = 16 - chunks = hexfile.segments.chunks(size=16, alignment=align, padding=b'\xff') + chunks = hexfile.segments.chunks(size=size, alignment=align, padding=b'\xff') chunks = list(chunks) assert not any(c.address % align for c in chunks) - assert all(len(c) == size for c in chunks) + assert not any(len(c) % align for c in chunks) if __name__ == '__main__': unittest.main() From 4ce09240a4328f51eb6ff2c3db9ca2c575c7a42d Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Sun, 8 Oct 2023 20:32:32 +0200 Subject: [PATCH 04/10] Specify chunks padding size in docstring --- bincopy.py | 10 ++++++---- tests/test_bincopy.py | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/bincopy.py b/bincopy.py index ab1c563..460d1dc 100755 --- a/bincopy.py +++ b/bincopy.py @@ -367,7 +367,7 @@ def chunks(self, size=32, alignment=1, padding=b''): Each chunk is itself a Segment. `size` and `alignment` are in words. `size` must be a multiple of - `alignment`. + `alignment`. If set, `padding` must be a word value. If `padding` is set, the first and final chunks are padded so that: 1. The first chunk is aligned even if the segment itself is not. @@ -379,7 +379,8 @@ def chunks(self, size=32, alignment=1, padding=b''): raise Error(f'size {size} is not a multiple of alignment {alignment}') if padding and len(padding) != self.word_size_bytes: - raise Error(f'padding must be same length as word ({self.word_size_bytes})') + raise Error(f'padding must be a word value (size {self.word_size_bytes}),' + f' got {padding}') size *= self.word_size_bytes alignment *= self.word_size_bytes @@ -656,7 +657,7 @@ def chunks(self, size=32, alignment=1, padding=b''): Each chunk is itself a Segment. `size` and `alignment` are in words. `size` must be a multiple of - `alignment`. + `alignment`. If set, `padding` must be a word value. If `padding` is set, the first and final chunks of each segment are padded so that: @@ -669,7 +670,8 @@ def chunks(self, size=32, alignment=1, padding=b''): raise Error(f'size {size} is not a multiple of alignment {alignment}') if padding and len(padding) != self.word_size_bytes: - raise Error(f'padding must be same length as word ({self.word_size_bytes})') + raise Error(f'padding must be a word value (size {self.word_size_bytes}),' + f' got {padding}') for segment in self: for chunk in segment.chunks(size, alignment, padding): diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index a16d453..0458af4 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -914,7 +914,7 @@ def test_chunks_bad_arguments(self): list(binfile.segments.chunks(padding=b'\xff\xff')) self.assertEqual(str(cm.exception), - 'padding must be same length as word (1)') + r"padding must be a word value (size 1), got b'\xff\xff'") def test_segment(self): binfile = bincopy.BinFile() From bdb4a486b2cd22447c74d3b2da91a1d6b0443726 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Mon, 9 Oct 2023 22:36:23 +0200 Subject: [PATCH 05/10] Merge overlapping chunks --- bincopy.py | 18 ++++++++++++++++++ tests/test_bincopy.py | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/bincopy.py b/bincopy.py index 460d1dc..1c0dd8b 100755 --- a/bincopy.py +++ b/bincopy.py @@ -673,10 +673,28 @@ def chunks(self, size=32, alignment=1, padding=b''): raise Error(f'padding must be a word value (size {self.word_size_bytes}),' f' got {padding}') + previous = Segment(-1, -1, b'', 1) + for segment in self: + # When chunks are padded to alignment, the final chunk of the previous + # segment and the first chunk of the current segment may align to the + # same address. To avoid overwriting data from the lower segment, the + # chunks must be merged. + merge = previous.address == segment.address - segment.address % alignment + for chunk in segment.chunks(size, alignment, padding): + # If padding is set, the first chunk's address can be less than the + # segment's. + if merge and chunk.address < segment.address: + low = int.from_bytes(previous.data, 'big') + high = int.from_bytes(chunk.data, 'big') + null = int.from_bytes(size * padding, 'big') + chunk.data = int.to_bytes(low ^ high ^ null, size, 'big') + yield chunk + previous = chunk + def __len__(self): """Get the number of segments. diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 0458af4..975a620 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -1881,5 +1881,16 @@ def test_chunk_padding(self): assert not any(c.address % align for c in chunks) assert not any(len(c) % align for c in chunks) + def test_merge_chunks(self): + records = (':0100000010EF\n' + ':0100020020DD\n') + hexfile = bincopy.BinFile() + hexfile.add_ihex(records) + align = 4 + size = 4 + chunks = hexfile.segments.chunks(size=size, alignment=align, padding=b'\xff') + chunks = list(chunks) + assert chunks[-1].data == b'\x10\xff \xff' + if __name__ == '__main__': unittest.main() From 2de63df32a9ca1ab4dc6b6e41335c6d62567d0e8 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Mon, 9 Oct 2023 22:43:52 +0200 Subject: [PATCH 06/10] fixup: Consider word size when merging chunks --- bincopy.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bincopy.py b/bincopy.py index 1c0dd8b..28ed5f6 100755 --- a/bincopy.py +++ b/bincopy.py @@ -689,7 +689,8 @@ def chunks(self, size=32, alignment=1, padding=b''): low = int.from_bytes(previous.data, 'big') high = int.from_bytes(chunk.data, 'big') null = int.from_bytes(size * padding, 'big') - chunk.data = int.to_bytes(low ^ high ^ null, size, 'big') + chunk.data = int.to_bytes(low ^ high ^ null, + size * self.word_size_bytes, 'big') yield chunk From 5bc05ae1ad0a19a9dd16b4b6ca06f64d3417d017 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Tue, 10 Oct 2023 13:03:41 +0200 Subject: [PATCH 07/10] Simplify chunk overlap check --- bincopy.py | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/bincopy.py b/bincopy.py index 28ed5f6..a6a6264 100755 --- a/bincopy.py +++ b/bincopy.py @@ -676,20 +676,15 @@ def chunks(self, size=32, alignment=1, padding=b''): previous = Segment(-1, -1, b'', 1) for segment in self: - # When chunks are padded to alignment, the final chunk of the previous - # segment and the first chunk of the current segment may align to the - # same address. To avoid overwriting data from the lower segment, the - # chunks must be merged. - merge = previous.address == segment.address - segment.address % alignment - for chunk in segment.chunks(size, alignment, padding): - # If padding is set, the first chunk's address can be less than the - # segment's. - if merge and chunk.address < segment.address: - low = int.from_bytes(previous.data, 'big') - high = int.from_bytes(chunk.data, 'big') - null = int.from_bytes(size * padding, 'big') - chunk.data = int.to_bytes(low ^ high ^ null, + # When chunks are padded to alignment, the final chunk of the previous + # segment and the first chunk of the current segment may align to the + # same address. To avoid overwriting data from the lower segment, the + # chunks must be merged. + if chunk.address == previous.address: + chunk.data = int.to_bytes(int.from_bytes(previous.data, 'big') ^ + int.from_bytes(chunk.data, 'big') ^ + int.from_bytes(size * padding, 'big'), size * self.word_size_bytes, 'big') yield chunk From 5e6f5610fae555683544a88079d5c6cb87e762f8 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Tue, 10 Oct 2023 22:13:44 +0200 Subject: [PATCH 08/10] Another attempt at chunk merging --- bincopy.py | 13 ++++++++----- tests/test_bincopy.py | 10 +++++----- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/bincopy.py b/bincopy.py index a6a6264..7d80ee8 100755 --- a/bincopy.py +++ b/bincopy.py @@ -681,11 +681,14 @@ def chunks(self, size=32, alignment=1, padding=b''): # segment and the first chunk of the current segment may align to the # same address. To avoid overwriting data from the lower segment, the # chunks must be merged. - if chunk.address == previous.address: - chunk.data = int.to_bytes(int.from_bytes(previous.data, 'big') ^ - int.from_bytes(chunk.data, 'big') ^ - int.from_bytes(size * padding, 'big'), - size * self.word_size_bytes, 'big') + if chunk.address < previous.address + len(previous): + low = previous.data[-alignment // self.word_size_bytes:] + high = chunk.data[:alignment // self.word_size_bytes] + merged = int.to_bytes(int.from_bytes(low, 'big') ^ + int.from_bytes(high, 'big') ^ + int.from_bytes(alignment * padding, 'big'), + alignment * self.word_size_bytes, 'big') + chunk.data = merged + chunk.data[alignment // self.word_size_bytes:] yield chunk diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 975a620..0a2f6f9 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -1882,15 +1882,15 @@ def test_chunk_padding(self): assert not any(len(c) % align for c in chunks) def test_merge_chunks(self): - records = (':0100000010EF\n' - ':0100020020DD\n') + records = (':0A0000001010101010101010101056\n' + ':0A000E001010101010101010101048\n') hexfile = bincopy.BinFile() hexfile.add_ihex(records) - align = 4 - size = 4 + align = 8 + size = 16 chunks = hexfile.segments.chunks(size=size, alignment=align, padding=b'\xff') chunks = list(chunks) - assert chunks[-1].data == b'\x10\xff \xff' + assert list(chunks[-1]) == [8, b'\x10\x10\xff\xff\xff\xff\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'] if __name__ == '__main__': unittest.main() From bc27cc5abf9bd5372ae9e9206f057d909f2b3014 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Wed, 11 Oct 2023 15:33:22 +0200 Subject: [PATCH 09/10] Fix chunk merging for word size > 1 --- bincopy.py | 12 ++++++------ tests/test_bincopy.py | 12 ++++++++++++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/bincopy.py b/bincopy.py index 7d80ee8..fbe3ba5 100755 --- a/bincopy.py +++ b/bincopy.py @@ -678,17 +678,17 @@ def chunks(self, size=32, alignment=1, padding=b''): for segment in self: for chunk in segment.chunks(size, alignment, padding): # When chunks are padded to alignment, the final chunk of the previous - # segment and the first chunk of the current segment may align to the - # same address. To avoid overwriting data from the lower segment, the - # chunks must be merged. + # segment and the first chunk of the current segment may overlap by + # one alignment block. To avoid overwriting data from the lower + # segment, the chunks must be merged. if chunk.address < previous.address + len(previous): - low = previous.data[-alignment // self.word_size_bytes:] - high = chunk.data[:alignment // self.word_size_bytes] + low = previous.data[-alignment * self.word_size_bytes:] + high = chunk.data[:alignment * self.word_size_bytes] merged = int.to_bytes(int.from_bytes(low, 'big') ^ int.from_bytes(high, 'big') ^ int.from_bytes(alignment * padding, 'big'), alignment * self.word_size_bytes, 'big') - chunk.data = merged + chunk.data[alignment // self.word_size_bytes:] + chunk.data = merged + chunk.data[alignment * self.word_size_bytes:] yield chunk diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 0a2f6f9..12a7c82 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -1892,5 +1892,17 @@ def test_merge_chunks(self): chunks = list(chunks) assert list(chunks[-1]) == [8, b'\x10\x10\xff\xff\xff\xff\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'] + def test_merge_chunks_16(self): + records = (':1000000010101010101010101010101010101010F0\n' + ':10000A0010101010101010101010101010101010E6\n') + hexfile = bincopy.BinFile(word_size_bits=16) + hexfile.add_ihex(records) + align = 6 + size = 12 + chunks = hexfile.segments.chunks(size=size, alignment=align, padding=b'\xff\xff') + chunks = list(chunks) + assert list(chunks[-1]) == [6, b'\x10\x10\x10\x10\xff\xff\xff\xff\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'] + + if __name__ == '__main__': unittest.main() From fe6a9e9338b88bf6736c0a4eddf470253b660961 Mon Sep 17 00:00:00 2001 From: Alexander Bessman Date: Wed, 11 Oct 2023 16:01:54 +0200 Subject: [PATCH 10/10] fixup: style --- tests/test_bincopy.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tests/test_bincopy.py b/tests/test_bincopy.py index 12a7c82..945086a 100644 --- a/tests/test_bincopy.py +++ b/tests/test_bincopy.py @@ -1890,7 +1890,8 @@ def test_merge_chunks(self): size = 16 chunks = hexfile.segments.chunks(size=size, alignment=align, padding=b'\xff') chunks = list(chunks) - assert list(chunks[-1]) == [8, b'\x10\x10\xff\xff\xff\xff\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'] + assert list(chunks[-1]) == [8, b'\x10\x10\xff\xff\xff\xff\x10\x10\x10\x10\x10' + b'\x10\x10\x10\x10\x10'] def test_merge_chunks_16(self): records = (':1000000010101010101010101010101010101010F0\n' @@ -1899,9 +1900,12 @@ def test_merge_chunks_16(self): hexfile.add_ihex(records) align = 6 size = 12 - chunks = hexfile.segments.chunks(size=size, alignment=align, padding=b'\xff\xff') + chunks = hexfile.segments.chunks(size=size, alignment=align, + padding=b'\xff\xff') chunks = list(chunks) - assert list(chunks[-1]) == [6, b'\x10\x10\x10\x10\xff\xff\xff\xff\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10'] + assert list(chunks[-1]) == [6, b'\x10\x10\x10\x10\xff\xff\xff\xff\x10\x10\x10' + b'\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10' + b'\x10\x10'] if __name__ == '__main__':