summaryrefslogtreecommitdiffstats
path: root/Objects/unionobject.c
diff options
context:
space:
mode:
authorYurii Karabas <1998uriyyo@gmail.com>2021-07-23 09:47:00 (GMT)
committerGitHub <noreply@github.com>2021-07-23 09:47:00 (GMT)
commitfe13f0b0f696464dd6f283576668dbf57cb11399 (patch)
treef6ef8c05220fc75cf20cb7eb9e7e2375c0db3ecb /Objects/unionobject.c
parent7d25254cf0763b62f4c4a3019e56385cab597b9f (diff)
downloadcpython-fe13f0b0f696464dd6f283576668dbf57cb11399.zip
cpython-fe13f0b0f696464dd6f283576668dbf57cb11399.tar.gz
cpython-fe13f0b0f696464dd6f283576668dbf57cb11399.tar.bz2
bpo-44676: Add ability to serialize types.Union (GH-27244)
Diffstat (limited to 'Objects/unionobject.c')
-rw-r--r--Objects/unionobject.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/Objects/unionobject.c b/Objects/unionobject.c
index 659346a..ea4aed8 100644
--- a/Objects/unionobject.c
+++ b/Objects/unionobject.c
@@ -299,6 +299,24 @@ is_unionable(PyObject *obj)
return 0;
}
+static int
+is_args_unionable(PyObject *args)
+{
+ Py_ssize_t nargs = PyTuple_GET_SIZE(args);
+ for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
+ PyObject *arg = PyTuple_GET_ITEM(args, iarg);
+ int is_arg_unionable = is_unionable(arg);
+ if (is_arg_unionable <= 0) {
+ if (is_arg_unionable == 0) {
+ PyErr_Format(PyExc_TypeError,
+ "Each union argument must be a type, got %.100R", arg);
+ }
+ return 0;
+ }
+ }
+ return 1;
+}
+
PyObject *
_Py_union_type_or(PyObject* self, PyObject* other)
{
@@ -418,14 +436,47 @@ error:
return NULL;
}
+static PyObject *
+union_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+ unionobject *alias = (unionobject *)self;
+ PyObject* from_args = PyObject_GetAttrString(self, "_from_args");
+ if (from_args == NULL) {
+ return NULL;
+ }
+
+ return Py_BuildValue("O(O)", from_args, alias->args);
+}
+
static PyMemberDef union_members[] = {
{"__args__", T_OBJECT, offsetof(unionobject, args), READONLY},
{0}
};
+static PyObject *
+union_from_args(PyObject *cls, PyObject *args)
+{
+ if (!PyTuple_CheckExact(args)) {
+ _PyArg_BadArgument("Union._from_args", "argument 'args'", "tuple", args);
+ return NULL;
+ }
+ if (!PyTuple_GET_SIZE(args)) {
+ PyErr_SetString(PyExc_ValueError, "args must be not empty");
+ return NULL;
+ }
+
+ if (is_args_unionable(args) <= 0) {
+ return NULL;
+ }
+
+ return make_union(args);
+}
+
static PyMethodDef union_methods[] = {
+ {"_from_args", union_from_args, METH_O | METH_CLASS},
{"__instancecheck__", union_instancecheck, METH_O},
{"__subclasscheck__", union_subclasscheck, METH_O},
+ {"__reduce__", union_reduce, METH_NOARGS},
{0}};