[Python-checkins] cpython: Make importlib compatible with __import__ by "fixing" code.co_filename

brett.cannon python-checkins at python.org
Thu Mar 24 00:16:06 CET 2011


http://hg.python.org/cpython/rev/5deb2094f033
changeset:   68887:5deb2094f033
user:        Brett Cannon <brett at python.org>
date:        Wed Mar 23 16:14:42 2011 -0700
summary:
  Make importlib compatible with __import__ by "fixing" code.co_filename
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.

files:
  Lib/importlib/_bootstrap.py |   1 +
  Misc/NEWS                   |   4 +++
  Python/import.c             |  27 +++++++++++++++++++++++++
  3 files changed, 32 insertions(+), 0 deletions(-)


diff --git a/Lib/importlib/_bootstrap.py b/Lib/importlib/_bootstrap.py
--- a/Lib/importlib/_bootstrap.py
+++ b/Lib/importlib/_bootstrap.py
@@ -404,6 +404,7 @@
                     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 {}"
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -84,6 +84,10 @@
 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
diff --git a/Python/import.c b/Python/import.c
--- a/Python/import.c
+++ b/Python/import.c
@@ -1374,6 +1374,32 @@
     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 @@
 #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 */
 };
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list