[Python-checkins] cpython: Issue #3080: find_module() expects module fullname and subname as Unicode

victor.stinner python-checkins at python.org
Sun Mar 20 04:13:55 CET 2011


http://hg.python.org/cpython/rev/156818529636
changeset:   68729:156818529636
user:        Victor Stinner <victor.stinner at haypocalc.com>
date:        Mon Mar 14 09:21:33 2011 -0400
summary:
  Issue #3080: find_module() expects module fullname and subname as Unicode

And PyImport_ReloadModule() uses Unicode for the module name.

files:
  Python/import.c

diff --git a/Python/import.c b/Python/import.c
--- a/Python/import.c
+++ b/Python/import.c
@@ -1491,7 +1491,7 @@
 
 /* Forward */
 static PyObject *load_module(PyObject *, FILE *, PyObject *, int, PyObject *);
-static struct filedescr *find_module(char *, const char *, PyObject *,
+static struct filedescr *find_module(PyObject *, PyObject *, PyObject *,
                                      char *, size_t, FILE **, PyObject **);
 static struct _frozen * find_frozen(PyObject *);
 
@@ -1507,7 +1507,13 @@
     char buf[MAXPATHLEN+1];
     FILE *fp = NULL;
     struct filedescr *fdp;
-    char *namestr;
+    static PyObject *initstr = NULL;
+
+    if (initstr == NULL) {
+        initstr = PyUnicode_InternFromString("__init__");
+        if (initstr == NULL)
+            return NULL;
+    }
 
     m = PyImport_AddModuleObject(name);
     if (m == NULL)
@@ -1532,10 +1538,7 @@
         Py_DECREF(path_list);
         return NULL;
     }
