@@ -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_DECREF (obj );
1264+ Py_DECREF (attr );
1265+ return NULL ;
1266+ }
1267+
1268+
12211269static void
12221270run_presite (PyThreadState * tstate )
12231271{
@@ -1228,22 +1276,68 @@ run_presite(PyThreadState *tstate)
12281276 return ;
12291277 }
12301278
1231- PyObject * presite_modname = PyUnicode_FromWideChar (
1232- config -> run_presite ,
1233- wcslen (config -> run_presite )
1234- );
1235- if (presite_modname == NULL ) {
1236- fprintf (stderr , "Could not convert pre-site module name to unicode\n" );
1279+ PyObject * presite = PyUnicode_FromWideChar (config -> run_presite , -1 );
1280+ if (presite == NULL ) {
1281+ fprintf (stderr , "Could not convert pre-site command to Unicode\n" );
1282+ _PyErr_Print (tstate );
1283+ return ;
1284+ }
1285+
1286+ // Accept "mod_name" and "mod_name:func_name" entry point syntax
1287+ Py_ssize_t len = PyUnicode_GET_LENGTH (presite );
1288+ Py_ssize_t pos = PyUnicode_FindChar (presite , ':' , 0 , len , 1 );
1289+ PyObject * mod_name = NULL ;
1290+ PyObject * func_name = NULL ;
1291+ PyObject * module = NULL ;
1292+ if (pos > 0 ) {
1293+ mod_name = PyUnicode_Substring (presite , 0 , pos );
1294+ if (mod_name == NULL ) {
1295+ goto error ;
1296+ }
1297+
1298+ func_name = PyUnicode_Substring (presite , pos + 1 , len );
1299+ if (func_name == NULL ) {
1300+ goto error ;
1301+ }
12371302 }
12381303 else {
1239- PyObject * presite = PyImport_Import (presite_modname );
1240- if (presite == NULL ) {
1241- fprintf (stderr , "pre-site import failed:\n" );
1242- _PyErr_Print (tstate );
1304+ mod_name = Py_NewRef (presite );
1305+ }
1306+
1307+ // mod_name can contain dots (ex: "math.integer")
1308+ module = PyImport_Import (mod_name );
1309+ if (module == NULL ) {
1310+ goto error ;
1311+ }
1312+
1313+ if (func_name != NULL ) {
1314+ PyObject * func = presite_resolve_name (module , func_name );
1315+ if (func == NULL ) {
1316+ goto error ;
1317+ }
1318+
1319+ PyObject * res = PyObject_CallNoArgs (func );
1320+ Py_DECREF (func );
1321+ if (res == NULL ) {
1322+ goto error ;
12431323 }
1244- Py_XDECREF (presite );
1245- Py_DECREF (presite_modname );
1324+ Py_DECREF (res );
12461325 }
1326+
1327+ Py_DECREF (presite );
1328+ Py_DECREF (mod_name );
1329+ Py_XDECREF (func_name );
1330+ Py_DECREF (module );
1331+ return ;
1332+
1333+ error :
1334+ fprintf (stderr , "pre-site failed:\n" );
1335+ _PyErr_Print (tstate );
1336+
1337+ Py_DECREF (presite );
1338+ Py_XDECREF (mod_name );
1339+ Py_XDECREF (func_name );
1340+ Py_XDECREF (module );
12471341}
12481342#endif
12491343
0 commit comments