summaryrefslogtreecommitdiffstats
path: root/Objects/genericaliasobject.c
diff options
context:
space:
mode:
authorYurii Karabas <1998uriyyo@gmail.com>2021-07-06 18:04:33 (GMT)
committerGitHub <noreply@github.com>2021-07-06 18:04:33 (GMT)
commitc45fa1a5d9b419cf13ad4b5a7cb453956495b83e (patch)
treeb3bae903cc808a324c87769f0c5a60e4cd4065c8 /Objects/genericaliasobject.c
parent8b849ea0f3482ad834e7989ff474dd5db2f295c8 (diff)
downloadcpython-c45fa1a5d9b419cf13ad4b5a7cb453956495b83e.zip
cpython-c45fa1a5d9b419cf13ad4b5a7cb453956495b83e.tar.gz
cpython-c45fa1a5d9b419cf13ad4b5a7cb453956495b83e.tar.bz2
bpo-44490: Add __parameters__ and __getitem__ to types.Union (GH-26980)
Co-authored-by: Ken Jin <28750310+Fidget-Spinner@users.noreply.github.com> Co-authored-by: Guido van Rossum <gvanrossum@gmail.com>
Diffstat (limited to 'Objects/genericaliasobject.c')
-rw-r--r--Objects/genericaliasobject.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/Objects/genericaliasobject.c b/Objects/genericaliasobject.c
index 803912b..d3d3871 100644
--- a/Objects/genericaliasobject.c
+++ b/Objects/genericaliasobject.c
@@ -198,8 +198,8 @@ tuple_add(PyObject *self, Py_ssize_t len, PyObject *item)
return 0;
}
-static PyObject *
-make_parameters(PyObject *args)
+PyObject *
+_Py_make_parameters(PyObject *args)
{
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
Py_ssize_t len = nargs;
@@ -294,18 +294,10 @@ subs_tvars(PyObject *obj, PyObject *params, PyObject **argitems)
return obj;
}
-static PyObject *
-ga_getitem(PyObject *self, PyObject *item)
+PyObject *
+_Py_subs_parameters(PyObject *self, PyObject *args, PyObject *parameters, PyObject *item)
{
- gaobject *alias = (gaobject *)self;
- // do a lookup for __parameters__ so it gets populated (if not already)
- if (alias->parameters == NULL) {
- alias->parameters = make_parameters(alias->args);
- if (alias->parameters == NULL) {
- return NULL;
- }
- }
- Py_ssize_t nparams = PyTuple_GET_SIZE(alias->parameters);
+ Py_ssize_t nparams = PyTuple_GET_SIZE(parameters);
if (nparams == 0) {
return PyErr_Format(PyExc_TypeError,
"There are no type variables left in %R",
@@ -320,32 +312,32 @@ ga_getitem(PyObject *self, PyObject *item)
nitems > nparams ? "many" : "few",
self);
}
- /* Replace all type variables (specified by alias->parameters)
+ /* Replace all type variables (specified by parameters)
with corresponding values specified by argitems.
t = list[T]; t[int] -> newargs = [int]
t = dict[str, T]; t[int] -> newargs = [str, int]
t = dict[T, list[S]]; t[str, int] -> newargs = [str, list[int]]
*/
- Py_ssize_t nargs = PyTuple_GET_SIZE(alias->args);
+ Py_ssize_t nargs = PyTuple_GET_SIZE(args);
PyObject *newargs = PyTuple_New(nargs);
if (newargs == NULL) {
return NULL;
}
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
- PyObject *arg = PyTuple_GET_ITEM(alias->args, iarg);
+ PyObject *arg = PyTuple_GET_ITEM(args, iarg);
int typevar = is_typevar(arg);
if (typevar < 0) {
Py_DECREF(newargs);
return NULL;
}
if (typevar) {
- Py_ssize_t iparam = tuple_index(alias->parameters, nparams, arg);
+ Py_ssize_t iparam = tuple_index(parameters, nparams, arg);
assert(iparam >= 0);
arg = argitems[iparam];
Py_INCREF(arg);
}
else {
- arg = subs_tvars(arg, alias->parameters, argitems);
+ arg = subs_tvars(arg, parameters, argitems);
if (arg == NULL) {
Py_DECREF(newargs);
return NULL;
@@ -354,6 +346,26 @@ ga_getitem(PyObject *self, PyObject *item)
PyTuple_SET_ITEM(newargs, iarg, arg);
}
+ return newargs;
+}
+
+static PyObject *
+ga_getitem(PyObject *self, PyObject *item)
+{
+ gaobject *alias = (gaobject *)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_GenericAlias(alias->origin, newargs);
Py_DECREF(newargs);
@@ -550,7 +562,7 @@ ga_parameters(PyObject *self, void *unused)
{
gaobject *alias = (gaobject *)self;
if (alias->parameters == NULL) {
- alias->parameters = make_parameters(alias->args);
+ alias->parameters = _Py_make_parameters(alias->args);
if (alias->parameters == NULL) {
return NULL;
}