diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index f4fb05c29b4ca45..b99b1ce5a23a9bb 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -1,7 +1,7 @@ import os import sys -from dataclasses import dataclass +from dataclasses import dataclass, _update_func_cell_for__class__ lazy import functools lazy import inspect @@ -478,6 +478,17 @@ class _Struct(endian_class): _fields_ = fields _anonymous_ = anonymous + for member in vars(_Struct).values(): + if not isinstance(member, type) and hasattr(member, '__wrapped__'): + member = inspect.unwrap(member) + if isinstance(member, property): + functions = (member.fget, member.fset, member.fdel) + else: + functions = (member,) + for func in functions: + if inspect.isfunction(func): + _update_func_cell_for__class__(func, decorated_class, _Struct) + return _Struct diff --git a/Lib/test/test_ctypes/test_structures.py b/Lib/test/test_ctypes/test_structures.py index a74a3548ee78413..bc667f2d078de2a 100644 --- a/Lib/test/test_ctypes/test_structures.py +++ b/Lib/test/test_ctypes/test_structures.py @@ -955,6 +955,37 @@ class Foo: self.assertEqual(Foo.__name__, "Foo") + @subTests("endian", ["native", "little", "big"]) + def test_struct_util_class_cell(self, endian): + @struct_util(endian=endian) + class Foo: + x: c_int + + def __init__(self, x=0): + super().__init__(x) + + self.assertEqual(Foo(1).x, 1) + + @struct_util(endian=endian) + class Foo: + x: c_int + + @classmethod + def create(cls): + return super().__new__(cls) + + self.assertIsInstance(Foo.create(), Foo) + + @struct_util(endian=endian) + class Foo: + x: c_int + + @property + def cls(self): + return __class__ + + self.assertIs(Foo().cls, Foo) + def test_string_annotations(self): from test.test_ctypes import struct_str_ann Point = struct_str_ann.Point