diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2009-01-06 18:10:47 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2009-01-06 18:10:47 (GMT) |
commit | e96d4ea4e235645452ae8a6c8ab557d31d2bb485 (patch) | |
tree | 20802b2b4711f32d21d422a7335cfdac7ddc4f34 /Python | |
parent | 3741bfdd3c789704f95b7969afa52f1053660e90 (diff) | |
download | cpython-e96d4ea4e235645452ae8a6c8ab557d31d2bb485.zip cpython-e96d4ea4e235645452ae8a6c8ab557d31d2bb485.tar.gz cpython-e96d4ea4e235645452ae8a6c8ab557d31d2bb485.tar.bz2 |
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.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/import.c | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/Python/import.c b/Python/import.c index 08024b2..e9ff922 100644 --- a/Python/import.c +++ b/Python/import.c @@ -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); |