@@ -1837,6 +1837,40 @@ BINARY(rshift, "x>>y");
18371837BINARY (and , "x&y" );
18381838BINARY (xor , "x^y" );
18391839BINARY (or , "x|y" );
1840+
1841+ static PyObject *
1842+ wrap_coercefunc (PyObject * self , PyObject * args , void * wrapped )
1843+ {
1844+ coercion func = (coercion )wrapped ;
1845+ PyObject * other , * res ;
1846+ int ok ;
1847+
1848+ if (!PyArg_ParseTuple (args , "O" , & other ))
1849+ return NULL ;
1850+ ok = func (& self , & other );
1851+ if (ok < 0 )
1852+ return NULL ;
1853+ if (ok > 0 ) {
1854+ Py_INCREF (Py_NotImplemented );
1855+ return Py_NotImplemented ;
1856+ }
1857+ res = PyTuple_New (2 );
1858+ if (res == NULL ) {
1859+ Py_DECREF (self );
1860+ Py_DECREF (other );
1861+ return NULL ;
1862+ }
1863+ PyTuple_SET_ITEM (res , 0 , self );
1864+ PyTuple_SET_ITEM (res , 1 , other );
1865+ return res ;
1866+ }
1867+
1868+ static struct wrapperbase tab_coerce [] = {
1869+ {"__coerce__" , (wrapperfunc )wrap_coercefunc ,
1870+ "x.__coerce__(y) <==> coerce(x, y)" },
1871+ {0 }
1872+ };
1873+
18401874BINARY (floordiv , "x//y" );
18411875BINARY (truediv , "x/y # true division" );
18421876
@@ -2573,7 +2607,7 @@ add_operators(PyTypeObject *type)
25732607 ADD (nb -> nb_and , tab_and );
25742608 ADD (nb -> nb_xor , tab_xor );
25752609 ADD (nb -> nb_or , tab_or );
2576- /* We don't support coerce() -- see above comment */
2610+ ADD ( nb -> nb_coerce , tab_coerce );
25772611 ADD (nb -> nb_int , tab_int );
25782612 ADD (nb -> nb_long , tab_long );
25792613 ADD (nb -> nb_float , tab_float );
@@ -2840,7 +2874,64 @@ SLOT1BIN(slot_nb_rshift, nb_rshift, "__rshift__", "__rrshift__")
28402874SLOT1BIN (slot_nb_and , nb_and , "__and__" , "__rand__" )
28412875SLOT1BIN (slot_nb_xor , nb_xor , "__xor__" , "__rxor__" )
28422876SLOT1BIN (slot_nb_or , nb_or , "__or__" , "__ror__" )
2843- /* Not coerce() */
2877+
2878+ static int
2879+ slot_nb_coerce (PyObject * * a , PyObject * * b )
2880+ {
2881+ static PyObject * coerce_str ;
2882+ PyObject * self = * a , * other = * b ;
2883+
2884+ if (self -> ob_type -> tp_as_number != NULL &&
2885+ self -> ob_type -> tp_as_number -> nb_coerce == slot_nb_coerce ) {
2886+ PyObject * r ;
2887+ r = call_maybe (
2888+ self , "__coerce__" , & coerce_str , "(O)" , other );
2889+ if (r == NULL )
2890+ return -1 ;
2891+ if (r == Py_NotImplemented ) {
2892+ Py_DECREF (r );
2893+ return 1 ;
2894+ }
2895+ if (!PyTuple_Check (r ) || PyTuple_GET_SIZE (r ) != 2 ) {
2896+ PyErr_SetString (PyExc_TypeError ,
2897+ "__coerce__ didn't return a 2-tuple" );
2898+ Py_DECREF (r );
2899+ return -1 ;
2900+ }
2901+ * a = PyTuple_GET_ITEM (r , 0 );
2902+ Py_INCREF (* a );
2903+ * b = PyTuple_GET_ITEM (r , 1 );
2904+ Py_INCREF (* b );
2905+ Py_DECREF (r );
2906+ return 0 ;
2907+ }
2908+ if (other -> ob_type -> tp_as_number != NULL &&
2909+ other -> ob_type -> tp_as_number -> nb_coerce == slot_nb_coerce ) {
2910+ PyObject * r ;
2911+ r = call_maybe (
2912+ other , "__coerce__" , & coerce_str , "(O)" , self );
2913+ if (r == NULL )
2914+ return -1 ;
2915+ if (r == Py_NotImplemented ) {
2916+ Py_DECREF (r );
2917+ return 1 ;
2918+ }
2919+ if (!PyTuple_Check (r ) || PyTuple_GET_SIZE (r ) != 2 ) {
2920+ PyErr_SetString (PyExc_TypeError ,
2921+ "__coerce__ didn't return a 2-tuple" );
2922+ Py_DECREF (r );
2923+ return -1 ;
2924+ }
2925+ * a = PyTuple_GET_ITEM (r , 1 );
2926+ Py_INCREF (* a );
2927+ * b = PyTuple_GET_ITEM (r , 0 );
2928+ Py_INCREF (* b );
2929+ Py_DECREF (r );
2930+ return 0 ;
2931+ }
2932+ return 1 ;
2933+ }
2934+
28442935SLOT0 (slot_nb_int , "__int__" )
28452936SLOT0 (slot_nb_long , "__long__" )
28462937SLOT0 (slot_nb_float , "__float__" )
@@ -3336,7 +3427,7 @@ override_slots(PyTypeObject *type, PyObject *dict)
33363427 NBSLOT ("__and__" , nb_and , slot_nb_and );
33373428 NBSLOT ("__xor__" , nb_xor , slot_nb_xor );
33383429 NBSLOT ("__or__" , nb_or , slot_nb_or );
3339- /* Not coerce() */
3430+ NBSLOT ( "__coerce__" , nb_coerce , slot_nb_coerce );
33403431 NBSLOT ("__int__" , nb_int , slot_nb_int );
33413432 NBSLOT ("__long__" , nb_long , slot_nb_long );
33423433 NBSLOT ("__float__" , nb_float , slot_nb_float );
0 commit comments