diff --git a/Lib/ctypes/util.py b/Lib/ctypes/util.py index b035bfb99feee0a..1b1a7ca0bcc8183 100644 --- a/Lib/ctypes/util.py +++ b/Lib/ctypes/util.py @@ -512,7 +512,8 @@ def _process_struct(decorated_class, /, *, align, layout, endian, pack): fields.extend(decorated_class._fields_) anonymous.extend(decorated_class._anonymous_) - for name, hint in annotationlib.get_annotations(decorated_class).items(): + annotations = annotationlib.get_annotations(decorated_class, eval_str=True) + for name, hint in annotations.items(): if get_origin(hint) is ClassVar: continue diff --git a/Lib/test/test_ctypes/struct_str_ann.py b/Lib/test/test_ctypes/struct_str_ann.py new file mode 100644 index 000000000000000..7a924825dd81eeb --- /dev/null +++ b/Lib/test/test_ctypes/struct_str_ann.py @@ -0,0 +1,15 @@ +from __future__ import annotations +from ctypes.util import struct +from ctypes import c_int + +class TestAnn: + x: c_int + +# Check that "from __future__ import annotations" works as expected +if not isinstance(TestAnn.__annotations__['x'], str): + raise Exception("annotations must be strings") + +@struct +class Point: + x: c_int + y: c_int diff --git a/Lib/test/test_ctypes/test_structures.py b/Lib/test/test_ctypes/test_structures.py index 4dc1ea867c0700a..04c3682e8308ece 100644 --- a/Lib/test/test_ctypes/test_structures.py +++ b/Lib/test/test_ctypes/test_structures.py @@ -88,13 +88,14 @@ class X(Structure): self.assertEqual(sizeof(X), min(8, longlong_align) + longlong_size) self.assertEqual(X.b.offset, min(8, longlong_align)) - with self.assertRaises(ValueError): - if use_struct_util: + if use_struct_util: + with self.assertRaises(NameError): @struct_util(pack=-1, layout='ms') class X: a: "b" b: "q" - else: + else: + with self.assertRaises(ValueError): class X(Structure): _fields_ = [("a", "b"), ("b", "q")] _pack_ = -1 @@ -954,6 +955,12 @@ class Foo: self.assertEqual(Foo.__name__, "Foo") + def test_string_annotations(self): + from test.test_ctypes import struct_str_ann + Point = struct_str_ann.Point + fields = [['x', c_int], ['y', c_int]] + self.assertEqual(Point._fields_, fields) + if __name__ == '__main__': unittest.main()