@@ -299,6 +299,24 @@ is_unionable(PyObject *obj)
299
299
return 0 ;
300
300
}
301
301
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
+
302
320
PyObject *
303
321
_Py_union_type_or (PyObject * self , PyObject * other )
304
322
{
@@ -422,15 +440,36 @@ static PyObject *
422
440
union_reduce (PyObject * self , PyObject * Py_UNUSED (ignored ))
423
441
{
424
442
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 );
426
449
}
427
450
428
451
static PyMemberDef union_members [] = {
429
452
{"__args__" , T_OBJECT , offsetof(unionobject , args ), READONLY },
430
453
{0 }
431
454
};
432
455
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
+
433
471
static PyMethodDef union_methods [] = {
472
+ {"from_args" , union_from_args , METH_O | METH_CLASS },
434
473
{"__instancecheck__" , union_instancecheck , METH_O },
435
474
{"__subclasscheck__" , union_subclasscheck , METH_O },
436
475
{"__reduce__" , union_reduce , METH_NOARGS },
@@ -455,18 +494,9 @@ union_getitem(PyObject *self, PyObject *item)
455
494
}
456
495
457
496
// 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 ;
470
500
}
471
501
472
502
PyObject * res = make_union (newargs );
@@ -502,34 +532,6 @@ static PyNumberMethods union_as_number = {
502
532
.nb_or = _Py_union_type_or , // Add __or__ function
503
533
};
504
534
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
-
533
535
static const char * const cls_attrs [] = {
534
536
"__name__" ,
535
537
"__qualname__" ,
@@ -574,7 +576,6 @@ PyTypeObject _PyUnion_Type = {
574
576
.tp_as_number = & union_as_number ,
575
577
.tp_repr = union_repr ,
576
578
.tp_getset = union_properties ,
577
- .tp_new = union_new ,
578
579
};
579
580
580
581
static PyObject *
0 commit comments