@@ -3898,23 +3898,28 @@ _PyImport_ResolveName(PyThreadState *tstate, PyObject *name,
38983898 return resolve_name (tstate , name , globals , level );
38993899}
39003900
3901- // Take `a.b.c` off the `a` that importing "a.b.c" returns, as IMPORT_FROM does.
3901+ // Look up, in order, the attributes recorded from the root placeholder to lz
3902+ // on the module the root's import returned.
39023903static PyObject *
3903- import_from_dotted_name (PyThreadState * tstate , PyObject * mod , PyObject * name )
3904- {
3905- PyObject * parts = PyUnicode_Split (name , _Py_LATIN1_CHR ('.' ), -1 );
3906- if (parts == NULL ) {
3907- return NULL ;
3908- }
3909- PyObject * obj = Py_NewRef (mod );
3910- for (Py_ssize_t i = 1 ; i < PyList_GET_SIZE (parts ); i ++ ) {
3911- Py_SETREF (obj , _PyEval_ImportFrom (tstate , obj ,
3912- PyList_GET_ITEM (parts , i )));
3913- if (obj == NULL ) {
3914- break ;
3904+ lazy_import_replay_from (PyThreadState * tstate , PyObject * mod ,
3905+ PyLazyImportObject * lz )
3906+ {
3907+ PyObject * from ;
3908+ if (PyLazyImport_CheckExact (lz -> lz_from )) {
3909+ from = lazy_import_replay_from (
3910+ tstate , mod , (PyLazyImportObject * )lz -> lz_from );
3911+ if (from == NULL ) {
3912+ return NULL ;
39153913 }
39163914 }
3917- Py_DECREF (parts );
3915+ else if (lz -> lz_attr != NULL && PyUnicode_Check (lz -> lz_attr )) {
3916+ from = Py_NewRef (mod );
3917+ }
3918+ else {
3919+ return Py_NewRef (mod );
3920+ }
3921+ PyObject * obj = _PyEval_ImportFrom (tstate , from , lz -> lz_attr );
3922+ Py_DECREF (from );
39183923 return obj ;
39193924}
39203925
@@ -3930,6 +3935,12 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
39303935 PyLazyImportObject * lz = (PyLazyImportObject * )lazy_import ;
39313936 PyInterpreterState * interp = tstate -> interp ;
39323937
3938+ // Walk back to the placeholder IMPORT_NAME left.
3939+ PyLazyImportObject * root = lz ;
3940+ while (PyLazyImport_CheckExact (root -> lz_from )) {
3941+ root = (PyLazyImportObject * )root -> lz_from ;
3942+ }
3943+
39333944 // Acquire the global import lock to serialize reification
39343945 _PyImport_AcquireLock (interp );
39353946
@@ -3966,7 +3977,7 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
39663977 return NULL ;
39673978 }
39683979 PyErr_SetImportErrorSubclass (PyExc_ImportCycleError , errmsg ,
3969- lz -> lz_from , NULL );
3980+ root -> lz_from , NULL );
39703981 Py_DECREF (errmsg );
39713982 Py_DECREF (name );
39723983 _PyImport_ReleaseLock (interp );
@@ -3976,24 +3987,24 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
39763987 goto error ;
39773988 }
39783989
3979- if (lz -> lz_attr != NULL ) {
3980- if (PyUnicode_Check (lz -> lz_attr )) {
3990+ if (root -> lz_attr != NULL ) {
3991+ if (PyUnicode_Check (root -> lz_attr )) {
39813992 fromlist = PyTuple_New (1 );
39823993 if (fromlist == NULL ) {
39833994 goto error ;
39843995 }
3985- Py_INCREF (lz -> lz_attr );
3986- PyTuple_SET_ITEM (fromlist , 0 , lz -> lz_attr );
3996+ Py_INCREF (root -> lz_attr );
3997+ PyTuple_SET_ITEM (fromlist , 0 , root -> lz_attr );
39873998 }
39883999 else {
3989- Py_INCREF (lz -> lz_attr );
3990- fromlist = lz -> lz_attr ;
4000+ Py_INCREF (root -> lz_attr );
4001+ fromlist = root -> lz_attr ;
39914002 }
39924003 }
39934004
39944005 PyObject * globals = PyEval_GetGlobals ();
39954006
3996- if (PyMapping_GetOptionalItem (lz -> lz_builtins , & _Py_ID (__import__ ),
4007+ if (PyMapping_GetOptionalItem (root -> lz_builtins , & _Py_ID (__import__ ),
39974008 & import_func ) < 0 ) {
39984009 goto error ;
39994010 }
@@ -4003,27 +4014,17 @@ _PyImport_LoadLazyImportTstate(PyThreadState *tstate, PyObject *lazy_import)
40034014 }
40044015 obj = _PyEval_ImportNameWithImport (
40054016 tstate , import_func , globals , globals ,
4006- lz -> lz_from , fromlist , _PyLong_GetZero ()
4017+ root -> lz_from , fromlist , _PyLong_GetZero ()
40074018 );
40084019 if (obj == NULL ) {
40094020 goto error ;
40104021 }
40114022
4012- if (lz -> lz_dotted_as ) {
4013- PyObject * top = obj ;
4014- obj = import_from_dotted_name (tstate , top , lz -> lz_from );
4015- Py_DECREF (top );
4016- if (obj == NULL ) {
4017- goto error ;
4018- }
4019- }
4020- else if (lz -> lz_attr != NULL && PyUnicode_Check (lz -> lz_attr )) {
4021- PyObject * from = obj ;
4022- obj = _PyEval_ImportFrom (tstate , from , lz -> lz_attr );
4023- Py_DECREF (from );
4024- if (obj == NULL ) {
4025- goto error ;
4026- }
4023+ PyObject * from = obj ;
4024+ obj = lazy_import_replay_from (tstate , from , lz );
4025+ Py_DECREF (from );
4026+ if (obj == NULL ) {
4027+ goto error ;
40274028 }
40284029
40294030 assert (!PyLazyImport_CheckExact (obj ));
@@ -4628,7 +4629,7 @@ _PyImport_LazyImportModuleLevelObject(PyThreadState *tstate,
46284629 else {
46294630 Py_XINCREF (fromlist );
46304631 }
4631- PyObject * res = _PyLazyImport_New (frame , builtins , abs_name , fromlist , 0 );
4632+ PyObject * res = _PyLazyImport_New (frame , builtins , abs_name , fromlist );
46324633 if (res == NULL ) {
46334634 Py_XDECREF (fromlist );
46344635 Py_DECREF (abs_name );
0 commit comments