? python/dist/src/Python/.import.c.swp Index: python/dist/src/Include/import.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/import.h,v retrieving revision 2.27 diff -c -r2.27 import.h *** python/dist/src/Include/import.h 1 Sep 2000 23:29:26 -0000 2.27 --- python/dist/src/Include/import.h 15 Mar 2002 17:21:27 -0000 *************** *** 20,25 **** --- 20,26 ---- PyAPI_FUNC(PyObject *) PyImport_ReloadModule(PyObject *m); PyAPI_FUNC(void) PyImport_Cleanup(void); PyAPI_FUNC(int) PyImport_ImportFrozenModule(char *); + PyAPI_FUNC(void) PyImport_InitZip(void); extern PyAPI_FUNC(PyObject *)_PyImport_FindExtension(char *, char *); extern PyAPI_FUNC(PyObject *)_PyImport_FixupExtension(char *, char *); Index: python/dist/src/Include/pythonrun.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Include/pythonrun.h,v retrieving revision 2.48 diff -c -r2.48 pythonrun.h *** python/dist/src/Include/pythonrun.h 31 Aug 2001 17:40:14 -0000 2.48 --- python/dist/src/Include/pythonrun.h 15 Mar 2002 17:21:27 -0000 *************** *** 17,22 **** --- 17,25 ---- PyAPI_FUNC(void) Py_SetProgramName(char *); PyAPI_FUNC(char *) Py_GetProgramName(void); + PyAPI_FUNC(void) Py_SetScriptName(char *); + PyAPI_FUNC(char *) Py_GetScriptName(void); + PyAPI_FUNC(void) Py_SetPythonHome(char *); PyAPI_FUNC(char *) Py_GetPythonHome(void); Index: python/dist/src/Lib/site.py =================================================================== RCS file: /cvsroot/python/python/dist/src/Lib/site.py,v retrieving revision 1.41 diff -c -r1.41 site.py *** python/dist/src/Lib/site.py 24 Feb 2002 05:32:32 -0000 1.41 --- python/dist/src/Lib/site.py 15 Mar 2002 17:21:28 -0000 *************** *** 75,89 **** _dirs_in_sys_path = {} for dir in sys.path: # Filter out paths that don't exist, but leave in the empty string ! # since it's a special case. We also need to special-case the Mac, ! # as file names are allowed on sys.path there. ! if sys.platform != 'mac': ! if dir and not os.path.isdir(dir): continue ! else: ! if dir and not os.path.exists(dir): ! continue ! dir, dircase = makepath(dir) if not dircase in _dirs_in_sys_path: L.append(dir) _dirs_in_sys_path[dircase] = 1 --- 75,88 ---- _dirs_in_sys_path = {} for dir in sys.path: # Filter out paths that don't exist, but leave in the empty string ! # since it's a special case. For the Mac, file names are allowed ! # in sys.path. For all platforms, zip archive file names are allowed. ! if dir: ! if not os.path.exists(dir): continue ! dir, dircase = makepath(dir) ! else: # Preserve "" in sys.path ! dircase = "" if not dircase in _dirs_in_sys_path: L.append(dir) _dirs_in_sys_path[dircase] = 1 Index: python/dist/src/Modules/getpath.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/getpath.c,v retrieving revision 1.41 diff -c -r1.41 getpath.c *** python/dist/src/Modules/getpath.c 12 Jan 2002 11:05:06 -0000 1.41 --- python/dist/src/Modules/getpath.c 15 Mar 2002 17:21:30 -0000 *************** *** 76,87 **** * * That's it! * ! * Well, almost. Once we have determined prefix and exec_prefix, the ! * preprocessor variable PYTHONPATH is used to construct a path. Each ! * relative path on PYTHONPATH is prefixed with prefix. Then the directory ! * containing the shared library modules is appended. The environment ! * variable $PYTHONPATH is inserted in front of it all. Finally, the ! * prefix and exec_prefix globals are tweaked so they reflect the values * expected by other code, by stripping the "lib/python$VERSION/..." stuff * off. If either points to the build directory, the globals are reset to * the corresponding preprocessor variables (so sys.prefix will reflect the --- 76,89 ---- * * That's it! * ! * Well, almost. Once we have determined prefix and exec_prefix, we ! * can construct the module_search_path that is returned by Py_GetPath(). ! * The first item is the environment variable $PYTHONPATH. Next is the ! * directory of the Python script being run, or "", or perhaps nothing. ! * Next is the zip file name. Next we add each item of the preprocessor ! * variable PYTHONPATH, prepending each relative path with prefix. Then ! * the directory containing the shared library modules is added. Finally, ! * the prefix and exec_prefix globals are tweaked so they reflect the values * expected by other code, by stripping the "lib/python$VERSION/..." stuff * off. If either points to the build directory, the globals are reset to * the corresponding preprocessor variables (so sys.prefix will reflect the *************** *** 347,358 **** return 0; } static void calculate_path(void) { - extern char *Py_GetProgramName(void); - static char delimiter[2] = {DELIM, '\0'}; static char separator[2] = {SEP, '\0'}; char *pythonpath = PYTHONPATH; --- 349,427 ---- return 0; } + /* + * Calculate item 0 of sys.path from the Python script name. + * If the script name is NULL, do not insert an item 0. + * The special name "" means item 0 is "". + * For a real script name, try to generate an absolute path. + */ + static int + get_sys_path_0(char *path) + { /* Return TRUE iff path has been set. Size of path must be MAXPATHLEN+1 */ + char *argv0 = Py_GetScriptName(); + char *p = NULL; + #ifdef HAVE_READLINK + char link[MAXPATHLEN+1]; + char argv0copy[2*MAXPATHLEN+1]; + int nr = 0; + #endif + + path[0] = 0; + if (argv0 == NULL) /* No sys.path[0] insertion */ + return 0; + + if (!argv0[0]) /* Insert "" as sys.path[0] */ + return 1; + + #ifdef HAVE_READLINK + nr = readlink(argv0, link, MAXPATHLEN); + if (nr > 0) { + /* It's a symlink */ + link[nr] = '\0'; + if (link[0] == SEP) + argv0 = link; /* Link to absolute path */ + else if (strchr(link, SEP) == NULL) + ; /* Link without path */ + else { + /* Must join(dirname(argv0), link) */ + char *q = strrchr(argv0, SEP); + if (q == NULL) + argv0 = link; /* argv0 without path */ + else { + /* Must make a copy */ + strcpy(argv0copy, argv0); + q = strrchr(argv0copy, SEP); + strcpy(q+1, link); + argv0 = argv0copy; + } + } + } + #endif /* HAVE_READLINK */ + + strncpy(path, argv0, MAXPATHLEN); + p = strrchr(path, SEP); + if (p == NULL) { /* No separator at all */ + path[0] = 0; + getcwd(path, MAXPATHLEN); + } + else if (p == path) { /* A single initial separator */ + path[0] = SEP; + path[1] = 0; + } + else { /* Last separator occurs within the name */ + #ifdef macintosh + *(p + 1) = 0; /* Keep trailing separator */ + #else + *p = 0; /* Remove trailing separator */ + #endif + absolutize(path); + } + return 1; + } static void calculate_path(void) { static char delimiter[2] = {DELIM, '\0'}; static char separator[2] = {SEP, '\0'}; char *pythonpath = PYTHONPATH; *************** *** 361,366 **** --- 430,438 ---- char *path = getenv("PATH"); char *prog = Py_GetProgramName(); char argv0_path[MAXPATHLEN+1]; + char zip_path[MAXPATHLEN+1]; + char syspath0[MAXPATHLEN+1]; + int have_syspath0; int pfound, efound; /* 1 if found; -1 if found build directory */ char *buf; size_t bufsz; *************** *** 478,483 **** --- 550,567 ---- else reduce(prefix); + strncpy(zip_path, prefix, MAXPATHLEN); + if (pfound > 0) { /* Use the reduced prefix returned by Py_GetPrefix() */ + reduce(zip_path); + reduce(zip_path); + } + else + strncpy(zip_path, PREFIX, MAXPATHLEN); + joinpath(zip_path, "lib/python00.zip"); + bufsz = strlen(zip_path); /* Replace "00" with version */ + zip_path[bufsz - 6] = VERSION[0]; + zip_path[bufsz - 5] = VERSION[2]; + if (!(efound = search_for_exec_prefix(argv0_path, home))) { if (!Py_FrozenFlag) fprintf(stderr, *************** *** 495,500 **** --- 579,588 ---- */ bufsz = 0; + have_syspath0 = get_sys_path_0(syspath0); + if (have_syspath0) + bufsz += strlen(syspath0) + 1; + if (rtpypath) bufsz += strlen(rtpypath) + 1; *************** *** 516,521 **** --- 604,610 ---- defpath = delim + 1; } + bufsz += strlen(zip_path) + 1; bufsz += strlen(exec_prefix) + 1; /* This is the only malloc call in this file */ *************** *** 535,540 **** --- 624,639 ---- } else buf[0] = '\0'; + + /* Next is syspath0 calculated from the script name */ + if (have_syspath0) { + strcat(buf, syspath0); + strcat(buf, delimiter); + } + + /* Next is the default zip path */ + strcat(buf, zip_path); + strcat(buf, delimiter); /* Next goes merge of compile-time $PYTHONPATH with * dynamically located prefix. Index: python/dist/src/Modules/main.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Modules/main.c,v retrieving revision 1.64 diff -c -r1.64 main.c *** python/dist/src/Modules/main.c 3 Mar 2002 02:59:16 -0000 1.64 --- python/dist/src/Modules/main.c 15 Mar 2002 17:21:30 -0000 *************** *** 122,127 **** --- 122,128 ---- int saw_inspect_flag = 0; int saw_unbuffered_flag = 0; PyCompilerFlags cf; + static char *ZLSTRING = ""; cf.cf_flags = 0; *************** *** 322,328 **** /* Leave stderr alone - it should be unbuffered anyway. */ } ! Py_SetProgramName(argv[0]); Py_Initialize(); if (Py_VerboseFlag || --- 323,333 ---- /* Leave stderr alone - it should be unbuffered anyway. */ } ! Py_SetProgramName(argv[0]); /* For use by Py_GetPath() */ ! if (filename) ! Py_SetScriptName(filename); /* For use by Py_GetPath() */ ! else ! Py_SetScriptName(ZLSTRING); /* Add "" to sys.path */ Py_Initialize(); if (Py_VerboseFlag || Index: python/dist/src/PC/getpathp.c =================================================================== RCS file: /cvsroot/python/python/dist/src/PC/getpathp.c,v retrieving revision 1.26 diff -c -r1.26 getpathp.c *** python/dist/src/PC/getpathp.c 12 Jan 2002 11:05:09 -0000 1.26 --- python/dist/src/PC/getpathp.c 15 Mar 2002 17:21:30 -0000 *************** *** 8,17 **** functionality, not the implementation (ie, the order in which these are actually fetched is different) ! * Python always adds an empty entry at the start, which corresponds ! to the current directory. ! * If the PYTHONPATH env. var. exists, it's entries are added next. * We look in the registry for "application paths" - that is, sub-keys under the main PythonPath registry key. These are added next (the --- 8,20 ---- functionality, not the implementation (ie, the order in which these are actually fetched is different) ! * If the PYTHONPATH env. var. exists, it's entries are added first. ! * The absolute path of the Python script; or the string "" for ! the "-c" option or an interactive interpreter. There is also ! an option to suppress this entry. ! ! * The default zip archive path. * We look in the registry for "application paths" - that is, sub-keys under the main PythonPath registry key. These are added next (the *************** *** 60,65 **** --- 63,69 ---- #ifdef MS_WIN32 #include #include + #include #endif #include *************** *** 81,86 **** --- 85,91 ---- static char prefix[MAXPATHLEN+1]; static char progpath[MAXPATHLEN+1]; + static char dllpath[MAXPATHLEN+1]; static char *module_search_path = NULL; *************** *** 350,355 **** --- 355,361 ---- char *prog = Py_GetProgramName(); #ifdef MS_WINDOWS + extern HANDLE PyWin_DLLhModule; #ifdef UNICODE WCHAR wprogpath[MAXPATHLEN+1]; /* Windows documents that GetModuleFileName() will "truncate", *************** *** 357,362 **** --- 363,376 ---- PLUS Windows itself defines MAX_PATH as the same, but anyway... */ wprogpath[MAXPATHLEN]=_T('\0'); + if (PyWin_DLLhModule && + GetModuleFileName(PyWin_DLLhModule, wprogpath, MAXPATHLEN)) { + WideCharToMultiByte(CP_ACP, 0, + wprogpath, -1, + dllpath, MAXPATHLEN+1, + NULL, NULL); + } + wprogpath[MAXPATHLEN]=_T('\0')'; if (GetModuleFileName(NULL, wprogpath, MAXPATHLEN)) { WideCharToMultiByte(CP_ACP, 0, wprogpath, -1, *************** *** 366,371 **** --- 380,388 ---- } #else /* static init of progpath ensures final char remains \0 */ + if (PyWin_DLLhModule) + if (!GetModuleFileName(PyWin_DLLhModule, dllpath, MAXPATHLEN)) + dllpath[0] = 0; if (GetModuleFileName(NULL, progpath, MAXPATHLEN)) return; #endif *************** *** 414,423 **** --- 431,548 ---- progpath[0] = '\0'; } + /* + * Calculate item 0 of sys.path from the Python script name. + * If the script name is NULL, do not insert an item 0. + * The special name "" means item 0 is "". + * For a real script name, try to generate an absolute path. + */ + static int + get_sys_path_0(char *path) + { /* Return TRUE iff path has been set. Size of path must be MAXPATHLEN+1 */ + char *argv0 = Py_GetScriptName(); + char *p = NULL; + #ifdef MS_WINDOWS + char dir[MAXPATHLEN+1]; + int drive; + size_t i, len; + #else + char *q; + int n = 0; + #endif + + path[0] = 0; + if (argv0 == NULL) /* No sys.path[0] insertion */ + return 0; + + if (!argv0[0]) /* Insert "" as sys.path[0] */ + return 1; + + #ifdef MS_WINDOWS + len = strlen(argv0); + if (len > 1 && argv0[1] == ':') { /* We have a drive letter */ + drive = toupper(argv0[0]) - 64; /* A=1, B=2, ... */ + strncpy(dir, argv0 + 2, MAXPATHLEN); + len -= 2; + } + else { /* Get drive letter */ + drive = _getdrive(); + strncpy(dir, argv0, MAXPATHLEN); + } + for (i=0; i < len; i++) /* Replace ALTSEP with SEP */ + if (dir[i] == ALTSEP) + dir[i] = SEP; + p = strrchr(dir, SEP); + if (p == NULL) { /* No separator at all */ + path[0] = 0; + _getdcwd(drive, path, MAXPATHLEN); + return 1; + } + if (p == dir) { /* A single initial separator */ + path[0] = 'A' + drive - 1; + path[1] = ':'; + path[2] = SEP; + path[3] = 0; + return 1; + } + /* Last separator occurs within the name */ + *p = 0; /* Remove trailing separator */ + if (dir[0] == SEP) { /* Absolute path was given */ + path[0] = 'A' + drive - 1; + path[1] = ':'; + path[2] = 0; + strncat(path, dir, MAXPATHLEN); + } + else if (_getdcwd(drive, path, MAXPATHLEN - 2)) { + len = strlen(path); + path[len] = SEP; + path[len + 1] = 0; + strncat(path, dir, MAXPATHLEN); + } + else { /* _getdcwd() failed */ + path[0] = 'A' + drive - 1; + path[1] = ':'; + path[2] = 0; + strncat(path, dir, MAXPATHLEN); + } + #else + /* getdrive(), getdcwd() are not available */ + /* When is this ever used?? */ + p = strrchr(argv0, SEP); + #ifdef ALTSEP + /* Test for alternate separator */ + q = strrchr(p ? p : argv0, ALTSEP); + if (q != NULL) + p = q; + #endif + if (p == NULL) { /* No separator at all */ + if (argv0[1] != ':') { /* No drive letter */ + path[0] = '.'; + path[1] = 0; + return 1; + } + } + else { + n = p + 1 - argv0; + if (n > 1 && p[-1] != ':') + n--; /* Drop trailing separator */ + } + if (n <= 0) + path[0] = 0; + else if (n < MAXPATHLEN) + strncpy(path, argv0, n); + else + strncpy(path, argv0, MAXPATHLEN); + #endif + return 1; + } + static void calculate_path(void) { char argv0_path[MAXPATHLEN+1]; + char syspath0[MAXPATHLEN+1]; + int have_syspath0; char *buf; size_t bufsz; char *pythonhome = Py_GetPythonHome(); *************** *** 427,432 **** --- 552,559 ---- int skiphome, skipdefault; char *machinepath = NULL; char *userpath = NULL; + char zip_path[MAXPATHLEN+1]; + size_t len; #endif get_progpath(); *************** *** 445,450 **** --- 572,593 ---- if (envpath && *envpath == '\0') envpath = NULL; + #ifdef MS_WINDOWS + /* Calculate zip archive path */ + if (dllpath[0]) /* use name of python DLL */ + strncpy(zip_path, dllpath, MAXPATHLEN); + else /* use name of executable program */ + strncpy(zip_path, progpath, MAXPATHLEN); + len = strlen(zip_path); + if (len > 4) { + zip_path[len-3] = 'z'; /* change ending to "zip" */ + zip_path[len-2] = 'i'; + zip_path[len-1] = 'p'; + } + else { + zip_path[0] = 0; + } + #endif #ifdef MS_WINDOWS skiphome = pythonhome==NULL ? 0 : 1; *************** *** 458,471 **** /* We need to construct a path from the following parts. (1) the PYTHONPATH environment variable, if set; ! (2) for Win32, the machinepath and userpath, if set; ! (3) the PYTHONPATH config macro, with the leading "." of each component replaced with pythonhome, if set; ! (4) the directory containing the executable (argv0_path). The length calculation calculates #3 first. Extra rules: ! - If PYTHONHOME is set (in any way) item (2) is ignored. ! - If registry values are used, (3) and (4) are ignored. */ /* Calculate size of return buffer */ --- 601,616 ---- /* We need to construct a path from the following parts. (1) the PYTHONPATH environment variable, if set; ! (2) the absolute path of the script file, or "", or nothing; ! (3) for Win32, the zip archive file path; ! (4) for Win32, the machinepath and userpath, if set; ! (5) the PYTHONPATH config macro, with the leading "." of each component replaced with pythonhome, if set; ! (6) the directory containing the executable (argv0_path). The length calculation calculates #3 first. Extra rules: ! - If PYTHONHOME is set (in any way) item (4) is ignored. ! - If registry values are used, (5) and (6) are ignored. */ /* Calculate size of return buffer */ *************** *** 480,485 **** --- 625,633 ---- } else bufsz = 0; + have_syspath0 = get_sys_path_0(syspath0); + if (have_syspath0) + bufsz += strlen(syspath0) + 1; bufsz += strlen(PYTHONPATH) + 1; bufsz += strlen(argv0_path) + 1; #ifdef MS_WINDOWS *************** *** 487,492 **** --- 635,641 ---- bufsz += strlen(userpath) + 1; if (machinepath) bufsz += strlen(machinepath) + 1; + bufsz += strlen(zip_path) + 1; #endif if (envpath != NULL) bufsz += strlen(envpath) + 1; *************** *** 517,523 **** --- 666,683 ---- buf = strchr(buf, '\0'); *buf++ = DELIM; } + + if (have_syspath0) { + strcpy(buf, syspath0); + buf = strchr(buf, '\0'); + *buf++ = DELIM; + } #ifdef MS_WINDOWS + if (zip_path[0]) { + strcpy(buf, zip_path); + buf = strchr(buf, '\0'); + *buf++ = DELIM; + } if (userpath) { strcpy(buf, userpath); buf = strchr(buf, '\0'); *************** *** 640,642 **** --- 800,804 ---- calculate_path(); return progpath; } + + /* Could add char * Py_GetDllFullPath(void) to return dllpath here. */ Index: python/dist/src/Python/import.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/import.c,v retrieving revision 2.195 diff -c -r2.195 import.c *** python/dist/src/Python/import.c 26 Feb 2002 11:41:34 -0000 2.195 --- python/dist/src/Python/import.c 15 Mar 2002 17:21:31 -0000 *************** *** 79,84 **** --- 79,148 ---- /* 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}, *************** *** 141,146 **** --- 205,232 ---- 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 *************** *** 150,155 **** --- 236,245 ---- extensions = NULL; PyMem_DEL(_PyImport_Filetab); _PyImport_Filetab = NULL; + Py_XDECREF(ExternalNames); + ExternalNames = NULL; + Py_XDECREF(InternalNames); + InternalNames = NULL; } *************** *** 220,225 **** --- 310,800 ---- #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 * *************** *** 855,878 **** } - /* 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. */ --- 1430,1435 ---- *************** *** 889,911 **** 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; char *filemode; 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 defined(PYOS_OS2) - size_t saved_len; - size_t saved_namelen; - char *saved_buf = NULL; - #endif if (strlen(realname) > MAXPATHLEN) { PyErr_SetString(PyExc_OverflowError, --- 1446,1458 ---- 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; char *filemode; + struct stZipSearchOrder *zso; FILE *fp = NULL; char name[MAXPATHLEN+1]; if (strlen(realname) > MAXPATHLEN) { PyErr_SetString(PyExc_OverflowError, *************** *** 942,955 **** #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; ! } #ifdef MS_COREDLL fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen); --- 1489,1502 ---- #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; ! } #ifdef MS_COREDLL fp = PyWin_FindRegisteredModule(name, &fdp, buf, buflen); *************** *** 967,972 **** --- 1514,1520 ---- } 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)) *************** *** 977,984 **** --- 1525,1552 ---- strcpy(buf, PyString_AsString(v)); if (strlen(buf) != len) { Py_XDECREF(copy); 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 /* ** Speedup: each sys.path item is interned, and *************** *** 1001,1006 **** --- 1569,1576 ---- return &resfiledescr; } #endif + + /* join the module name to the path item */ if (len > 0 && buf[len-1] != SEP #ifdef ALTSEP && buf[len-1] != ALTSEP *************** *** 1010,1106 **** 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 #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) ! /* 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(realname) > 8) { ! /* is this an attempt to load a C extension? */ ! const struct filedescr *scan = _PyImport_DynLoadFiletab; ! while (scan->suffix != NULL) { ! if (strcmp(scan->suffix, fdp->suffix) == 0) ! break; ! else ! scan++; ! } ! if (scan->suffix != NULL) { ! /* yes, so truncate the name */ ! namelen = 8; ! len -= strlen(realname) - namelen; ! buf[len] = '\0'; ! } } #endif /* PYOS_OS2 */ ! 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 defined(PYOS_OS2) ! /* restore the saved snapshot */ ! strcpy(buf, saved_buf); ! len = saved_len; ! namelen = saved_namelen; ! #endif } #if defined(PYOS_OS2) ! /* don't need/want the module name snapshot anymore */ ! if (saved_buf) ! { ! free(saved_buf); ! saved_buf = NULL; ! } #endif - 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) --- 1580,1749 ---- 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; ! #if defined(PYOS_OS2) ! size_t saved_len; ! size_t saved_namelen; ! char *saved_buf = NULL; ! #endif ! ! /* 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 #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) ! /* 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(realname) > 8) { ! /* is this an attempt to load a C extension? */ ! const struct filedescr *scan = _PyImport_DynLoadFiletab; ! while (scan->suffix != NULL) { ! if (strcmp(scan->suffix, fdp->suffix) == 0) ! break; ! else ! scan++; ! } ! if (scan->suffix != NULL) { ! /* yes, so truncate the name */ ! namelen = 8; ! len -= strlen(realname) - namelen; ! buf[len] = '\0'; } + } #endif /* PYOS_OS2 */ ! 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; ! } } #if defined(PYOS_OS2) ! /* restore the saved snapshot */ ! strcpy(buf, saved_buf); ! len = saved_len; ! namelen = saved_namelen; #endif } ! #if defined(PYOS_OS2) ! /* don't need/want the module name snapshot anymore */ ! if (saved_buf) ! { ! free(saved_buf); ! saved_buf = NULL; } ! #endif ! return NULL; } /* case_ok(char* buf, int len, int namelen, char* name) *************** *** 1506,1511 **** --- 2149,2158 ---- 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)", *************** *** 2297,2303 **** char *name; if (!PyArg_ParseTuple(args, "s:is_builtin", &name)) return NULL; ! return PyInt_FromLong(is_builtin(name)); } static PyObject * --- 2944,2950 ---- 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 * *************** *** 2561,2566 **** --- 3208,3214 ---- 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: ; *************** *** 2601,2606 **** --- 3249,3255 ---- PyImport_Inittab = our_copy = p; memcpy(p+i, newtab, (n+1) * sizeof(struct _inittab)); + get_internal_names(); return 0; } Index: python/dist/src/Python/importdl.h =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/importdl.h,v retrieving revision 2.18 diff -c -r2.18 importdl.h *** python/dist/src/Python/importdl.h 26 Feb 2002 11:41:34 -0000 2.18 --- python/dist/src/Python/importdl.h 15 Mar 2002 17:21:31 -0000 *************** *** 16,22 **** PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, ! PY_CODERESOURCE /* Mac only */ }; struct filedescr { --- 16,23 ---- PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, ! PY_CODERESOURCE, /* Mac only */ ! PY_ZIPFILE }; struct filedescr { Index: python/dist/src/Python/pythonrun.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/pythonrun.c,v retrieving revision 2.155 diff -c -r2.155 pythonrun.c *** python/dist/src/Python/pythonrun.c 3 Mar 2002 21:30:27 -0000 2.155 --- python/dist/src/Python/pythonrun.c 15 Mar 2002 17:21:31 -0000 *************** *** 169,174 **** --- 169,175 ---- initsigs(); /* Signal handling stuff, including initintr() */ initmain(); /* Module __main__ */ + PyImport_InitZip(); if (!Py_NoSiteFlag) initsite(); /* Module site */ } *************** *** 335,340 **** --- 336,342 ---- PyDict_SetItemString(interp->sysdict, "modules", interp->modules); initmain(); + PyImport_InitZip(); if (!Py_NoSiteFlag) initsite(); } *************** *** 396,401 **** --- 398,417 ---- Py_GetProgramName(void) { return progname; + } + + static char *scriptname = NULL; + + void + Py_SetScriptName(char *pn) + { + scriptname = pn; + } + + char * + Py_GetScriptName(void) + { + return scriptname; } static char *default_home = NULL; Index: python/dist/src/Python/sysmodule.c =================================================================== RCS file: /cvsroot/python/python/dist/src/Python/sysmodule.c,v retrieving revision 2.101 diff -c -r2.101 sysmodule.c *** python/dist/src/Python/sysmodule.c 3 Mar 2002 15:11:17 -0000 2.101 --- python/dist/src/Python/sysmodule.c 15 Mar 2002 17:21:31 -0000 *************** *** 905,984 **** PySys_SetArgv(int argc, char **argv) { PyObject *av = makeargvobject(argc, argv); - PyObject *path = PySys_GetObject("path"); if (av == NULL) Py_FatalError("no mem for sys.argv"); if (PySys_SetObject("argv", av) != 0) Py_FatalError("can't assign sys.argv"); - if (path != NULL) { - char *argv0 = argv[0]; - char *p = NULL; - int n = 0; - PyObject *a; - #ifdef HAVE_READLINK - char link[MAXPATHLEN+1]; - char argv0copy[2*MAXPATHLEN+1]; - int nr = 0; - if (argc > 0 && argv0 != NULL) - nr = readlink(argv0, link, MAXPATHLEN); - if (nr > 0) { - /* It's a symlink */ - link[nr] = '\0'; - if (link[0] == SEP) - argv0 = link; /* Link to absolute path */ - else if (strchr(link, SEP) == NULL) - ; /* Link without path */ - else { - /* Must join(dirname(argv0), link) */ - char *q = strrchr(argv0, SEP); - if (q == NULL) - argv0 = link; /* argv0 without path */ - else { - /* Must make a copy */ - strcpy(argv0copy, argv0); - q = strrchr(argv0copy, SEP); - strcpy(q+1, link); - argv0 = argv0copy; - } - } - } - #endif /* HAVE_READLINK */ - #if SEP == '\\' /* Special case for MS filename syntax */ - if (argc > 0 && argv0 != NULL) { - char *q; - p = strrchr(argv0, SEP); - /* Test for alternate separator */ - q = strrchr(p ? p : argv0, '/'); - if (q != NULL) - p = q; - if (p != NULL) { - n = p + 1 - argv0; - if (n > 1 && p[-1] != ':') - n--; /* Drop trailing separator */ - } - } - #else /* All other filename syntaxes */ - if (argc > 0 && argv0 != NULL) - p = strrchr(argv0, SEP); - if (p != NULL) { - #ifndef RISCOS - n = p + 1 - argv0; - #else /* don't include trailing separator */ - n = p - argv0; - #endif /* RISCOS */ - #if SEP == '/' /* Special case for Unix filename syntax */ - if (n > 1) - n--; /* Drop trailing separator */ - #endif /* Unix */ - } - #endif /* All others */ - a = PyString_FromStringAndSize(argv0, n); - if (a == NULL) - Py_FatalError("no mem for sys.path insertion"); - if (PyList_Insert(path, 0, a) < 0) - Py_FatalError("sys.path.insert(0) failed"); - Py_DECREF(a); - } Py_DECREF(av); } --- 905,914 ----