]> granicus.if.org Git - python/commitdiff
Make importlib compatible with __import__ by "fixing" code.co_filename
authorBrett Cannon <brett@python.org>
Wed, 23 Mar 2011 23:14:42 +0000 (16:14 -0700)
committerBrett Cannon <brett@python.org>
Wed, 23 Mar 2011 23:14:42 +0000 (16:14 -0700)
paths.

__import__ does a little trick when importing from bytecode by
back-patching the co_filename paths to point to the file location
where the code object was loaded from, *not* where the code object was
originally created. This allows co_filename to point to a valid path.
Problem is that co_filename is immutable from Python, so a private
function -- imp._fix_co_filename() -- had to be introduced in order to
get things working properly. Originally the plan was to add a file
argument to marshal.loads(), but that failed as the algorithm used by
__import__ is not fully recursive as one might expect, so to be fully
backwards-compatible the code used by __import__ needed to be exposed.

This closes issue #6811 by taking a different approach than outlined
in the issue.

Lib/importlib/_bootstrap.py
Misc/NEWS
Python/import.c

index f2ef1cf714c7dd58e8d2b15cbf19cd696c7fb00b..18ea85cb78307ece4ee59711839d19507e9ea716 100644 (file)
@@ -404,6 +404,7 @@ class SourceLoader(_LoaderBasics):
                     else:
                         found = marshal.loads(bytes_data)
                         if isinstance(found, code_type):
+                            imp._fix_co_filename(found, source_path)
                             return found
                         else:
                             msg = "Non-code object in {}"
index 0dd8a3d58e03a398413ab16f7240a9275d127b1f..f70998c9db7fa51019fc54928cf8d6f550ea6bec 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -84,6 +84,10 @@ Core and Builtins
 Library
 -------
 
+- Issue #6811: Allow importlib to change a code object's co_filename attribute
+  to match the path to where the source code currently is, not where the code
+  object originally came from.
+
 - Issue #8754: Have importlib use the repr of a module name in error messages.
 
 - Issue #11591: Prevent "import site" from modifying sys.path when python
index 907ccd797ccf7d9fd5ded12db7625d39f7daea4b..b074b834e90d9450addb5d1749f8cdb95f0d8638 100644 (file)
@@ -1374,6 +1374,32 @@ update_compiled_module(PyCodeObject *co, PyObject *newname)
     Py_DECREF(oldname);
 }
 
+static PyObject *
+imp_fix_co_filename(PyObject *self, PyObject *args)
+{
+    PyObject *co;
+    PyObject *file_path;
+
+    if (!PyArg_ParseTuple(args, "OO:_fix_co_filename", &co, &file_path))
+        return NULL;
+
+    if (!PyCode_Check(co)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "first argument must be a code object");
+        return NULL;
+    }
+
+    if (!PyUnicode_Check(file_path)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "second argument must be a string");
+        return NULL;
+    }
+
+    update_compiled_module((PyCodeObject*)co, file_path);
+
+    Py_RETURN_NONE;
+}
+
 /* Load a source module from a given file and return its module
    object WITH INCREMENTED REFERENCE COUNT.  If there's a matching
    byte-compiled file, use that instead. */
@@ -3976,6 +4002,7 @@ static PyMethodDef imp_methods[] = {
 #endif
     {"load_package",            imp_load_package,       METH_VARARGS},
     {"load_source",             imp_load_source,        METH_VARARGS},
+    {"_fix_co_filename",        imp_fix_co_filename,    METH_VARARGS},
     {NULL,                      NULL}           /* sentinel */
 };