Skip to content

Commit 4729976

Browse files
bpo-44662: Add ability to annotate types.Union (GH-27214) (GH-27461)
Co-authored-by: Ken Jin <[email protected]> (cherry picked from commit 8182c83) Co-authored-by: Yurii Karabas <[email protected]>
1 parent 0b984d1 commit 4729976

File tree

3 files changed

+36
-1
lines changed

3 files changed

+36
-1
lines changed

Lib/test/test_typing.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3009,6 +3009,16 @@ def barfoo3(x: BA2): ...
30093009
get_type_hints(barfoo3, globals(), locals(), include_extras=True)["x"],
30103010
BA2
30113011
)
3012+
BA3 = typing.Annotated[int | float, "const"]
3013+
def barfoo4(x: BA3): ...
3014+
self.assertEqual(
3015+
get_type_hints(barfoo4, globals(), locals()),
3016+
{"x": int | float}
3017+
)
3018+
self.assertEqual(
3019+
get_type_hints(barfoo4, globals(), locals(), include_extras=True),
3020+
{"x": typing.Annotated[int | float, "const"]}
3021+
)
30123022

30133023
def test_get_type_hints_annotated_refs(self):
30143024

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Add ``__module__`` to ``types.Union``. This also fixes
2+
``types.Union`` issues with ``typing.Annotated``. Patch provided by
3+
Yurii Karabas.

Objects/unionobject.c

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,28 @@ static PyNumberMethods union_as_number = {
422422
.nb_or = _Py_union_type_or, // Add __or__ function
423423
};
424424

425+
static const char* const cls_attrs[] = {
426+
"__module__", // Required for compatibility with typing module
427+
NULL,
428+
};
429+
430+
static PyObject *
431+
union_getattro(PyObject *self, PyObject *name)
432+
{
433+
unionobject *alias = (unionobject *)self;
434+
if (PyUnicode_Check(name)) {
435+
for (const char * const *p = cls_attrs; ; p++) {
436+
if (*p == NULL) {
437+
break;
438+
}
439+
if (_PyUnicode_EqualToASCIIString(name, *p)) {
440+
return PyObject_GetAttr((PyObject *) Py_TYPE(alias), name);
441+
}
442+
}
443+
}
444+
return PyObject_GenericGetAttr(self, name);
445+
}
446+
425447
PyTypeObject _PyUnion_Type = {
426448
PyVarObject_HEAD_INIT(&PyType_Type, 0)
427449
.tp_name = "types.UnionType",
@@ -435,7 +457,7 @@ PyTypeObject _PyUnion_Type = {
435457
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
436458
.tp_traverse = union_traverse,
437459
.tp_hash = union_hash,
438-
.tp_getattro = PyObject_GenericGetAttr,
460+
.tp_getattro = union_getattro,
439461
.tp_members = union_members,
440462
.tp_methods = union_methods,
441463
.tp_richcompare = union_richcompare,

0 commit comments

Comments
 (0)