-    namestr = _PyUnicode_AsString(name);
-    if (namestr == NULL)
-        goto error;
-    fdp = find_module(namestr, "__init__", path_list, buf, sizeof(buf), &fp, NULL);
+    fdp = find_module(name, initstr, path_list, buf, sizeof(buf), &fp, NULL);
     Py_DECREF(path_list);
     if (fdp == NULL) {
         if (PyErr_ExceptionMatches(PyExc_ImportError)) {
@@ -1680,7 +1683,7 @@
         and *buf is the path */
 
 static int
-find_module_path(char *fullname, const char *name, PyObject *path,
+find_module_path(PyObject *fullname, PyObject *name, PyObject *path,
                  PyObject *path_hooks, PyObject *path_importer_cache,
                  char *buf, size_t buflen,
                  PyObject **p_loader, struct filedescr **p_fd)
@@ -1691,6 +1694,7 @@
     size_t namelen;
     struct stat statbuf;
     static struct filedescr fd_package = {"", "", PKG_DIRECTORY};
+    char *namestr;
 
     if (PyUnicode_Check(path)) {
         path_bytes = PyUnicode_EncodeFSDefault(path);
@@ -1704,7 +1708,8 @@
     else
         return 0;
 
-    namelen = strlen(name);
+    namestr = _PyUnicode_AsString(name);
+    namelen = strlen(namestr);
     base = PyBytes_AS_STRING(path_bytes);
     len = PyBytes_GET_SIZE(path_bytes);
     if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) {
@@ -1731,8 +1736,7 @@
         if (importer != Py_None) {
             PyObject *loader;
             loader = PyObject_CallMethod(importer,
-                                         "find_module",
-                                         "s", fullname);
+                                         "find_module", "O", fullname);
             if (loader == NULL)
                 return -1;  /* error */
             if (loader != Py_None) {
@@ -1753,7 +1757,7 @@
 #endif
         )
         buf[len++] = SEP;
-    strcpy(buf+len, name);
+    strcpy(buf+len, namestr);
     len += namelen;
 
     /* Check for package import (buf holds a directory name,
@@ -1761,7 +1765,7 @@
 #ifdef HAVE_STAT
     if (stat(buf, &statbuf) == 0 &&         /* it exists */
         S_ISDIR(statbuf.st_mode) &&         /* it's a directory */
-        case_ok(buf, len, namelen, name)) { /* case matches */
+        case_ok(buf, len, namelen, namestr)) { /* case matches */
         if (find_init_module(buf)) { /* and has __init__.py */
             *p_fd = &fd_package;
             return 2;
@@ -1784,7 +1788,7 @@
 }
 
 /* Find a module in search_path_list. For each path, try
-   find_module_filename() or try each _PyImport_Filetab suffix.
+   find_module_path() or try each _PyImport_Filetab suffix.
 
    If the module is found, return a file descriptor, write the path in
    *p_filename, write the pointer to the file object into *p_fp, and (if
@@ -1793,7 +1797,7 @@
    Otherwise, raise an exception and return NULL. */
 
 static struct filedescr*
-find_module_path_list(char *fullname, const char *name,
+find_module_path_list(PyObject *fullname, PyObject *name,
                       PyObject *search_path_list, PyObject *path_hooks,
                       PyObject *path_importer_cache,
                       char *buf, size_t buflen,
@@ -1804,9 +1808,11 @@
     struct filedescr *fdp = NULL;
     char *filemode;
     FILE *fp = NULL;
+    char *namestr;
 
     npath = PyList_Size(search_path_list);
-    namelen = strlen(name);
+    namestr = _PyUnicode_AsString(name);
+    namelen = strlen(namestr);
     for (i = 0; i < npath; i++) {
         PyObject *path;
         int ok;
@@ -1836,7 +1842,7 @@
                 filemode = "r" PY_STDIOTEXTMODE;
             fp = fopen(buf, filemode);
             if (fp != NULL) {
-                if (case_ok(buf, len, namelen, name))
+                if (case_ok(buf, len, namelen, namestr))
                     break;
                 else {                   /* continue search */
                     fclose(fp);
@@ -1849,7 +1855,7 @@
     }
     if (fp == NULL) {
         PyErr_Format(PyExc_ImportError,
-                     "No module named %.200s", name);
+                     "No module named %U", name);
         return NULL;
     }
     *p_fp = fp;
@@ -1882,21 +1888,20 @@
    set) are set to NULL. Eg. *buf is an empty string for a builtin package. */
 
 static struct filedescr *
-find_module(char *fullname, const char *name, PyObject *search_path_list,
+find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list,
             char *buf, size_t buflen, FILE **p_fp, PyObject **p_loader)
 {
     Py_ssize_t i, npath;
     static struct filedescr fd_frozen = {"", "", PY_FROZEN};
     static struct filedescr fd_builtin = {"", "", C_BUILTIN};
     PyObject *path_hooks, *path_importer_cache;
-    PyObject *fullname_obj, *nameobj;
 
     *buf = '\0';
     *p_fp = NULL;
     if (p_loader != NULL)
         *p_loader = NULL;
 
-    if (strlen(name) > MAXPATHLEN) {
+    if (PyUnicode_GET_SIZE(name) > MAXPATHLEN) {
         PyErr_SetString(PyExc_OverflowError,
                         "module name is too long");
         return NULL;
@@ -1919,7 +1924,7 @@
             PyObject *loader;
             PyObject *hook = PyList_GetItem(meta_path, i);
             loader = PyObject_CallMethod(hook, "find_module",
-                                         "sO", fullname,
+                                         "OO", fullname,
                                          search_path_list != NULL ?
                                          search_path_list : Py_None);
             if (loader == NULL) {
@@ -1937,16 +1942,9 @@
         Py_DECREF(meta_path);
     }
 
-    if (fullname != NULL) {
-        fullname_obj = PyUnicode_FromString(fullname);
-        if (fullname == NULL)
-            return NULL;
-        if (find_frozen(fullname_obj) != NULL) {
-            Py_DECREF(fullname_obj);
-            strcpy(buf, fullname);
-            return &fd_frozen;
-        }
-        Py_DECREF(fullname_obj);
+    if (find_frozen(fullname) != NULL) {
+        strcpy(buf, _PyUnicode_AsString(fullname));
+        return &fd_frozen;
     }
 
     if (search_path_list == NULL) {
@@ -1955,18 +1953,13 @@
         struct filedescr *fdp;
         PyObject *filename, *filename_bytes;
 #endif
-        nameobj = PyUnicode_FromString(name);
-        if (nameobj == NULL)
-            return NULL;
-        if (is_builtin(nameobj)) {
-            Py_DECREF(nameobj);
-            strcpy(buf, name);
+        if (is_builtin(name)) {
+            strcpy(buf, _PyUnicode_AsString(name));
             return &fd_builtin;
         }
 #ifdef MS_COREDLL
-        fp = _PyWin_FindRegisteredModule(nameobj, &fdp, &filename);
+        fp = _PyWin_FindRegisteredModule(name, &fdp, &filename);
         if (fp != NULL) {
-            Py_DECREF(nameobj);
             filename_bytes = PyUnicode_EncodeFSDefault(filename);
             Py_DECREF(filename);
             if (filename_bytes == NULL)
@@ -1980,7 +1973,6 @@
         else if (PyErr_Occurred())
             return NULL;
 #endif
-        Py_DECREF(nameobj);
         search_path_list = PySys_GetObject("path");
     }
 
@@ -3139,8 +3131,8 @@
         }
     }
 
-    fdp = find_module(_PyUnicode_AsString(fullname),
-                      _PyUnicode_AsString(subname),
+    fdp = find_module(fullname,
+                      subname,
                       path, buf, MAXPATHLEN+1,
                       &fp, &loader);
     Py_XDECREF(path);
@@ -3180,12 +3172,13 @@
     PyInterpreterState *interp = PyThreadState_Get()->interp;
     PyObject *modules_reloading = interp->modules_reloading;
     PyObject *modules = PyImport_GetModuleDict();
-    PyObject *path = NULL, *loader, *existing_m = NULL;
-    char *name, *subname;
     char buf[MAXPATHLEN+1];
+    PyObject *path = NULL, *loader = NULL, *existing_m = NULL;
+    PyObject *nameobj, *bufobj, *subnameobj;
+    Py_UNICODE *name, *subname;
     struct filedescr *fdp;
-    FILE *fp;
-    PyObject *newm, *nameobj, *bufobj;
+    FILE *fp = NULL;
+    PyObject *newm = NULL;
 
     if (modules_reloading == NULL) {
         Py_FatalError("PyImport_ReloadModule: "
@@ -3198,69 +3191,75 @@
                         "reload() argument must be module");
         return NULL;
     }
-    name = (char*)PyModule_GetName(m);
-    if (name == NULL)
+    nameobj = PyModule_GetNameObject(m);
+    if (nameobj == NULL)
         return NULL;
-    if (m != PyDict_GetItemString(modules, name)) {
+    if (m != PyDict_GetItem(modules, nameobj)) {
         PyErr_Format(PyExc_ImportError,
-                     "reload(): module %.200s not in sys.modules",
-                     name);
+                     "reload(): module %U not in sys.modules",
+                     nameobj);
+        Py_DECREF(nameobj);
         return NULL;
     }
-    existing_m = PyDict_GetItemString(modules_reloading, name);
+    existing_m = PyDict_GetItem(modules_reloading, nameobj);
     if (existing_m != NULL) {
         /* Due to a recursive reload, this module is already
            being reloaded. */
+        Py_DECREF(nameobj);
         Py_INCREF(existing_m);
         return existing_m;
     }
-    if (PyDict_SetItemString(modules_reloading, name, m) < 0)
+    if (PyDict_SetItem(modules_reloading, nameobj, m) < 0) {
+        Py_DECREF(nameobj);
         return NULL;
-
-    subname = strrchr(name, '.');
-    if (subname == NULL)
-        subname = name;
+    }
+
+    name = PyUnicode_AS_UNICODE(nameobj);
+    subname = Py_UNICODE_strrchr(name, '.');
+    if (subname == NULL) {
+        Py_INCREF(nameobj);
+        subnameobj = nameobj;
+    }
     else {
         PyObject *parentname, *parent;
-        parentname = PyUnicode_FromStringAndSize(name, (subname-name));
+        Py_ssize_t len;
+        len = subname - name;
+        parentname = PyUnicode_FromUnicode(name, len);
         if (parentname == NULL) {
-            imp_modules_reloading_clear();
-            return NULL;
+            goto error;
         }
         parent = PyDict_GetItem(modules, parentname);
         if (parent == NULL) {
             PyErr_Format(PyExc_ImportError,
-                "reload(): parent %R not in sys.modules",
+                "reload(): parent %U not in sys.modules",
                  parentname);
             Py_DECREF(parentname);
-            imp_modules_reloading_clear();
-            return NULL;
+            goto error;
         }
         Py_DECREF(parentname);
-        subname++;
         path = PyObject_GetAttrString(parent, "__path__");
         if (path == NULL)
             PyErr_Clear();
+        subname++;
+        len = PyUnicode_GET_SIZE(nameobj) - (len + 1);
+        subnameobj = PyUnicode_FromUnicode(subname, len);
     }
-    fdp = find_module(name, subname, path, buf, MAXPATHLEN+1, &fp, &loader);
+    if (subnameobj == NULL)
+        goto error;
+    fdp = find_module(nameobj, subnameobj,
+                      path, buf, MAXPATHLEN+1, &fp, &loader);
+    Py_DECREF(subnameobj);
     Py_XDECREF(path);
 
     if (fdp == NULL) {
         Py_XDECREF(loader);
-        imp_modules_reloading_clear();
-        return NULL;
+        goto error;
     }
 
-    nameobj = PyUnicode_FromString(name);
-    if (nameobj != NULL) {
-        bufobj = PyUnicode_DecodeFSDefault(buf);
-        if (bufobj != NULL) {
-            newm = load_module(nameobj, fp, bufobj, fdp->type, loader);
-            Py_DECREF(bufobj);
-        }
-        else
-            newm = NULL;
-        Py_DECREF(nameobj);
+    bufobj = PyUnicode_DecodeFSDefault(buf);
+    if (bufobj != NULL) {
+        newm = load_module(nameobj, fp, bufobj, fdp->type, loader);
+        Py_DECREF(bufobj);
     }
     else
         newm = NULL;
@@ -3274,9 +3273,12 @@
          * going to return NULL in this case regardless of whether
          * replacing name succeeds, so the return value is ignored.
          */
-        PyDict_SetItemString(modules, name, m);
+        PyDict_SetItem(modules, nameobj, m);
     }
+
+error:
     imp_modules_reloading_clear();
+    Py_DECREF(nameobj);
     return newm;
 }
 
@@ -3424,7 +3426,7 @@
 }
 
 static PyObject *
-call_find_module(char *name, PyObject *path)
+call_find_module(PyObject *name, PyObject *path)
 {
     extern int fclose(FILE *);
     PyObject *fob, *ret;
@@ -3483,15 +3485,11 @@
 static PyObject *
 imp_find_module(PyObject *self, PyObject *args)
 {
-    PyObject *name;
-    PyObject *ret, *path = NULL;
-    if (!PyArg_ParseTuple(args, "O&|O:find_module",
-                          PyUnicode_FSConverter, &name,
-                          &path))
+    PyObject *name, *path_list = NULL;
+    if (!PyArg_ParseTuple(args, "U|O:find_module",
+                          &name, &path_list))
         return NULL;
-    ret = call_find_module(PyBytes_AS_STRING(name), path);
-    Py_DECREF(name);
-    return ret;
+    return call_find_module(name, path_list);
 }
 
 static PyObject *

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


More information about the Python-checkins mailing list