*** import.c.orig Tue Jul 9 10:17:11 2002 --- import.c Tue Jul 9 11:16:31 2002 *************** *** 60,65 **** --- 60,129 ---- /* these tables define the module suffixes that Python recognizes */ struct filedescr * _PyImport_Filetab = NULL; + static struct filedescr fd_frozen = {"", "", PY_FROZEN}; + static struct filedescr fd_builtin = {"", "", C_BUILTIN}; + static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; + static struct filedescr fd_zip = {"", "", PY_ZIPFILE}; + + static struct stZipSearchOrder { + char suffix[16]; + int type; + } ZipSearchOrder[] = { + {"/__init__.pyc", PKG_DIRECTORY}, + {"/__init__.pyo", PKG_DIRECTORY}, + {"/__init__.py", PKG_DIRECTORY}, + {".pyc", PY_ZIPFILE}, + {".pyo", PY_ZIPFILE}, + {".py", PY_ZIPFILE}, + {"", 0} + }; + + #define PY_IMP_NO_VALUE 0 + #define PY_IMP_BUILTIN 1 + #define PY_IMP_FROZEN 2 + #define PY_IMP_LISTDIR 3 + #define PY_IMP_NO_LISTDIR 4 + #define PY_IMP_FILE 5 + #define PY_IMP_ZIP 6 + #define PY_CACHE_USING_OS_LISTDIR 1 + + static int use_os_listdir = 0; /* 0: init, 1: use os.listdir, -1: don't use */ + static PyObject * ExternalNames = NULL; + static PyObject * InternalNames = NULL; + static void get_internal_names(void); + static struct filedescr * search_using_fopen(char *, char *, + size_t, size_t, FILE **); + + /* + Import dictionary entries have values of int or tuple. An int value + must be one of the PY_IMP_ constants. For a sequence, the first item + of the sequence must be one of the PY_IMP_ constants. + + InternalNames is a dictionary: keys are the names of all builtin and + frozen modules, value is PY_IMP_BUILTIN or PY_IMP_FROZEN. It is + used to speed up searching for internal modules. + + ExternalNames is a dictionary used to speed up imports. Keys are: + Names of zip archive files; value is PY_IMP_ZIP. + For example, /A/B/python22.zip. + Names of items in sys.path; values are: + PY_IMP_ZIP: The string ".zip" appears in the sys.path item. + For example, /A/B/python22.zip, /A/B/python22.zip/LibFoo. + PY_IMP_LISTDIR: A directory; use os.listdir() to record contents. + For example, /A/B/C. + PY_IMP_NO_LISTDIR: os.listdir() is not available. + For example, /A/B/C. + Names of files in the zip archive joined with the zip archive name. + For example, /usr/lib/python22.zip/Dir/mymodule.py. + Zip paths are always spelled with SEP instead of '/'. + The value is a tuple, and the first item is PY_IMP_ZIP. + Names of files in the directory joined with the directory name. + Names are returned using os.listdir(). + For example, /A/B/C/jim.pyc + The value is PY_IMP_FILE. + If os.listdir() is not available, the directory entries are absent. + */ + #ifdef RISCOS static const struct filedescr _PyImport_StandardFiletab[] = { {"/py", "r", PY_SOURCE}, *************** *** 122,127 **** --- 186,213 ---- code created in normal operation mode. */ pyc_magic = MAGIC + 1; } + + if (ExternalNames) + PyDict_Clear(ExternalNames); + else + ExternalNames = PyDict_New(); + if (InternalNames) + PyDict_Clear(InternalNames); + else + InternalNames = PyDict_New(); + ZipSearchOrder[0].suffix[0] = SEP; /* Correct directory separator */ + ZipSearchOrder[1].suffix[0] = SEP; + ZipSearchOrder[2].suffix[0] = SEP; + if (Py_OptimizeFlag) { /* Reverse *.pyc and *.pyo */ + struct stZipSearchOrder zso; + zso = ZipSearchOrder[0]; + ZipSearchOrder[0] = ZipSearchOrder[1]; + ZipSearchOrder[1] = zso; + zso = ZipSearchOrder[3]; + ZipSearchOrder[3] = ZipSearchOrder[4]; + ZipSearchOrder[4] = zso; + } + get_internal_names(); } void *************** *** 131,136 **** --- 217,226 ---- extensions = NULL; PyMem_DEL(_PyImport_Filetab); _PyImport_Filetab = NULL; + Py_XDECREF(ExternalNames); + ExternalNames = NULL; + Py_XDECREF(InternalNames); + InternalNames = NULL; } *************** *** 201,206 **** --- 291,781 ---- #endif } + /* Helper functions to import from zip archives */ + + void PyImport_InitZip() + { + PyObject *zlib; + int have_zlib; + + zlib = PyImport_ImportModule("zlib"); /* import zlib */ + if (zlib) { + have_zlib = 1; + Py_DECREF(zlib); + } + else { + have_zlib = 0; + PyErr_Clear(); + } + if (Py_VerboseFlag) + PySys_WriteStderr("# PyImport_InitZip: zlib %s\n", + have_zlib? "available": "UNAVAILABLE"); + + #if PY_CACHE_USING_OS_LISTDIR + { + PyObject *v, *vv; + v = PyImport_ImportModule("os"); /* import the os module */ + vv = NULL; + if (v && (vv = PyObject_GetAttrString(v, "listdir")) != NULL) { + if (Py_VerboseFlag) + PySys_WriteStderr("Import os.listdir() succeeds\n"); + use_os_listdir = 1; /* os.listdir() is available */ + } + else { + if (Py_VerboseFlag) + PySys_WriteStderr("Import os.listdir() fails\n"); + PyErr_Clear(); + use_os_listdir = -1; /* os.listdir() is not available */ + } + Py_XDECREF(vv); + Py_XDECREF(v); + } + #else + use_os_listdir = -1; /* os.listdir() is not available */ + #endif + } + + static void get_internal_names() + { + int i; + PyObject *v; + struct _frozen *pFrozen; + + if (!InternalNames) + return; + PyDict_Clear(InternalNames); + /* Add frozen module names to the import dictionary */ + v = PyInt_FromLong(PY_IMP_FROZEN); + for (pFrozen = PyImport_FrozenModules; pFrozen->name; pFrozen++) + PyDict_SetItemString(InternalNames, pFrozen->name, v); + Py_DECREF(v); + /* Add builtin module names to the import dictionary */ + v = PyInt_FromLong(PY_IMP_BUILTIN); + for (i = 0; PyImport_Inittab[i].name; i++) + PyDict_SetItemString(InternalNames, PyImport_Inittab[i].name, v); + Py_DECREF(v); + } + + static int relative_path(char *path) + { /* Return TRUE if path is a relative (non-absolute) path */ + if (path[0] == 0) /* zero-length string is current dir */ + return 1; + #ifdef macintosh + return !strchr(path, ':') || path[0] == ':'; + #else + if (SEP == '\\') /* Windows-type requires a drive letter */ + return !(path[1] == ':' && (path[2] == SEP + #ifdef ALTSEP + || path[2] == ALTSEP + #endif + )); + return path[0] != SEP; /* Unix and all other */ + #endif + } + + static int get_path_type(PyObject *dict, char *path) + { /* return one of the PY_IMP_ constants for the import dictionary path */ + PyObject *pyobj; + int i; + + pyobj = PyDict_GetItemString(dict, path); + if (!pyobj) + return PY_IMP_NO_VALUE; + if (PyInt_Check(pyobj)) + return (int)PyInt_AsLong(pyobj); + if (PySequence_Check(pyobj)) { + pyobj = PySequence_GetItem(pyobj, 0); + if (pyobj && PyInt_Check(pyobj)) { + i = (int)PyInt_AsLong(pyobj); + Py_DECREF(pyobj); + return i; + } + Py_XDECREF(pyobj); + } + return PY_IMP_NO_VALUE; + } + + static void add_directory_names(char *path) + { /* Read the directory names and add to ExternalNames */ + PyObject *v, *modules, *modOS, *pyList, *func, *args, *pyFile; + long count, i, length; + char name[MAXPATHLEN + 5]; + char *filename; + + if (get_path_type(ExternalNames, path) == PY_IMP_LISTDIR) + return; /* We have already seen this directory */ + v = PyInt_FromLong(PY_IMP_LISTDIR); + PyDict_SetItemString(ExternalNames, path, v); + Py_DECREF(v); + modules = PyImport_GetModuleDict(); + if (!modules) + return; + modOS = PyDict_GetItemString(modules, "os"); + if (!modOS) + return; + func = PyObject_GetAttrString(modOS, "listdir"); + if (!func) + return; + args = Py_BuildValue("(s)", path); + pyList = PyEval_CallObject(func, args); + Py_DECREF(args); + Py_DECREF(func); + if (!pyList || !PyList_Check(pyList)) { + PyErr_Clear(); + if (Py_VerboseFlag) + PySys_WriteStderr("# directory: ADD 0 names from %s\n", path); + return; + } + count = PyList_Size(pyList); + if (Py_VerboseFlag) + PySys_WriteStderr("# directory: ADD %ld names from %s\n", count, path); + strncpy(name, path, MAXPATHLEN); + length = strlen(name); + if (name[length - 1] != SEP + #ifdef ALTSEP + && name[length - 1] != ALTSEP + #endif + ) + name[length++] = SEP; + pyFile = PyInt_FromLong(PY_IMP_FILE); + for (i = 0; i < count; i++) { + filename = PyString_AsString(PyList_GetItem(pyList, i)); + /* Join member name to archive name */ + strncpy(name + length, filename, MAXPATHLEN - length); + PyDict_SetItemString(ExternalNames, name, pyFile); + } + Py_DECREF(pyFile); + Py_DECREF(pyList); + return; + } + + static int add_zip_names(char *path) + { /* Read all zip archive names and add to ExternalNames */ + /* Return 1 if path is a zip archive, else 0 */ + PyObject *pyTuple, *pyZip; + FILE *fp; + long compress, crc, data_size, file_size, file_offset, date, time; + long header_offset, name_size, header_size; + long i, l, length, count; + char archive[MAXPATHLEN + 5]; + char zipname[MAXPATHLEN + 5]; + char ch, *pt; + + /* The "path" is an item of sys.path. We need to extract the zip + file name and read the contents of the archive. + Indicate that we have already seen this item by creating a + dictionary entry for the path. + */ + + l = (long)strlen(path) - 4; + length = 0; + for (i = 1; i <= l; i++) /* Search for ".zip/" */ + if (path[i] == '.' && path[i+1] == 'z' && + path[i+2] == 'i' && path[i+3] == 'p' && + ((ch = path[i+4]) == SEP || + #ifdef ALTSEP + ch == ALTSEP || + #endif + ch == 0)) { + length = i + 4; + strncpy(archive, path, length); + archive[length] = 0; + break; + + } + if (!length) + return 0; /* There is no ".zip" in the name */ + #ifdef ALTSEP + for (i = 0; i < length; i++) /* Use only SEP in zip names */ + if (archive[i] == ALTSEP) + archive[i] = SEP; + #endif + pyZip = PyInt_FromLong(PY_IMP_ZIP); /* Mark path as seen */ + /* "archive" is now the path up to and including ".zip" */ + if (PyDict_GetItemString(ExternalNames, archive)) { + PyDict_SetItemString(ExternalNames, path, pyZip); + Py_DECREF(pyZip); + return 1; /* We have already seen this archive */ + } + else { + PyDict_SetItemString(ExternalNames, path, pyZip); + PyDict_SetItemString(ExternalNames, archive, pyZip); + } + fp = fopen(archive, "rb"); + if (!fp) { /* Not an error; no such file */ + Py_DECREF(pyZip); + return 1; + } + fseek(fp, -22, 2); /* Seek from end of file */ + if (PyMarshal_ReadLongFromFile(fp) != 0x06054B50) { + fclose(fp); + Py_DECREF(pyZip); + return 1; /* Bad: End of Central Dir signature */ + } + fseek(fp, -6, 2); + header_offset = PyMarshal_ReadLongFromFile(fp); + /* Start of Central Directory */ + length = (long)strlen(archive); + count = 0; + while(1) { + fseek(fp, header_offset, 0); /* Start of file header */ + l = PyMarshal_ReadLongFromFile(fp); + if (l != 0x02014B50) + break; /* Bad: Central Dir File Header */ + fseek(fp, header_offset + 10, 0); + compress = PyMarshal_ReadShortFromFile(fp); + time = PyMarshal_ReadShortFromFile(fp); + date = PyMarshal_ReadShortFromFile(fp); + crc = PyMarshal_ReadLongFromFile(fp); + data_size = PyMarshal_ReadLongFromFile(fp); + file_size = PyMarshal_ReadLongFromFile(fp); + name_size = PyMarshal_ReadShortFromFile(fp); + header_size = 46 + name_size + + PyMarshal_ReadShortFromFile(fp) + + PyMarshal_ReadShortFromFile(fp); + fseek(fp, header_offset + 42, 0); + file_offset = PyMarshal_ReadLongFromFile(fp); + if (name_size > MAXPATHLEN) + name_size = MAXPATHLEN; + /* Unicode: zipname should work even if sizeof(char) > 1 */ + pt = zipname; + *pt++ = SEP; /* Add an initial '/' */ + for (i = 0; i < name_size; i++) { + ch = (char)getc(fp); + /* Must change '/' to SEP in archive */ + if (ch == '/' || ch == '\\') { + if (i > 0) /* Remove an initial '/' */ + *pt++ = SEP; + } + else + *pt++ = ch; + } + *pt = 0; /* Add ending null byte */ + header_offset += header_size; + /* Check to make sure the local file header is correct */ + fseek(fp, file_offset, 0); + l = PyMarshal_ReadLongFromFile(fp); + if (l != 0x04034B50) + continue; /* Bad: Local File Header */ + fseek(fp, file_offset + 26, 0); + l = 30 + PyMarshal_ReadShortFromFile(fp) + + PyMarshal_ReadShortFromFile(fp); /* local header size */ + file_offset += l; /* Start of file data */ + archive[length] = 0; + /* Record zip archive data for this file name */ + pyTuple = PyTuple_New(6); + Py_INCREF(pyZip); + PyTuple_SetItem(pyTuple, 0, pyZip); + PyTuple_SetItem(pyTuple, 1, PyString_FromString(archive)); + PyTuple_SetItem(pyTuple, 2, PyInt_FromLong(compress)); + PyTuple_SetItem(pyTuple, 3, PyInt_FromLong(data_size)); + PyTuple_SetItem(pyTuple, 4, PyInt_FromLong(file_size)); + PyTuple_SetItem(pyTuple, 5, PyInt_FromLong(file_offset)); + /* Join member name to archive name */ + strncpy(archive + length, zipname, MAXPATHLEN - length); + PyDict_SetItemString(ExternalNames, archive, pyTuple); + Py_DECREF(pyTuple); + count++; + } + fclose(fp); + Py_DECREF(pyZip); + archive[length] = 0; + if (Py_VerboseFlag) + PySys_WriteStderr("# zip import: add %ld names from %s\n", + count, archive); + return 1; + } + + static PyObject * + get_zip_string(char *name) + { /* Return the string from the zip archive */ + PyObject *modules, *mZlib, *pyTuple, *deobj; + PyObject *pyData, *pyFile1, *pyFile2, *method, *decomp, *args; + int nerr; + long compress, data_size, file_size, file_offset; + char *archive, *data; + FILE *fp; + + /* This function must set its own errors if it returns NULL */ + pyTuple = PyDict_GetItemString(ExternalNames, name); + if (!pyTuple || !PyTuple_Check(pyTuple)) { + PyErr_Format(PyExc_ValueError, + "Zip import: no data for %s", name); + return NULL; + } + archive = PyString_AsString(PyTuple_GetItem(pyTuple, 1)); + compress = PyInt_AsLong(PyTuple_GetItem(pyTuple, 2)); + data_size = PyInt_AsLong(PyTuple_GetItem(pyTuple, 3)); + file_size = PyInt_AsLong(PyTuple_GetItem(pyTuple, 4)); + file_offset = PyInt_AsLong(PyTuple_GetItem(pyTuple, 5)); + fp = fopen(archive, "rb"); + if (!fp) { + PyErr_Format(PyExc_IOError, + "Zip import: can not open file %s", archive); + return NULL; + } + data = (char *)PyMem_Malloc(data_size); + fseek(fp, file_offset, 0); + fread(data, 1, data_size, fp); + fclose(fp); + /* Should use an API to create a string stealing the data ref */ + pyData = PyString_FromStringAndSize(data, data_size); + PyMem_Free(data); + if (compress == 0) /* data is not compressed */ + return pyData; + /* Uncompress with zlib */ + modules = PyImport_GetModuleDict(); + if (!modules || + (mZlib = PyDict_GetItemString(modules, "zlib")) == NULL) { + Py_DECREF(pyData); + PyErr_Format(PyExc_ImportError, + "Zip import: missing zlib, can not decompress %s", name); + return NULL; + } + /* We would prefer to use zlib.decompress(), but it sometimes returns -5 */ + decomp = method = NULL; + deobj = PyObject_GetAttrString(mZlib, "decompressobj"); + if (!deobj) { + nerr = 1; + goto error; + } + args = Py_BuildValue("(l)", -15L); + decomp = PyEval_CallObject(deobj, args); + Py_DECREF(args); + if (!decomp) { + nerr = 2; + goto error; + } + method = PyObject_GetAttrString(decomp, "decompress"); + if (!method) { + nerr = 3; + goto error; + } + args = PyTuple_New(1); + PyTuple_SetItem(args, 0, pyData); + pyData = NULL; + pyFile1 = PyEval_CallObject(method, args); + if (!pyFile1 || !PyString_Check(pyFile1)) { + Py_DECREF(args); + nerr = 4; + goto error; + } + pyFile2 = PyEval_CallObject(method, args); + while(pyFile2 && PyString_Check(pyFile2) && PyString_Size(pyFile2)) { + PyString_ConcatAndDel(&pyFile1, pyFile2); + pyFile2 = PyEval_CallObject(method, args); + } + Py_DECREF(args); + Py_DECREF(method); + Py_DECREF(decomp); + Py_DECREF(deobj); + deobj = decomp = method = NULL; + Py_XDECREF(pyFile2); + if (pyFile1 && PyString_Check(pyFile1) && + PyString_Size(pyFile1) == file_size) + return pyFile1; + Py_XDECREF(pyFile1); + nerr = 5; + error: + Py_XDECREF(method); + Py_XDECREF(decomp); + Py_XDECREF(deobj); + Py_XDECREF(pyData); + PyErr_Format(PyExc_ImportError, + "Zip import: failure %d in decompressing %s", nerr, name); + return NULL; + } + + static PyObject * + load_zip_source_module(char *name, char *pathname) + { + PyObject *pyStr, *m; + PyCodeObject *code; + node *n; + char *pt; + + /* pathname ends in ".py" */ + pyStr = get_zip_string(pathname); + if (pyStr == NULL) + return NULL; + pt = PyString_AsString(pyStr); + n = PyParser_SimpleParseString(pt, Py_file_input); + if (n == NULL) { + Py_DECREF(pyStr); + return NULL; + } + code = PyNode_Compile(n, pathname); + PyNode_Free(n); + if (code == NULL) { + Py_DECREF(pyStr); + return NULL; + } + if (Py_VerboseFlag) + PySys_WriteStderr("import %s # source from zip %s\n", + name, pathname); + m = PyImport_ExecCodeModuleEx(name, (PyObject *)code, pathname); + Py_DECREF(code); + Py_DECREF(pyStr); + + return m; + } + + static PyObject * + load_zip_module(char *name, char *pathname) + { + long size; + PyObject *pyStr, *m, *code; + unsigned char *pt; + char source[MAXPATHLEN]; + + /* pathname ends in ".py" or ".pyc" or ".pyo" */ + size = (long)strlen(pathname); + if (pathname[size-3] == '.' && + pathname[size-2] == 'p' && + pathname[size-1] == 'y') + return load_zip_source_module(name, pathname); + pyStr = get_zip_string(pathname); + if (pyStr == NULL) + return NULL; + pt = PyString_AsString(pyStr); + size = PyString_Size(pyStr); + if (pt[0] != ( pyc_magic & 0xFF) || + pt[1] != ((pyc_magic >> 8) & 0xFF) || + pt[2] != ((pyc_magic >> 16) & 0xFF) || + pt[3] != ((pyc_magic >> 24) & 0xFF)) { /* Bad magic number */ + strncpy(source, pathname, MAXPATHLEN); + source[strlen(source) - 1] = 0; /* try source file X.py */ + if (PyDict_GetItemString(ExternalNames, source)) { + if (Py_VerboseFlag) + PySys_WriteStderr( + "Zip import: Bad magic number in %.200s; try source X.py\n", + pathname); + Py_DECREF(pyStr); + return load_zip_source_module(name, source); + } + PyErr_Format(PyExc_ImportError, + "Bad magic number in %.200s", pathname); + Py_DECREF(pyStr); + return NULL; + } + code = PyMarshal_ReadObjectFromString(pt + 8, size - 8); + if (!code || !PyCode_Check(code)) { + Py_XDECREF(code); + PyErr_Format(PyExc_TypeError, + "zip compiled file %.200s is not a code object", + name); + Py_DECREF(pyStr); + return NULL; + } + m = PyImport_ExecCodeModuleEx(name, code, pathname); + Py_DECREF(code); + Py_DECREF(pyStr); + if (Py_VerboseFlag) + PySys_WriteStderr("import %s # precompiled from zip %s\n", + name, pathname); + return m; + } + /* Helper for sys */ PyObject * *************** *** 836,859 **** } - /* Helper to test for built-in module */ - - static int - is_builtin(char *name) - { - int i; - for (i = 0; PyImport_Inittab[i].name != NULL; i++) { - if (strcmp(name, PyImport_Inittab[i].name) == 0) { - if (PyImport_Inittab[i].initfunc == NULL) - return -1; - else - return 1; - } - } - return 0; - } - - /* Search the path (default sys.path) for a module. Return the corresponding filedescr struct, and (via return arguments) the pathname and an open file. Return NULL if the module is not found. */ --- 1411,1416 ---- *************** *** 870,885 **** find_module(char *realname, PyObject *path, char *buf, size_t buflen, FILE **p_fp) { ! int i, npath; size_t len, namelen; struct filedescr *fdp = NULL; FILE *fp = NULL; - #ifndef RISCOS - struct stat statbuf; - #endif - static struct filedescr fd_frozen = {"", "", PY_FROZEN}; - static struct filedescr fd_builtin = {"", "", C_BUILTIN}; - static struct filedescr fd_package = {"", "", PKG_DIRECTORY}; char name[MAXPATHLEN+1]; if (strlen(realname) > MAXPATHLEN) { --- 1427,1437 ---- find_module(char *realname, PyObject *path, char *buf, size_t buflen, FILE **p_fp) { ! int i, npath, path_type; size_t len, namelen; struct filedescr *fdp = NULL; + struct stZipSearchOrder *zso; FILE *fp = NULL; char name[MAXPATHLEN+1]; if (strlen(realname) > MAXPATHLEN) { *************** *** 918,928 **** #endif } if (path == NULL) { ! if (is_builtin(name)) { strcpy(buf, name); return &fd_builtin; ! } ! if ((find_frozen(name)) != NULL) { strcpy(buf, name); return &fd_frozen; } --- 1470,1480 ---- #endif } if (path == NULL) { ! switch(get_path_type(InternalNames, name)) { ! case PY_IMP_BUILTIN: strcpy(buf, name); return &fd_builtin; ! case PY_IMP_FROZEN: strcpy(buf, name); return &fd_frozen; } *************** *** 943,948 **** --- 1495,1501 ---- } npath = PyList_Size(path); namelen = strlen(name); + *p_fp = NULL; for (i = 0; i < npath; i++) { PyObject *v = PyList_GetItem(path, i); if (!PyString_Check(v)) *************** *** 953,958 **** --- 1506,1531 ---- strcpy(buf, PyString_AsString(v)); if (strlen(buf) != len) continue; /* v contains '\0' */ + path_type = get_path_type(ExternalNames, buf); + if (path_type == PY_IMP_NO_VALUE || path_type == PY_IMP_FILE) { + /* Zip imports may fail for relative paths */ + if (add_zip_names(buf)) { + path_type = PY_IMP_ZIP; + } + else if (use_os_listdir < 0 || relative_path(buf)) { + /* Do not cache directories for relative paths */ + PyObject *vv; + vv = PyInt_FromLong(PY_IMP_NO_LISTDIR); + PyDict_SetItemString(ExternalNames, buf, vv); + Py_DECREF(vv); + path_type = PY_IMP_NO_LISTDIR; + } + else if (use_os_listdir > 0) { + add_directory_names(buf); + path_type = PY_IMP_LISTDIR; + } + /* use_os_listdir == 0: We are starting up. */ + } #ifdef macintosh #ifdef INTERN_STRINGS /* *************** *** 977,982 **** --- 1550,1557 ---- return &resfiledescr; } #endif + + /* join the module name to the path item */ if (len > 0 && buf[len-1] != SEP #ifdef ALTSEP && buf[len-1] != ALTSEP *************** *** 986,1037 **** strcpy(buf+len, name); len += namelen; ! /* 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 */ ! find_init_module(buf) && /* it has __init__.py */ ! case_ok(buf, len, namelen, name)) /* and case matches */ ! return &fd_package; #else ! /* XXX How are you going to test for directories? */ #ifdef RISCOS ! if (isdir(buf) && ! find_init_module(buf) && ! case_ok(buf, len, namelen, name)) ! return &fd_package; #endif #endif #ifdef macintosh ! fdp = PyMac_FindModuleExtension(buf, &len, name); ! if (fdp) { #else ! for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { ! strcpy(buf+len, fdp->suffix); ! if (Py_VerboseFlag > 1) ! PySys_WriteStderr("# trying %s\n", buf); #endif /* !macintosh */ ! fp = fopen(buf, fdp->mode); ! if (fp != NULL) { ! if (case_ok(buf, len, namelen, name)) ! break; ! else { /* continue search */ ! fclose(fp); ! fp = NULL; ! } } } - if (fp != NULL) - break; } ! if (fp == NULL) { ! PyErr_Format(PyExc_ImportError, ! "No module named %.200s", name); ! return NULL; ! } ! *p_fp = fp; ! return fdp; } /* case_ok(char* buf, int len, int namelen, char* name) --- 1561,1680 ---- strcpy(buf+len, name); len += namelen; ! switch(path_type) { /* Search according to path type */ ! case PY_IMP_ZIP: /* Path includes ".zip/" */ ! #ifdef ALTSEP ! { ! size_t j; ! /* Use only SEP in zip names, never ALTSEP */ ! for (j = 0; j < len; j++) ! if (buf[j] == ALTSEP) ! buf[j] = SEP; ! } ! #endif ! for (zso = ZipSearchOrder; zso->type; zso++) { ! strcpy(buf+len, zso->suffix); ! if (Py_VerboseFlag > 1) ! PySys_WriteStderr("# trying %s\n", buf); ! if (PyDict_GetItemString(ExternalNames, buf)) { ! if (zso->type == PKG_DIRECTORY) { ! buf[len] = 0; ! return &fd_package; ! } ! return &fd_zip; ! } ! } ! break; ! case PY_IMP_LISTDIR: /* We have read the directory names */ ! if (PyDict_GetItemString(ExternalNames, buf)) { ! /* Check for package directory */ ! add_directory_names(buf); ! buf[len] = SEP; ! strcpy(buf+len+1, "__init__.py"); ! if (get_path_type(ExternalNames, buf)) { ! buf[len] = 0; ! return &fd_package; ! } ! if (Py_OptimizeFlag) /* Add 'o' or 'c' */ ! buf[len+12] = 'o'; ! else ! buf[len+12] = 'c'; ! buf[len+13] = 0; ! if (get_path_type(ExternalNames, buf)) { ! buf[len] = 0; ! return &fd_package; ! } ! } ! /* Search the list of suffixes: .pyc, .pyd, ... */ ! for (fdp = _PyImport_Filetab; fdp->suffix; fdp++) { ! strcpy(buf+len, fdp->suffix); ! if (Py_VerboseFlag > 1) ! PySys_WriteStderr("# trying %s\n", buf); ! if (get_path_type(ExternalNames, buf) && ! (fp = fopen(buf, fdp->mode)) != NULL) { ! *p_fp = fp; ! return fdp; ! } ! } ! break; ! default: /* Not zip, no names: search using fopen() */ ! fdp = search_using_fopen(name, buf, len, namelen, p_fp); ! if (fdp) ! return fdp; ! break; ! } /* End of switch on path type */ ! } /* End of loop on path items */ ! PyErr_Format(PyExc_ImportError, ! "No module named %.200s", name); ! return NULL; ! } ! ! static struct filedescr * ! search_using_fopen(char *name, char *buf, size_t len, size_t namelen, FILE **p_fp) ! { ! struct filedescr *fdp; ! FILE *fp; ! ! /* Check for package import (buf holds a directory name, ! and there's an __init__ module in that directory */ #ifdef HAVE_STAT ! struct stat statbuf; ! if (stat(buf, &statbuf) == 0 && /* it exists */ ! S_ISDIR(statbuf.st_mode) && /* it's a directory */ ! find_init_module(buf) && /* it has __init__.py */ ! case_ok(buf, len, namelen, name)) /* and case matches */ ! return &fd_package; #else ! /* XXX How are you going to test for directories? */ #ifdef RISCOS ! if (isdir(buf) && ! find_init_module(buf) && ! case_ok(buf, len, namelen, name)) ! return &fd_package; #endif #endif #ifdef macintosh ! fdp = PyMac_FindModuleExtension(buf, &len, name); ! if (fdp) { #else ! for (fdp = _PyImport_Filetab; fdp->suffix != NULL; fdp++) { ! strcpy(buf+len, fdp->suffix); ! if (Py_VerboseFlag > 1) ! PySys_WriteStderr("# trying %s\n", buf); #endif /* !macintosh */ ! fp = fopen(buf, fdp->mode); ! if (fp != NULL) { ! if (case_ok(buf, len, namelen, name)) { ! *p_fp = fp; ! return fdp; ! } ! else { /* continue search */ ! fclose(fp); ! fp = NULL; } } } ! return NULL; } /* case_ok(char* buf, int len, int namelen, char* name) *************** *** 1411,1416 **** --- 2054,2063 ---- Py_INCREF(m); break; + case PY_ZIPFILE: + m = load_zip_module(name, buf); + break; + default: PyErr_Format(PyExc_ImportError, "Don't know how to import %.200s (type code %d)", *************** *** 2202,2208 **** char *name; if (!PyArg_ParseTuple(args, "s:is_builtin", &name)) return NULL; ! return PyInt_FromLong(is_builtin(name)); } static PyObject * --- 2849,2855 ---- char *name; if (!PyArg_ParseTuple(args, "s:is_builtin", &name)) return NULL; ! return PyInt_FromLong(get_path_type(InternalNames, name) == PY_IMP_BUILTIN); } static PyObject * *************** *** 2466,2471 **** --- 3113,3119 ---- if (setint(d, "C_BUILTIN", C_BUILTIN) < 0) goto failure; if (setint(d, "PY_FROZEN", PY_FROZEN) < 0) goto failure; if (setint(d, "PY_CODERESOURCE", PY_CODERESOURCE) < 0) goto failure; + if (setint(d, "PY_ZIPFILE", PY_ZIPFILE) < 0) goto failure; failure: ; *************** *** 2506,2511 **** --- 3154,3160 ---- PyImport_Inittab = our_copy = p; memcpy(p+i, newtab, (n+1) * sizeof(struct _inittab)); + get_internal_names(); return 0; }