summaryrefslogtreecommitdiff
path: root/Objects/unionobject.c
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2021-07-17 22:14:57 +0300
committerGitHub <noreply@github.com>2021-07-17 22:14:57 +0300
commit2d055ce13250a4074f66a945381a149a3cf8c46f (patch)
tree41260fe1f80398f1bfd84517755ac2480a4d409d /Objects/unionobject.c
parente22e8641dd277478b8df7a9fe792ea551adc6932 (diff)
downloadcpython-git-2d055ce13250a4074f66a945381a149a3cf8c46f.tar.gz
[3.10] bpo-44490: Add __parameters__ and __getitem__ to types.Union (GH-26980) (GH-27207)
Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Co-authored-by: Guido van Rossum <gvanrossum@gmail.com>. (cherry picked from commit c45fa1a5d9b419cf13ad4b5a7cb453956495b83e) Co-authored-by: Yurii Karabas <1998uriyyo@gmail.com> Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com>
Diffstat (limited to 'Objects/unionobject.c')
-rw-r--r--Objects/unionobject.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/Objects/unionobject.c b/Objects/unionobject.c
index 15cd6c5c74..b3a6506862 100644
--- a/Objects/unionobject.c
+++ b/Objects/unionobject.c
@@ -8,6 +8,7 @@
typedef struct {
PyObject_HEAD
PyObject *args;
+ PyObject *parameters;
} unionobject;
static void
@@ -18,6 +19,7 @@ unionobject_dealloc(PyObject *self)
_PyObject_GC_UNTRACK(self);
Py_XDECREF(alias->args);
+ Py_XDECREF(alias->parameters);
Py_TYPE(self)->tp_free(self);
}
@@ -26,6 +28,7 @@ union_traverse(PyObject *self, visitproc visit, void *arg)
{
unionobject *alias = (unionobject *)self;
Py_VISIT(alias->args);
+ Py_VISIT(alias->parameters);
return 0;
}
@@ -450,6 +453,53 @@ static PyMethodDef union_methods[] = {
{"__subclasscheck__", union_subclasscheck, METH_O},
{0}};
+
+static PyObject *
+union_getitem(PyObject *self, PyObject *item)
+{
+ unionobject *alias = (unionobject *)self;
+ // Populate __parameters__ if needed.
+ if (alias->parameters == NULL) {
+ alias->parameters = _Py_make_parameters(alias->args);
+ if (alias->parameters == NULL) {
+ return NULL;
+ }
+ }
+
+ PyObject *newargs = _Py_subs_parameters(self, alias->args, alias->parameters, item);
+ if (newargs == NULL) {
+ return NULL;
+ }
+
+ PyObject *res = _Py_Union(newargs);
+
+ Py_DECREF(newargs);
+ return res;
+}
+
+static PyMappingMethods union_as_mapping = {
+ .mp_subscript = union_getitem,
+};
+
+static PyObject *
+union_parameters(PyObject *self, void *Py_UNUSED(unused))
+{
+ unionobject *alias = (unionobject *)self;
+ if (alias->parameters == NULL) {
+ alias->parameters = _Py_make_parameters(alias->args);
+ if (alias->parameters == NULL) {
+ return NULL;
+ }
+ }
+ Py_INCREF(alias->parameters);
+ return alias->parameters;
+}
+
+static PyGetSetDef union_properties[] = {
+ {"__parameters__", union_parameters, (setter)NULL, "Type variables in the types.Union.", NULL},
+ {0}
+};
+
static PyNumberMethods union_as_number = {
.nb_or = _Py_union_type_or, // Add __or__ function
};
@@ -471,8 +521,10 @@ PyTypeObject _Py_UnionType = {
.tp_members = union_members,
.tp_methods = union_methods,
.tp_richcompare = union_richcompare,
+ .tp_as_mapping = &union_as_mapping,
.tp_as_number = &union_as_number,
.tp_repr = union_repr,
+ .tp_getset = union_properties,
};
PyObject *
@@ -516,6 +568,7 @@ _Py_Union(PyObject *args)
return NULL;
}
+ result->parameters = NULL;
result->args = args;
_PyObject_GC_TRACK(result);
return (PyObject*)result;