From 8ac5ec17bf747594335c11edbb26c6d658871935 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Tue, 4 Feb 2025 16:01:12 +0100 Subject: [PATCH] Python 3.14: Call __annotate__ on type objects to get annotations Fixes https://github.com/jcrist/msgspec/issues/795 --- msgspec/_core.c | 10 +++++++++- msgspec/_utils.py | 7 ++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/msgspec/_core.c b/msgspec/_core.c index 147ad95a..d9f07940 100644 --- a/msgspec/_core.c +++ b/msgspec/_core.c @@ -5817,7 +5817,15 @@ structmeta_collect_fields(StructMetaInfo *info, MsgspecState *mod, bool kwonly) PyObject *annotations = PyDict_GetItemString( info->namespace, "__annotations__" ); - if (annotations == NULL) return 0; + if (annotations == NULL) { + PyObject *annotate = PyDict_GetItemString( + info->namespace, "__annotate__" + ); + if (annotate == NULL) return 0; + PyObject *format = PyLong_FromLong(1); /* annotationlib.Format.VALUE */ + annotations = PyObject_CallOneArg(annotate, format); + Py_XDECREF(format); + } if (!PyDict_Check(annotations)) { PyErr_SetString(PyExc_TypeError, "__annotations__ must be a dict"); diff --git a/msgspec/_utils.py b/msgspec/_utils.py index 6d338104..01e52644 100644 --- a/msgspec/_utils.py +++ b/msgspec/_utils.py @@ -149,7 +149,12 @@ def get_class_annotations(obj): cls_locals = dict(vars(cls)) cls_globals = getattr(sys.modules.get(cls.__module__, None), "__dict__", {}) - ann = cls.__dict__.get("__annotations__", {}) + if "__annotations__" in cls.__dict__: + ann = cls.__dict__["__annotations__"] + elif "__annotate__" in cls.__dict__: + ann = cls.__dict__["__annotate__"](1) # annotationlib.Format.VALUE + else: + ann = {} for name, value in ann.items(): if name in hints: continue