Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit eb52dc8

Browse files
committed
Update unionobject
1 parent 43556fe commit eb52dc8

File tree

3 files changed

+51
-50
lines changed

3 files changed

+51
-50
lines changed

Lib/test/test_types.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -782,20 +782,20 @@ def test_union_pickle(self):
782782
self.assertEqual(alias.__args__, loaded.__args__)
783783
self.assertEqual(alias.__parameters__, loaded.__parameters__)
784784

785-
def test_union_new(self):
785+
def test_union_from_args(self):
786786
with self.assertRaisesRegex(
787787
TypeError,
788-
r"^__args__ argument of typing.Union object is not a valid as type$",
788+
r"^Each union argument must be a type, got 1$",
789789
):
790-
types.Union((1,))
790+
types.Union.from_args((1,))
791791

792792
with self.assertRaisesRegex(
793793
TypeError,
794-
r"Union\(\) argument '__args__' must be tuple, not int$",
794+
r"Union.from_args\(\) argument '__args__' must be tuple, not int$",
795795
):
796-
types.Union(1)
796+
types.Union.from_args(1)
797797

798-
alias = types.Union((int, str, T))
798+
alias = types.Union.from_args((int, str, T))
799799

800800
self.assertEqual(alias.__args__, (int, str, T))
801801
self.assertEqual(alias.__parameters__, (T,))

Lib/typing.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,7 @@ def _eval_type(t, globalns, localns, recursive_guard=frozenset()):
322322
if isinstance(t, GenericAlias):
323323
return GenericAlias(t.__origin__, ev_args)
324324
if isinstance(t, types.Union):
325-
return types.Union(ev_args)
325+
return types.Union.from_args(ev_args)
326326
else:
327327
return t.copy_with(ev_args)
328328
return t
@@ -1786,7 +1786,7 @@ def _strip_annotations(t):
17861786
stripped_args = tuple(_strip_annotations(a) for a in t.__args__)
17871787
if stripped_args == t.__args__:
17881788
return t
1789-
return types.Union(stripped_args)
1789+
return types.Union.from_args(stripped_args)
17901790

17911791
return t
17921792

Objects/unionobject.c

Lines changed: 43 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,24 @@ is_unionable(PyObject *obj)
299299
return 0;
300300
}
301301

302+
static int
303+
is_args_unionable(PyObject *args)
304+
{
305+
Py_ssize_t nargs = PyTuple_GET_SIZE(args);
306+
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
307+
PyObject *arg = PyTuple_GET_ITEM(args, iarg);
308+
int is_arg_unionable = is_unionable(arg);
309+
if (is_arg_unionable <= 0) {
310+
if (is_arg_unionable == 0) {
311+
PyErr_Format(PyExc_TypeError,
312+
"Each union argument must be a type, got %.100R", arg);
313+
}
314+
return 0;
315+
}
316+
}
317+
return 1;
318+
}
319+
302320
PyObject *
303321
_Py_union_type_or(PyObject* self, PyObject* other)
304322
{
@@ -422,15 +440,36 @@ static PyObject *
422440
union_reduce(PyObject *self, PyObject *Py_UNUSED(ignored))
423441
{
424442
unionobject *alias = (unionobject *)self;
425-
return Py_BuildValue("O(O)", Py_TYPE(alias), alias->args);
443+
PyObject* from_args = PyObject_GetAttrString(self, "from_args");
444+
if (from_args == NULL) {
445+
return NULL;
446+
}
447+
448+
return Py_BuildValue("O(O)", from_args, alias->args);
426449
}
427450

428451
static PyMemberDef union_members[] = {
429452
{"__args__", T_OBJECT, offsetof(unionobject, args), READONLY},
430453
{0}
431454
};
432455

456+
static PyObject *
457+
union_from_args(PyObject *cls, PyObject *args)
458+
{
459+
if (!PyTuple_CheckExact(args)) {
460+
_PyArg_BadArgument("Union.from_args", "argument '__args__'", "tuple", args);
461+
return NULL;
462+
}
463+
464+
if (is_args_unionable(args) <= 0) {
465+
return NULL;
466+
}
467+
468+
return make_union(args);
469+
}
470+
433471
static PyMethodDef union_methods[] = {
472+
{"from_args", union_from_args, METH_O | METH_CLASS},
434473
{"__instancecheck__", union_instancecheck, METH_O},
435474
{"__subclasscheck__", union_subclasscheck, METH_O},
436475
{"__reduce__", union_reduce, METH_NOARGS},
@@ -455,18 +494,9 @@ union_getitem(PyObject *self, PyObject *item)
455494
}
456495

457496
// Check arguments are unionable.
458-
Py_ssize_t nargs = PyTuple_GET_SIZE(newargs);
459-
for (Py_ssize_t iarg = 0; iarg < nargs; iarg++) {
460-
PyObject *arg = PyTuple_GET_ITEM(newargs, iarg);
461-
int is_arg_unionable = is_unionable(arg);
462-
if (is_arg_unionable <= 0) {
463-
Py_DECREF(newargs);
464-
if (is_arg_unionable == 0) {
465-
PyErr_Format(PyExc_TypeError,
466-
"Each union argument must be a type, got %.100R", arg);
467-
}
468-
return NULL;
469-
}
497+
if (is_args_unionable(newargs) <= 0) {
498+
Py_DECREF(newargs);
499+
return NULL;
470500
}
471501

472502
PyObject *res = make_union(newargs);
@@ -502,34 +532,6 @@ static PyNumberMethods union_as_number = {
502532
.nb_or = _Py_union_type_or, // Add __or__ function
503533
};
504534

505-
static PyObject *
506-
union_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
507-
{
508-
if (!_PyArg_NoKeywords("Union", kwds)) {
509-
return NULL;
510-
}
511-
if (!_PyArg_CheckPositional("Union", PyTuple_GET_SIZE(args), 1, 1)) {
512-
return NULL;
513-
}
514-
515-
PyObject* unionargs = PyTuple_GET_ITEM(args, 0);
516-
517-
if (!PyTuple_CheckExact(unionargs)) {
518-
_PyArg_BadArgument("Union", "argument '__args__'", "tuple", unionargs);
519-
return NULL;
520-
}
521-
522-
PyObject* result = _Py_Union(unionargs);
523-
524-
if (result == Py_NotImplemented) {
525-
Py_DECREF(result);
526-
PyErr_SetString(PyExc_TypeError, "__args__ argument of typing.Union object is not a valid as type");
527-
return NULL;
528-
}
529-
530-
return result;
531-
}
532-
533535
static const char* const cls_attrs[] = {
534536
"__name__",
535537
"__qualname__",
@@ -574,7 +576,6 @@ PyTypeObject _PyUnion_Type = {
574576
.tp_as_number = &union_as_number,
575577
.tp_repr = union_repr,
576578
.tp_getset = union_properties,
577-
.tp_new = union_new,
578579
};
579580

580581
static PyObject *

0 commit comments

Comments
 (0)