filemode = fdp->mode;
if (filemode[0] == 'U')
filemode = "r" PY_STDIOTEXTMODE;
- 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);
+
+ 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;
+
+ if (PyUnicode_GET_SIZE(name) > MAXPATHLEN) {
+ PyErr_SetString(PyExc_OverflowError,
+ "module name is too long");
+ return 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_ImportError,
++ 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_ImportError,
++ PyErr_SetString(PyExc_RuntimeError,
+ "sys.path must be a list of directory names");
+ return NULL;
+ }
+
+ path_hooks = PySys_GetObject("path_hooks");
+ if (path_hooks == NULL || !PyList_Check(path_hooks)) {
- PyErr_SetString(PyExc_ImportError,
++ PyErr_SetString(PyExc_RuntimeError,
+ "sys.path_hooks must be a list of "
+ "import hooks");
return NULL;
}
- *p_fp = fp;
- return fdp;
+ path_importer_cache = PySys_GetObject("path_importer_cache");
+ if (path_importer_cache == NULL ||
+ !PyDict_Check(path_importer_cache)) {
- PyErr_SetString(PyExc_ImportError,
++ 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
* ^ ^ ^ ^