def test_f_attribute(self): context = ParsingContext(parent=ParsingContext( parent=ParsingContext()._add_values({ 'foo': 9, 'bar': 10 }))._add_values({ 'a': 3, 'b': 4 }))._add_values({'x': 1}) self.assertEqual(1, context.f.x) self.assertEqual(3, context.f._.a) self.assertEqual(4, context.f._.b) self.assertEqual(9, context.f._root.foo) self.assertEqual(10, context.f._root.bar) self.assertIs(context, context.f._context)
def test_capture_raw_from_context(self): class S(Structure): a = FixedLengthField(length=6) s = S.from_bytes(b"abcdef", ParsingContext(capture_raw=True)) self.assertFalse(hasattr(s._context.stream, 'cache_read_last')) self.assertEqual(b"abcdef", s._context.fields['a'].raw)
def test_raw_bytes_are_not_read_if_capture_is_false(self): context = ParsingContext(capture_raw=False) class TestStructure(Structure): field1 = StringField(length=5) TestStructure.from_stream(io.BytesIO(b"abcdef"), context) self.assertEqual(None, context.fields['field1'].raw)
def test_raw_bytes_are_read(self): context = ParsingContext(capture_raw=True) class TestStructure(Structure): field1 = StringField(length=5) TestStructure.from_stream(io.BytesIO(b"abcdef"), context) self.assertEqual(b"abcde", context.fields['field1'].raw)
def test_terminator_handler_until_with_peek_multibyte_misaligned_field( self): with self.subTest("step larger than terminator length"): pio = PeekableBytesIO(b"1231231\0\0") field = BytesField(terminator=b"\0\0", step=3, terminator_handler='until') result = field.from_stream(pio, ParsingContext()) self.assertEqual(b"1231231", result[0]) self.assertEqual(b"\0\0", pio.read(2)) with self.subTest("step smaller than terminator length"): pio = PeekableBytesIO(b"1231231\0\0") field = BytesField(terminator=b"\0\0", step=1, terminator_handler='until') result = field.from_stream(pio, ParsingContext()) self.assertEqual(b"1231231", result[0]) self.assertEqual(b"\0\0", pio.read(2))
def test_finalizer_called(self): class TestStructure(Structure): field1 = FixedLengthField(length=3) context = ParsingContext() with mock.patch.object(TestStructure, 'finalize', side_effect=lambda x: x) as mock_method: TestStructure(field1=b'asd').to_stream(io.BytesIO(), context) mock_method.assert_called_once_with(context)
def show(structure, stream): if not issubclass(structure, Structure): raise ValueError(f"{structure!r} is not a Structure") if isinstance(stream, bytes): raw = stream else: raw = stream.read() context = ParsingContext(structure) structure.from_stream(io.BytesIO(raw), context) gui = TkStructViewer(context, raw) gui.run()
def test_fieldcontext(self): class Struct1(Structure): byte1 = FixedLengthField(length=1) class Struct2(Structure): s = StructureField(Struct1) with self.subTest("from_stream"): context = ParsingContext() Struct2.from_stream(io.BytesIO(b"\0"), context) self.assertIsInstance(context.fields['s'].subcontext, ParsingContext) self.assertEqual( b"\0", context.fields['s'].subcontext.fields['byte1'].value) with self.subTest("to_stream"): context = ParsingContext() Struct2(s=Struct1(byte1=b"\0")).to_stream(io.BytesIO(), context) self.assertIsInstance(context.fields['s'].subcontext, ParsingContext) self.assertEqual( b"\0", context.fields['s'].subcontext.fields['byte1'].value)
def test_context(self): class TestStruct(Structure): numbers = ArrayField(IntegerField(length=1), count=3) context = ParsingContext() TestStruct.from_stream(io.BytesIO(b'\x02\x01\x03'), context) self.assertIsInstance(context.fields['numbers'].subcontext, ParsingContext) self.assertEqual(2, context.fields['numbers'].subcontext.fields[0].value) self.assertEqual(1, context.fields['numbers'].subcontext.fields[1].value) self.assertEqual(3, context.fields['numbers'].subcontext.fields[2].value)
def test_terminator_handler_until_with_peek(self): pio = PeekableBytesIO(b"abcdef\0gh") field = BytesField(terminator=b"\0", terminator_handler='until') result = field.from_stream(pio, ParsingContext()) self.assertEqual(b"abcdef", result[0]) self.assertEqual(b"\0", pio.read(1))
def call_field_to_stream(self, field, value, *, field_values=None): stream = io.BytesIO() context = ParsingContext()._add_values(field_values) field.to_stream(stream, value, context) return stream.getvalue()
def call_field_from_stream(self, field, value, *, field_values=None): context = ParsingContext()._add_values(field_values) return field.from_stream(io.BytesIO(value), context)
def test_child_context_capture_raw(self): context = ParsingContext(capture_raw=True)._add_values({'x': 1}) subcontext = context.fields['x'].create_subcontext() self.assertFalse(subcontext.capture_raw)
def test_child_context(self): context = ParsingContext()._add_values({'x': 1}) subcontext = context.fields['x'].create_subcontext() self.assertIs(context.fields['x'].subcontext, subcontext)
def test_f_attribute_no_parent(self): context = ParsingContext()._add_values({'x': 1}) self.assertEqual(1, context.f.x) self.assertEqual(None, context.f._) self.assertIs(context.f, context.f._root)