From 7d04cb32737d13245820bc7a5d37d75d1533926d Mon Sep 17 00:00:00 2001 From: sheidan Date: Tue, 30 May 2023 19:02:25 +0200 Subject: [PATCH 1/4] fix nested unions in structures in the opposite system byteorder --- Lib/ctypes/_endian.py | 2 +- Lib/test/test_ctypes/test_byteswap.py | 20 +++++++++++++++++++ ...-05-30-18-30-11.gh-issue-105102.SnpK04.rst | 2 ++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 Misc/NEWS.d/next/Library/2023-05-30-18-30-11.gh-issue-105102.SnpK04.rst diff --git a/Lib/ctypes/_endian.py b/Lib/ctypes/_endian.py index b5446c049bc9dc..f6e64e7005814c 100644 --- a/Lib/ctypes/_endian.py +++ b/Lib/ctypes/_endian.py @@ -16,7 +16,7 @@ def _other_endian(typ): if isinstance(typ, _array_type): return _other_endian(typ._type_) * typ._length_ # if typ is structure - if issubclass(typ, Structure): + if issubclass(typ, Structure | Union): return typ raise TypeError("This type does not support other endian: %s" % typ) diff --git a/Lib/test/test_ctypes/test_byteswap.py b/Lib/test/test_ctypes/test_byteswap.py index 7e98559dfbccb6..49c7814659cec4 100644 --- a/Lib/test/test_ctypes/test_byteswap.py +++ b/Lib/test/test_ctypes/test_byteswap.py @@ -359,6 +359,26 @@ class TestUnion(parent): del ctypes._pointer_type_cache[TestUnion] self.assertEqual(s.point.x, 1) self.assertEqual(s.point.y, 2) + + def test_build_struct_union_opposite_system_byteorder(self): + # gh-105102 + if sys.byteorder == "little": + _Structure = BigEndianStructure + _Union = BigEndianUnion + else: + _Structure = LittleEndianStructure + _Union = LittleEndianUnion + + class S1(_Structure): + _fields_ = [("a", c_byte), ("b", c_byte)] + + class U1(_Union): + _fields_ = [("s1", S1), ("ab", c_short)] + + class S2(_Structure): + _fields_ = [("u1", U1), ("c", c_byte)] + + if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS.d/next/Library/2023-05-30-18-30-11.gh-issue-105102.SnpK04.rst b/Misc/NEWS.d/next/Library/2023-05-30-18-30-11.gh-issue-105102.SnpK04.rst new file mode 100644 index 00000000000000..7ca21afefa3132 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-30-18-30-11.gh-issue-105102.SnpK04.rst @@ -0,0 +1,2 @@ +Allow :class:`ctypes.Union` to be nested in :class:`ctypes.Structure` when +the system endianness is the opposite of the classes. From 9fe132465912f867ccad8d38a77eb2a2f8eeae2c Mon Sep 17 00:00:00 2001 From: sheidan Date: Tue, 30 May 2023 19:13:41 +0200 Subject: [PATCH 2/4] trim trailing whitespace --- Lib/test/test_ctypes/test_byteswap.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/test/test_ctypes/test_byteswap.py b/Lib/test/test_ctypes/test_byteswap.py index 49c7814659cec4..3e22c510c5e1f6 100644 --- a/Lib/test/test_ctypes/test_byteswap.py +++ b/Lib/test/test_ctypes/test_byteswap.py @@ -377,8 +377,6 @@ class U1(_Union): class S2(_Structure): _fields_ = [("u1", U1), ("c", c_byte)] - - if __name__ == "__main__": unittest.main() From 28497bc95f58c631e7d89e902a9a971928e91ea5 Mon Sep 17 00:00:00 2001 From: sheidan Date: Tue, 30 May 2023 19:18:02 +0200 Subject: [PATCH 3/4] trim trailing whitespace --- Lib/test/test_ctypes/test_byteswap.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_ctypes/test_byteswap.py b/Lib/test/test_ctypes/test_byteswap.py index 3e22c510c5e1f6..4aa1814d62ea12 100644 --- a/Lib/test/test_ctypes/test_byteswap.py +++ b/Lib/test/test_ctypes/test_byteswap.py @@ -359,7 +359,7 @@ class TestUnion(parent): del ctypes._pointer_type_cache[TestUnion] self.assertEqual(s.point.x, 1) self.assertEqual(s.point.y, 2) - + def test_build_struct_union_opposite_system_byteorder(self): # gh-105102 if sys.byteorder == "little": @@ -368,13 +368,13 @@ def test_build_struct_union_opposite_system_byteorder(self): else: _Structure = LittleEndianStructure _Union = LittleEndianUnion - + class S1(_Structure): _fields_ = [("a", c_byte), ("b", c_byte)] - + class U1(_Union): _fields_ = [("s1", S1), ("ab", c_short)] - + class S2(_Structure): _fields_ = [("u1", U1), ("c", c_byte)] From 00cb70b1a154d9f2dad84c398def1d87ba4feab1 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Wed, 17 Jan 2024 20:01:32 +0200 Subject: [PATCH 4/4] Update _endian.py --- Lib/ctypes/_endian.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/ctypes/_endian.py b/Lib/ctypes/_endian.py index 4276ffe40dbf00..6382dd22b8acc8 100644 --- a/Lib/ctypes/_endian.py +++ b/Lib/ctypes/_endian.py @@ -15,8 +15,8 @@ def _other_endian(typ): # if typ is array if isinstance(typ, _array_type): return _other_endian(typ._type_) * typ._length_ - # if typ is structure - if issubclass(typ, Structure | Union): + # if typ is structure or union + if issubclass(typ, (Structure, Union)): return typ raise TypeError("This type does not support other endian: %s" % typ)