@@ -1034,13 +1034,65 @@ PyNumber_AsSsize_t(PyObject *item, PyObject *err)
10341034}
10351035
10361036
1037+ PyObject *
1038+ _PyNumber_ConvertIntegralToInt (PyObject * integral , const char * error_format )
1039+ {
1040+ const char * type_name ;
1041+ static PyObject * int_name = NULL ;
1042+ if (int_name == NULL ) {
1043+ int_name = PyString_InternFromString ("__int__" );
1044+ if (int_name == NULL )
1045+ return NULL ;
1046+ }
1047+
1048+ if (integral && (!PyInt_Check (integral ) &&
1049+ !PyLong_Check (integral ))) {
1050+ /* Don't go through tp_as_number->nb_int to avoid
1051+ hitting the classic class fallback to __trunc__. */
1052+ PyObject * int_func = PyObject_GetAttr (integral , int_name );
1053+ if (int_func == NULL ) {
1054+ PyErr_Clear (); /* Raise a different error. */
1055+ goto non_integral_error ;
1056+ }
1057+ Py_DECREF (integral );
1058+ integral = PyEval_CallObject (int_func , NULL );
1059+ Py_DECREF (int_func );
1060+ if (integral && (!PyInt_Check (integral ) &&
1061+ !PyLong_Check (integral ))) {
1062+ goto non_integral_error ;
1063+ }
1064+ }
1065+ return integral ;
1066+
1067+ non_integral_error :
1068+ if (PyInstance_Check (integral )) {
1069+ type_name = PyString_AS_STRING (((PyInstanceObject * )integral )
1070+ -> in_class -> cl_name );
1071+ }
1072+ else {
1073+ type_name = integral -> ob_type -> tp_name ;
1074+ }
1075+ PyErr_Format (PyExc_TypeError , error_format , type_name );
1076+ Py_DECREF (integral );
1077+ return NULL ;
1078+ }
1079+
1080+
10371081PyObject *
10381082PyNumber_Int (PyObject * o )
10391083{
10401084 PyNumberMethods * m ;
1085+ static PyObject * trunc_name = NULL ;
1086+ PyObject * trunc_func ;
10411087 const char * buffer ;
10421088 Py_ssize_t buffer_len ;
10431089
1090+ if (trunc_name == NULL ) {
1091+ trunc_name = PyString_InternFromString ("__trunc__" );
1092+ if (trunc_name == NULL )
1093+ return NULL ;
1094+ }
1095+
10441096 if (o == NULL )
10451097 return null_error ();
10461098 if (PyInt_CheckExact (o )) {
@@ -1049,6 +1101,7 @@ PyNumber_Int(PyObject *o)
10491101 }
10501102 m = o -> ob_type -> tp_as_number ;
10511103 if (m && m -> nb_int ) { /* This should include subclasses of int */
1104+ /* Classic classes always take this branch. */
10521105 PyObject * res = m -> nb_int (o );
10531106 if (res && (!PyInt_Check (res ) && !PyLong_Check (res ))) {
10541107 PyErr_Format (PyExc_TypeError ,
@@ -1063,6 +1116,18 @@ PyNumber_Int(PyObject *o)
10631116 PyIntObject * io = (PyIntObject * )o ;
10641117 return PyInt_FromLong (io -> ob_ival );
10651118 }
1119+ trunc_func = PyObject_GetAttr (o , trunc_name );
1120+ if (trunc_func ) {
1121+ PyObject * truncated = PyEval_CallObject (trunc_func , NULL );
1122+ Py_DECREF (trunc_func );
1123+ /* __trunc__ is specified to return an Integral type, but
1124+ int() needs to return an int. */
1125+ return _PyNumber_ConvertIntegralToInt (
1126+ truncated ,
1127+ "__trunc__ returned non-Integral (type %.200s)" );
1128+ }
1129+ PyErr_Clear (); /* It's not an error if o.__trunc__ doesn't exist. */
1130+
10661131 if (PyString_Check (o ))
10671132 return int_from_string (PyString_AS_STRING (o ),
10681133 PyString_GET_SIZE (o ));
@@ -1102,13 +1167,22 @@ PyObject *
11021167PyNumber_Long (PyObject * o )
11031168{
11041169 PyNumberMethods * m ;
1170+ static PyObject * trunc_name = NULL ;
1171+ PyObject * trunc_func ;
11051172 const char * buffer ;
11061173 Py_ssize_t buffer_len ;
11071174
1175+ if (trunc_name == NULL ) {
1176+ trunc_name = PyString_InternFromString ("__trunc__" );
1177+ if (trunc_name == NULL )
1178+ return NULL ;
1179+ }
1180+
11081181 if (o == NULL )
11091182 return null_error ();
11101183 m = o -> ob_type -> tp_as_number ;
11111184 if (m && m -> nb_long ) { /* This should include subclasses of long */
1185+ /* Classic classes always take this branch. */
11121186 PyObject * res = m -> nb_long (o );
11131187 if (res && (!PyInt_Check (res ) && !PyLong_Check (res ))) {
11141188 PyErr_Format (PyExc_TypeError ,
@@ -1121,6 +1195,26 @@ PyNumber_Long(PyObject *o)
11211195 }
11221196 if (PyLong_Check (o )) /* A long subclass without nb_long */
11231197 return _PyLong_Copy ((PyLongObject * )o );
1198+ trunc_func = PyObject_GetAttr (o , trunc_name );
1199+ if (trunc_func ) {
1200+ PyObject * truncated = PyEval_CallObject (trunc_func , NULL );
1201+ PyObject * int_instance ;
1202+ Py_DECREF (trunc_func );
1203+ /* __trunc__ is specified to return an Integral type,
1204+ but long() needs to return a long. */
1205+ int_instance = _PyNumber_ConvertIntegralToInt (
1206+ truncated ,
1207+ "__trunc__ returned non-Integral (type %.200s)" );
1208+ if (int_instance && PyInt_Check (int_instance )) {
1209+ /* Make sure that long() returns a long instance. */
1210+ long value = PyInt_AS_LONG (int_instance );
1211+ Py_DECREF (int_instance );
1212+ return PyLong_FromLong (value );
1213+ }
1214+ return int_instance ;
1215+ }
1216+ PyErr_Clear (); /* It's not an error if o.__trunc__ doesn't exist. */
1217+
11241218 if (PyString_Check (o ))
11251219 /* need to do extra error checking that PyLong_FromString()
11261220 * doesn't do. In particular long('9.5') must raise an
0 commit comments