@@ -1218,6 +1218,54 @@ pyinit_main_reconfigure(PyThreadState *tstate)
12181218
12191219
12201220#ifdef Py_DEBUG
1221+ // Equivalent to the Python code:
1222+ //
1223+ // for part in attr.split('.'):
1224+ // obj = getattr(obj, part)
1225+ static PyObject *
1226+ presite_resolve_name (PyObject * obj , PyObject * attr )
1227+ {
1228+ obj = Py_NewRef (obj );
1229+ attr = Py_NewRef (attr );
1230+ PyObject * res ;
1231+
1232+ while (1 ) {
1233+ Py_ssize_t len = PyUnicode_GET_LENGTH (attr );
1234+ Py_ssize_t pos = PyUnicode_FindChar (attr , '.' , 0 , len , 1 );
1235+ if (pos < 0 ) {
1236+ break ;
1237+ }
1238+
1239+ PyObject * name = PyUnicode_Substring (attr , 0 , pos );
1240+ if (name == NULL ) {
1241+ goto error ;
1242+ }
1243+ res = PyObject_GetAttr (obj , name );
1244+ Py_DECREF (name );
1245+ if (res == NULL ) {
1246+ goto error ;
1247+ }
1248+ Py_SETREF (obj , res );
1249+
1250+ PyObject * suffix = PyUnicode_Substring (attr , pos + 1 , len );
1251+ if (suffix == NULL ) {
1252+ goto error ;
1253+ }
1254+ Py_SETREF (attr , suffix );
1255+ }
1256+
1257+ res = PyObject_GetAttr (obj , attr );
1258+ Py_DECREF (obj );
1259+ Py_DECREF (attr );
1260+ return res ;
1261+
1262+ error :
1263+ Py_XDECREF (obj );
1264+ Py_DECREF (attr );
1265+ return NULL ;
1266+ }
1267+
1268+
12211269static void
12221270run_presite (PyThreadState * tstate )
12231271{
@@ -1256,13 +1304,14 @@ run_presite(PyThreadState *tstate)
12561304 mod_name = Py_NewRef (presite );
12571305 }
12581306
1307+ // mod_name can contain dots (ex: "math.integer")
12591308 module = PyImport_Import (mod_name );
12601309 if (module == NULL ) {
12611310 goto error ;
12621311 }
12631312
12641313 if (func_name != NULL ) {
1265- PyObject * func = PyObject_GetAttr (module , func_name );
1314+ PyObject * func = presite_resolve_name (module , func_name );
12661315 if (func == NULL ) {
12671316 goto error ;
12681317 }
0 commit comments