if (loader != Py_None) {
/* a loader was found */
*p_loader = loader;
- Py_DECREF(meta_path);
- return &importhookdescr;
+ *p_fd = &importhookdescr;
+ return 2;
}
Py_DECREF(loader);
+ return 0;
}
- Py_DECREF(meta_path);
- }
-
- if (find_frozen(fullname) != NULL) {
- strcpy(buf, fullname);
- return &fd_frozen;
}
+ /* no hook was found, use builtin import */
- if (path == NULL) {
- if (is_builtin(name)) {
- strcpy(buf, name);
- return &fd_builtin;
- }
-#ifdef MS_COREDLL
- fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen);
- if (fp != NULL) {
- *p_fp = fp;
- return fdp;
- }
+ if (len > 0 && buf[len-1] != SEP
+#ifdef ALTSEP
+ && buf[len-1] != ALTSEP
#endif
- path = PySys_GetObject("path");
- }
-
- if (path == NULL || !PyList_Check(path)) {
- PyErr_SetString(PyExc_RuntimeError,
- "sys.path must be a list of directory names");
- return NULL;
- }
+ )
+ buf[len++] = SEP;
+ Py_UNICODE_strcpy(buf+len, PyUnicode_AS_UNICODE(name));
+ len += PyUnicode_GET_SIZE(name);
- path_hooks = PySys_GetObject("path_hooks");
- if (path_hooks == NULL || !PyList_Check(path_hooks)) {
- PyErr_SetString(PyExc_RuntimeError,
- "sys.path_hooks must be a list of "
- "import hooks");
- return NULL;
- }
- path_importer_cache = PySys_GetObject("path_importer_cache");
- if (path_importer_cache == NULL ||
- !PyDict_Check(path_importer_cache)) {
- PyErr_SetString(PyExc_RuntimeError,
- "sys.path_importer_cache must be a dict");
- return NULL;
- }
+ filename = PyUnicode_FromUnicode(buf, len);
+ if (filename == NULL)
+ return -1;
- npath = PyList_Size(path);
- namelen = strlen(name);
- for (i = 0; i < npath; i++) {
- PyObject *v = PyList_GetItem(path, i);
- PyObject *origv = v;
- const char *base;
- Py_ssize_t size;
- if (!v)
- return NULL;
- if (PyUnicode_Check(v)) {
- v = PyUnicode_EncodeFSDefault(v);
- if (v == NULL)
- return NULL;
- }
- else if (!PyBytes_Check(v))
- continue;
- else
- Py_INCREF(v);
-
- base = PyBytes_AS_STRING(v);
- size = PyBytes_GET_SIZE(v);
- len = size;
- if (len + 2 + namelen + MAXSUFFIXSIZE >= buflen) {
- Py_DECREF(v);
- continue; /* Too long */
- }
- strcpy(buf, base);
- Py_DECREF(v);
+ /* Check for package import (buf holds a directory name,
+ and there's an __init__ module in that directory */
+#ifdef HAVE_STAT
+ if (_Py_stat(filename, &statbuf) == 0 && /* it exists */
+ S_ISDIR(statbuf.st_mode)) /* it's a directory */
+ {
+ int match;
- if (strlen(buf) != len) {
- continue; /* v contains '\0' */
+ match = case_ok(filename, 0, name);
+ if (match < 0) {
+ Py_DECREF(filename);
+ return -1;
}
-
- /* sys.path_hooks import hook */
- if (p_loader != NULL) {
- PyObject *importer;
-
- importer = get_path_importer(path_importer_cache,
- path_hooks, origv);
- if (importer == NULL) {
- return NULL;
+ if (match) { /* case matches */
+ if (find_init_module(filename)) { /* and has __init__.py */
+ *p_path = filename;
+ *p_fd = &fd_package;
+ return 2;
}
- /* Note: importer is a borrowed reference */
- if (importer != Py_None) {
- PyObject *loader;
- loader = PyObject_CallMethod(importer,
- "find_module",
- "s", fullname);
- if (loader == NULL)
- return NULL; /* error */
- if (loader != Py_None) {
- /* a loader was found */
- *p_loader = loader;
- return &importhookdescr;
+ else {
+ int err;
+ err = PyErr_WarnFormat(PyExc_ImportWarning, 1,
+ "Not importing directory %R: missing __init__.py",
+ filename);
+ if (err) {
+ Py_DECREF(filename);
+ return -1;
}
- Py_DECREF(loader);
- continue;
}
}
- /* no hook was found, use builtin import */
-
- if (len > 0 && buf[len-1] != SEP
-#ifdef ALTSEP
- && buf[len-1] != ALTSEP
+ }
#endif
- )
- buf[len++] = SEP;
- strcpy(buf+len, name);
- len += namelen;
+ *p_path = filename;
+ return 1;
+}
- /* Check for package import (buf holds a directory name,
- and there's an __init__ module in that directory */
-#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 */
- if (find_init_module(buf)) { /* and has __init__.py */
- return &fd_package;
- }
- else {
- int err;
- PyObject *unicode = PyUnicode_DecodeFSDefault(buf);
- if (unicode == NULL)
- return NULL;
- err = PyErr_WarnFormat(PyExc_ImportWarning, 1,
- "Not importing directory '%U': missing __init__.py",
- unicode);
- Py_DECREF(unicode);
- if (err)
- return NULL;
- }
+/* Find a module in search_path_list. For each path, try
+ 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
+ p_loader is not NULL) the loader into *p_loader.
+
+ Otherwise, raise an exception and return NULL. */
+
+static struct filedescr*
+find_module_path_list(PyObject *fullname, PyObject *name,
+ PyObject *search_path_list, PyObject *path_hooks,
+ PyObject *path_importer_cache,
+ PyObject **p_path, FILE **p_fp, PyObject **p_loader)
+{
+ Py_ssize_t i, npath;
+ struct filedescr *fdp = NULL;
+ char *filemode;
+ FILE *fp = NULL;
+ PyObject *prefix, *filename;
+ int match;
+
+ npath = PyList_Size(search_path_list);
+ for (i = 0; i < npath; i++) {
+ PyObject *path;
+ int ok;
+
+ path = PyList_GetItem(search_path_list, i);
+ if (path == NULL)
+ return NULL;
+
+ prefix = NULL;
+ ok = find_module_path(fullname, name, path,
+ path_hooks, path_importer_cache,
+ &prefix, p_loader, &fdp);
+ if (ok < 0)
+ return NULL;
+ if (ok == 0)
+ continue;
+ if (ok == 2) {
+ *p_path = prefix;
+ return fdp;
}
-#endif
-#if defined(PYOS_OS2)
- /* take a snapshot of the module spec for restoration
- * after the 8 character DLL hackery
- */
- saved_buf = strdup(buf);
- saved_len = len;
- saved_namelen = namelen;
-#endif /* PYOS_OS2 */
+
for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) {
-#if defined(PYOS_OS2) && defined(HAVE_DYNAMIC_LOADING)
- /* OS/2 limits DLLs to 8 character names (w/o
- extension)
- * so if the name is longer than that and its a
- * dynamically loaded module we're going to try,
- * truncate the name before trying
- */
- if (strlen(subname) > 8) {
- /* is this an attempt to load a C extension? */
- const struct filedescr *scan;
- scan = _PyImport_DynLoadFiletab;
- while (scan->suffix != NULL) {
- if (!strcmp(scan->suffix, fdp->suffix))
- break;
- else
- scan++;
- }
- if (scan->suffix != NULL) {
- /* yes, so truncate the name */
- namelen = 8;
- len -= strlen(subname) - namelen;
- buf[len] = '\0';
- }
- }
-#endif /* PYOS_OS2 */
- strcpy(buf+len, fdp->suffix);
- if (Py_VerboseFlag > 1)
- PySys_WriteStderr("# trying %s\n", buf);
+ struct stat statbuf;
+
filemode = fdp->mode;
if (filemode[0] == 'U')
filemode = "r" PY_STDIOTEXTMODE;
- if (stat(buf, &statbuf) == 0 && S_ISDIR(statbuf.st_mode))
- /* it's a directory */
- fp = NULL;
- else
- fp = fopen(buf, filemode);
- if (fp != NULL) {
- if (case_ok(buf, len, namelen, name))
- break;
- else { /* continue search */
- fclose(fp);
- fp = NULL;
+ filename = PyUnicode_FromFormat("%U%s", prefix, fdp->suffix);
+ if (filename == NULL) {
+ Py_DECREF(prefix);
+ return NULL;
+ }
+
+ if (Py_VerboseFlag > 1)
+ PySys_FormatStderr("# trying %R\n", filename);
+
++ if (_Py_stat(filename, &statbuf) == 0 && /* it exists */
++ S_ISDIR(statbuf.st_mode)) /* it's a directory */
++ {
++ Py_DECREF(filename);
++ continue;
++ }
++
+ fp = _Py_fopen(filename, filemode);
+ if (fp == NULL) {
+ Py_DECREF(filename);
+ if (PyErr_Occurred()) {
+ Py_DECREF(prefix);
+ return NULL;
}
+ continue;
}
-#if defined(PYOS_OS2)
- /* restore the saved snapshot */
- strcpy(buf, saved_buf);
- len = saved_len;
- namelen = saved_namelen;
-#endif
+ match = case_ok(filename, -(Py_ssize_t)strlen(fdp->suffix), name);
+ if (match < 0) {
+ Py_DECREF(prefix);
+ Py_DECREF(filename);
+ return NULL;
+ }
+ if (match) {
+ Py_DECREF(prefix);
+ *p_path = filename;
+ *p_fp = fp;
+ return fdp;
+ }
+ Py_DECREF(filename);
+
+ fclose(fp);
+ fp = NULL;
}
-#if defined(PYOS_OS2)
- /* don't need/want the module name snapshot anymore */
- if (saved_buf)
- {
- free(saved_buf);
- saved_buf = NULL;
+ Py_DECREF(prefix);
+ }
+ PyErr_Format(PyExc_ImportError,
+ "No module named %R", name);
+ return NULL;
+}
+
+/* Find a module:
+
+ - try find_module() of each sys.meta_path hook
+ - try find_frozen()
+ - try is_builtin()
+ - try _PyWin_FindRegisteredModule() (Windows only)
+ - otherwise, call find_module_path_list() with search_path_list (if not
+ NULL) or sys.path
+
+ fullname can be NULL, but only if p_loader is NULL.
+
+ Return:
+
+ - &fd_builtin (C_BUILTIN) if it is a builtin
+ - &fd_frozen (PY_FROZEN) if it is frozen
+ - &fd_package (PKG_DIRECTORY) and write the filename into *p_path
+ if it is a package
+ - &importhookdescr (IMP_HOOK) and write the loader into *p_loader if a
+ importer loader was found
+ - a file descriptor (PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE or
+ PY_CODERESOURCE: see _PyImport_Filetab), write the filename into
+ *p_path and the pointer to the open file into *p_fp
+ - NULL on error
+
+ By default, *p_path, *p_fp and *p_loader (if set) are set to NULL.
+ Eg. *p_path is set to NULL for a builtin package.
+*/
+
+static struct filedescr *
+find_module(PyObject *fullname, PyObject *name, PyObject *search_path_list,
+ PyObject **p_path, 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;
+
+ *p_path = NULL;
+ *p_fp = NULL;
+ if (p_loader != NULL)
+ *p_loader = NULL;
+
+ /* sys.meta_path import hook */
+ if (p_loader != NULL) {
+ PyObject *meta_path;
+
+ meta_path = PySys_GetObject("meta_path");
+ if (meta_path == NULL || !PyList_Check(meta_path)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "sys.meta_path must be a list of "
+ "import hooks");
+ return NULL;
+ }
+ Py_INCREF(meta_path); /* zap guard */
+ npath = PyList_Size(meta_path);
+ for (i = 0; i < npath; i++) {
+ PyObject *loader;
+ PyObject *hook = PyList_GetItem(meta_path, i);
+ loader = PyObject_CallMethod(hook, "find_module",
+ "OO", fullname,
+ search_path_list != NULL ?
+ search_path_list : Py_None);
+ if (loader == NULL) {
+ Py_DECREF(meta_path);
+ return NULL; /* true error */
+ }
+ if (loader != Py_None) {
+ /* a loader was found */
+ *p_loader = loader;
+ Py_DECREF(meta_path);
+ return &importhookdescr;
+ }
+ Py_DECREF(loader);
}
+ Py_DECREF(meta_path);
+ }
+
+ if (find_frozen(fullname) != NULL)
+ return &fd_frozen;
+
+ if (search_path_list == NULL) {
+#ifdef MS_COREDLL
+ FILE *fp;
+ struct filedescr *fdp;
#endif
- if (fp != NULL)
- break;
+ if (is_builtin(name))
+ return &fd_builtin;
+#ifdef MS_COREDLL
+ fp = _PyWin_FindRegisteredModule(name, &fdp, p_path);
+ if (fp != NULL) {
+ *p_fp = fp;
+ return fdp;
+ }
+ else if (PyErr_Occurred())
+ return NULL;
+#endif
+ search_path_list = PySys_GetObject("path");
}
- if (fp == NULL) {
- PyErr_Format(PyExc_ImportError,
- "No module named %.200s", name);
+
+ if (search_path_list == NULL || !PyList_Check(search_path_list)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "sys.path must be a list of directory names");
return NULL;
}
- *p_fp = fp;
- return fdp;
+
+ path_hooks = PySys_GetObject("path_hooks");
+ if (path_hooks == NULL || !PyList_Check(path_hooks)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "sys.path_hooks must be a list of "
+ "import hooks");
+ return NULL;
+ }
+ path_importer_cache = PySys_GetObject("path_importer_cache");
+ if (path_importer_cache == NULL ||
+ !PyDict_Check(path_importer_cache)) {
+ PyErr_SetString(PyExc_RuntimeError,
+ "sys.path_importer_cache must be a dict");
+ return NULL;
+ }
+
+ return find_module_path_list(fullname, name,
+ search_path_list, path_hooks,
+ path_importer_cache,
+ p_path, p_fp, p_loader);
}
-/* case_ok(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name)
+/* case_bytes(char* buf, Py_ssize_t len, Py_ssize_t namelen, char* name)
* The arguments here are tricky, best shown by example:
* /a/b/c/d/e/f/g/h/i/j/k/some_long_module_name.py\0
* ^ ^ ^ ^