Issue #1180193: When importing a module from a .pyc (or .pyo) file with

an existing .py counterpart, override the co_filename attributes of all
code objects if the original filename is obsolete (which can happen if the
file has been renamed, moved, or if it is accessed through different paths).
Patch by Ziga Seilnacht and Jean-Paul Calderone.
This commit is contained in:
Antoine Pitrou 2009-01-06 18:10:47 +00:00
parent 3741bfdd3c
commit e96d4ea4e2
3 changed files with 144 additions and 1 deletions

View file

@ -909,6 +909,49 @@ write_compiled_module(PyCodeObject *co, char *cpathname, struct stat *srcstat)
PySys_WriteStderr("# wrote %s\n", cpathname);
}
static void
update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname)
{
PyObject *constants, *tmp;
Py_ssize_t i, n;
if (!_PyString_Eq(co->co_filename, oldname))
return;
tmp = co->co_filename;
co->co_filename = newname;
Py_INCREF(co->co_filename);
Py_DECREF(tmp);
constants = co->co_consts;
n = PyTuple_GET_SIZE(constants);
for (i = 0; i < n; i++) {
tmp = PyTuple_GET_ITEM(constants, i);
if (PyCode_Check(tmp))
update_code_filenames((PyCodeObject *)tmp,
oldname, newname);
}
}
static int
update_compiled_module(PyCodeObject *co, char *pathname)
{
PyObject *oldname, *newname;
if (strcmp(PyString_AsString(co->co_filename), pathname) == 0)
return 0;
newname = PyString_FromString(pathname);
if (newname == NULL)
return -1;
oldname = co->co_filename;
Py_INCREF(oldname);
update_code_filenames(co, oldname, newname);
Py_DECREF(oldname);
Py_DECREF(newname);
return 1;
}
/* Load a source module from a given file and return its module
object WITH INCREMENTED REFERENCE COUNT. If there's a matching
@ -949,6 +992,8 @@ load_source_module(char *name, char *pathname, FILE *fp)
fclose(fpc);
if (co == NULL)
return NULL;
if (update_compiled_module(co, pathname) < 0)
return NULL;
if (Py_VerboseFlag)
PySys_WriteStderr("import %s # precompiled from %s\n",
name, cpathname);