summaryrefslogtreecommitdiffstats
path: root/Python/import.c
diff options
context:
space:
mode:
authorBrett Cannon <brett@python.org>2012-07-13 17:57:03 (GMT)
committerBrett Cannon <brett@python.org>2012-07-13 17:57:03 (GMT)
commita6473f9cfd13358b003b8353cd722ca19352817c (patch)
tree3533968bc996698be3bd30eb80ecb5b6dea05f85 /Python/import.c
parentd104eef118bda30725ac087e06252a5a3525e2df (diff)
downloadcpython-a6473f9cfd13358b003b8353cd722ca19352817c.zip
cpython-a6473f9cfd13358b003b8353cd722ca19352817c.tar.gz
cpython-a6473f9cfd13358b003b8353cd722ca19352817c.tar.bz2
Issues #15169, #14599: Make PyImport_ExecCodeModuleWithPathnames() use
Lib/imp.py for imp.source_from_cache() instead of its own C version. Also change PyImport_ExecCodeModuleObject() to not infer the source path from the bytecode path like PyImport_ExecCodeModuleWithPathnames() does. This makes the function less magical. This also has the side-effect of removing all uses of MAXPATHLEN in Python/import.c which can cause failures on really long filenames.
Diffstat (limited to 'Python/import.c')
-rw-r--r--Python/import.c195
1 files changed, 29 insertions, 166 deletions
diff --git a/Python/import.c b/Python/import.c
index 26f4772..982c389 100644
--- a/Python/import.c
+++ b/Python/import.c
@@ -630,8 +630,6 @@ remove_module(PyObject *name)
"sys.modules failed");
}
-static PyObject * get_sourcefile(PyObject *filename);
-static PyObject *make_source_pathname(PyObject *pathname);
/* Execute a code object in a module and return the module object
* WITH INCREMENTED REFERENCE COUNT. If an error occurs, name is
@@ -668,18 +666,37 @@ PyImport_ExecCodeModuleWithPathnames(char *name, PyObject *co, char *pathname,
if (nameobj == NULL)
return NULL;
- if (pathname != NULL) {
- pathobj = PyUnicode_DecodeFSDefault(pathname);
- if (pathobj == NULL)
- goto error;
- } else
- pathobj = NULL;
if (cpathname != NULL) {
cpathobj = PyUnicode_DecodeFSDefault(cpathname);
if (cpathobj == NULL)
goto error;
- } else
+ }
+ else
cpathobj = NULL;
+
+ if (pathname != NULL) {
+ pathobj = PyUnicode_DecodeFSDefault(pathname);
+ if (pathobj == NULL)
+ goto error;
+ }
+ else if (cpathobj != NULL) {
+ PyInterpreterState *interp = PyThreadState_GET()->interp;
+ _Py_IDENTIFIER(_get_sourcefile);
+
+ if (interp == NULL) {
+ Py_FatalError("PyImport_ExecCodeModuleWithPathnames: "
+ "no interpreter!");
+ }
+
+ pathobj = _PyObject_CallMethodObjIdArgs(interp->importlib,
+ &PyId__get_sourcefile, cpathobj,
+ NULL);
+ if (pathobj == NULL)
+ PyErr_Clear();
+ }
+ else
+ pathobj = NULL;
+
m = PyImport_ExecCodeModuleObject(nameobj, co, pathobj, cpathobj);
error:
Py_DECREF(nameobj);
@@ -706,18 +723,13 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname,
PyEval_GetBuiltins()) != 0)
goto error;
}
- /* Remember the filename as the __file__ attribute */
if (pathname != NULL) {
- v = get_sourcefile(pathname);
- if (v == NULL)
- PyErr_Clear();
+ v = pathname;
}
- else
- v = NULL;
- if (v == NULL) {
+ else {
v = ((PyCodeObject *)co)->co_filename;
- Py_INCREF(v);
}
+ Py_INCREF(v);
if (PyDict_SetItemString(d, "__file__", v) != 0)
PyErr_Clear(); /* Not important enough to report */
Py_DECREF(v);
@@ -752,100 +764,6 @@ PyImport_ExecCodeModuleObject(PyObject *name, PyObject *co, PyObject *pathname,
}
-/* Like rightmost_sep, but operate on unicode objects. */
-static Py_ssize_t
-rightmost_sep_obj(PyObject* o, Py_ssize_t start, Py_ssize_t end)
-{
- Py_ssize_t found, i;
- Py_UCS4 c;
- for (found = -1, i = start; i < end; i++) {
- c = PyUnicode_READ_CHAR(o, i);
- if (c == SEP
-#ifdef ALTSEP
- || c == ALTSEP
-#endif
- )
- {
- found = i;
- }
- }
- return found;
-}
-
-
-/* Given a pathname to a Python byte compiled file, return the path to the
- source file, if the path matches the PEP 3147 format. This does not check
- for any file existence, however, if the pyc file name does not match PEP
- 3147 style, NULL is returned. buf must be at least as big as pathname;
- the resulting path will always be shorter.
-
- (...)/__pycache__/foo.<tag>.pyc -> (...)/foo.py */
-
-static PyObject*
-make_source_pathname(PyObject *path)
-{
- Py_ssize_t left, right, dot0, dot1, len;
- Py_ssize_t i, j;
- PyObject *result;
- int kind;
- void *data;
-
- len = PyUnicode_GET_LENGTH(path);
- if (len > MAXPATHLEN)
- return NULL;
-
- /* Look back two slashes from the end. In between these two slashes
- must be the string __pycache__ or this is not a PEP 3147 style
- path. It's possible for there to be only one slash.
- */
- right = rightmost_sep_obj(path, 0, len);
- if (right == -1)
- return NULL;
- left = rightmost_sep_obj(path, 0, right);
- if (left == -1)
- left = 0;
- else
- left++;
- if (right-left != sizeof(CACHEDIR)-1)
- return NULL;
- for (i = 0; i < sizeof(CACHEDIR)-1; i++)
- if (PyUnicode_READ_CHAR(path, left+i) != CACHEDIR[i])
- return NULL;
-
- /* Now verify that the path component to the right of the last slash
- has two dots in it.
- */
- dot0 = PyUnicode_FindChar(path, '.', right+1, len, 1);
- if (dot0 < 0)
- return NULL;
- dot1 = PyUnicode_FindChar(path, '.', dot0+1, len, 1);
- if (dot1 < 0)
- return NULL;
- /* Too many dots? */
- if (PyUnicode_FindChar(path, '.', dot1+1, len, 1) != -1)
- return NULL;
-
- /* This is a PEP 3147 path. Start by copying everything from the
- start of pathname up to and including the leftmost slash. Then
- copy the file's basename, removing the magic tag and adding a .py
- suffix.
- */
- result = PyUnicode_New(left + (dot0-right) + 2,
- PyUnicode_MAX_CHAR_VALUE(path));
- if (!result)
- return NULL;
- kind = PyUnicode_KIND(result);
- data = PyUnicode_DATA(result);
- PyUnicode_CopyCharacters(result, 0, path, 0, (i = left));
- PyUnicode_CopyCharacters(result, left, path, right+1,
- (j = dot0-right));
- PyUnicode_WRITE(kind, data, i+j, 'p');
- PyUnicode_WRITE(kind, data, i+j+1, 'y');
- assert(_PyUnicode_CheckConsistency(result, 1));
- return result;
-}
-
-
static void
update_code_filenames(PyCodeObject *co, PyObject *oldname, PyObject *newname)
{
@@ -911,61 +829,6 @@ imp_fix_co_filename(PyObject *self, PyObject *args)
}
-/* Get source file -> unicode or None
- * Returns the path to the py file if available, else the given path
- */
-static PyObject *
-get_sourcefile(PyObject *filename)
-{
- Py_ssize_t len;
- PyObject *py;
- struct stat statbuf;
- int err;
- void *data;
- unsigned int kind;
-
- len = PyUnicode_GET_LENGTH(filename);
- if (len == 0)
- Py_RETURN_NONE;
-
- /* don't match *.pyc or *.pyo? */
- data = PyUnicode_DATA(filename);
- kind = PyUnicode_KIND(filename);
- if (len < 5
- || PyUnicode_READ(kind, data, len-4) != '.'
- || (PyUnicode_READ(kind, data, len-3) != 'p'
- && PyUnicode_READ(kind, data, len-3) != 'P')
- || (PyUnicode_READ(kind, data, len-2) != 'y'
- && PyUnicode_READ(kind, data, len-2) != 'Y'))
- goto unchanged;
-
- /* Start by trying to turn PEP 3147 path into source path. If that
- * fails, just chop off the trailing character, i.e. legacy pyc path
- * to py.
- */
- py = make_source_pathname(filename);
- if (py == NULL) {
- PyErr_Clear();
- py = PyUnicode_Substring(filename, 0, len - 1);
- }
- if (py == NULL)
- goto error;
-
- err = _Py_stat(py, &statbuf);
- if (err == -2)
- goto error;
- if (err == 0 && S_ISREG(statbuf.st_mode))
- return py;
- Py_DECREF(py);
- goto unchanged;
-
-error:
- PyErr_Clear();
-unchanged:
- Py_INCREF(filename);
- return filename;
-}
-
/* Forward */
static struct _frozen * find_frozen(PyObject *);