Issue 966431: import x.y inside of module x.y (original) (raw)
Logged In: YES user_id=595483
The error seems to be due to the calling sequence of add_submodule and loadmodule in import.c:import_submodule. If load_module(..) is called after add_submodule(...) gets called, the above does not trigger Attribute Error. I made a patch that does it, but there is a problem... Currently, when import produces errors, sys.modules have the damaged module, but the patch does not. (That's why it cannot pass the test_pkgimport.py unittest, I think.) Someone who knows more about import.c could fix the patch to behave like that.
The patch is in http://seojiwon.dnip.net:8000/~jiwon/tmp/import.diff
Logged In: YES user_id=595483
The behavior is definitely due to the calling sequence of add_submodule and load_module in import_submodule. (like following)
... m = load_module(fullname, fp, buf, fdp->type, loader); Py_XDECREF(loader); if (fp) fclose(fp); if (!add_submodule(mod, m, fullname, subname, modules)) { Py_XDECREF(m); m = NULL; } ...
For "importing package.x;do_something(package.x)" from within package.x to be possible, add_submodule should be done before load_module, since in load_module, not only the module is load, but also executed by PyImport_ExecCodeModuleEx. So, if we make a module and call add_submodule before load_module, import ing package.x and using it is possible. (like following)
m = PyImport_AddModule(fullname); if (!m) { return NULL; }
if (!add_submodule(mod, m, fullname, subname, modules)) { Py_XDECREF(m); return NULL; }
m = load_module(mod, fullname, fp, buf, fdp->type, loader); Py_XDECREF(loader);
but above would make test_importhook fail because in IMP_HOOK case, module object is created by PyObject_CallMethod(... "load_module"..), not by calling PyImport_AddModule. So, we cannot know about the module before that method calling is returned. Thus, in IMP_HOOK case, load_module would not use the already-created module by PyImport_AddModule, but would make a new one, which is not added as submodule to its parent.
Anyway, adding another add_submodule after load_module would make import-hook test code to be passed, but it's a lame patch since in IMP_HOOK case, import package.x in package/x.py cannot be done.
So, for the behavior to be possible, I think load_module should be explicitly separated into two function - load_module, execute_module. And then we'll load_module, add_submodule itself to its parent and then execute_module. There does not seem to be any hack that touches only limited places, so I think this bug(?) will stay open for quite long time. =)