Index: Lib/runpy.py =================================================================== --- Lib/runpy.py (revision 56090) +++ Lib/runpy.py (working copy) @@ -95,6 +95,18 @@ filename, loader, alter_sys) +def run_zip(zip_filename, mod_name='__zipmain__'): + """Execute a module within of a zip file. + + This is used to implement the -z interpreter flag. + """ + sys.path.insert(0, zip_filename) + try: + run_module(mod_name, run_name='__main__') + finally: + sys.path.pop() # Restore sys.path to what it was before. + + if __name__ == "__main__": # Run the module specified as the next command line argument if len(sys.argv) < 2: Index: Modules/main.c =================================================================== --- Modules/main.c (revision 56090) +++ Modules/main.c (working copy) @@ -40,7 +40,7 @@ static int orig_argc; /* command line options */ -#define BASE_OPTS "3c:dEhim:OQ:StuUvVW:xX?" +#define BASE_OPTS "3c:dEhim:OQ:StuUvVW:xXz:?" #ifndef RISCOS #define PROGRAM_OPTS BASE_OPTS @@ -155,11 +155,10 @@ Py_DECREF(runpy); return -1; } - runargs = Py_BuildValue("sOsO", module, - Py_None, "__main__", Py_True); + runargs = Py_BuildValue("sOsO", module, Py_None, "__main__", Py_True); if (runargs == NULL) { fprintf(stderr, - "Could not create arguments for runpy.run_module\n"); + "Could not create arguments for runpy.run_module\n"); Py_DECREF(runpy); Py_DECREF(runmodule); return -1; @@ -178,6 +177,46 @@ return 0; } + +/* Invokes the standard library runpy.run_zip function to implement the -z + interpreter flag. */ +static int RunZip(char *zip_filename) +{ + PyObject *runpy, *runzip, *runargs, *result; + runpy = PyImport_ImportModule("runpy"); + if (runpy == NULL) { + fprintf(stderr, "Could not import runpy module\n"); + return -1; + } + runzip = PyObject_GetAttrString(runpy, "run_zip"); + if (runzip == NULL) { + fprintf(stderr, "Could not access runpy.run_zip\n"); + Py_DECREF(runpy); + return -1; + } + runargs = Py_BuildValue("(s)", zip_filename); + if (runargs == NULL) { + fprintf(stderr, + "Could not create arguments for runpy.run_zip\n"); + Py_DECREF(runpy); + Py_DECREF(runzip); + return -1; + } + result = PyObject_Call(runzip, runargs, NULL); + if (result == NULL) { + PyErr_Print(); + } + Py_DECREF(runpy); + Py_DECREF(runzip); + Py_DECREF(runargs); + if (result == NULL) { + return -1; + } + Py_DECREF(result); + return 0; +} + + /* Wait until threading._shutdown completes, provided the threading module was imported in the first place. The shutdown routine will wait until all non-daemon @@ -215,11 +254,15 @@ char *command = NULL; char *filename = NULL; char *module = NULL; + char *zip_filename = NULL; FILE *fp = stdin; char *p; int unbuffered = 0; int skipfirstline = 0; int stdin_is_interactive = 0; + /* normal_run is true iff we are not using any of the special run mode + flags: -c, -m, or -z */ + int normal_run = 0; int help = 0; int version = 0; int saw_unbuffered_flag = 0; @@ -237,10 +280,11 @@ PySys_ResetWarnOptions(); while ((c = _PyOS_GetOpt(argc, argv, PROGRAM_OPTS)) != EOF) { + /* The -c, -m and -z options are considered the last interpreter + options specified. Subsequent arguments that look like + options are left for the command/module to interpret. */ if (c == 'c') { - /* -c is the last option; following arguments - that look like options are left for the - command to interpret. */ + /* + 2 for \0 and newline */ command = (char *)malloc(strlen(_PyOS_optarg) + 2); if (command == NULL) Py_FatalError( @@ -251,10 +295,7 @@ } if (c == 'm') { - /* -m is the last option; following arguments - that look like options are left for the - module to interpret. */ - module = (char *)malloc(strlen(_PyOS_optarg) + 2); + module = (char *)malloc(strlen(_PyOS_optarg) + 1); if (module == NULL) Py_FatalError( "not enough memory to copy -m argument"); @@ -262,6 +303,15 @@ break; } + if (c == 'z') { + zip_filename = (char *)malloc(strlen(_PyOS_optarg) + 1); + if (zip_filename == NULL) + Py_FatalError( + "not enough memory to copy -z argument"); + strcpy(zip_filename, _PyOS_optarg); + break; + } + switch (c) { case 'd': @@ -378,8 +428,9 @@ (p = Py_GETENV("PYTHONUNBUFFERED")) && *p != '\0') unbuffered = 1; - if (command == NULL && module == NULL && _PyOS_optind < argc && - strcmp(argv[_PyOS_optind], "-") != 0) + normal_run = command == NULL && module == NULL && zip_filename == NULL; + if (normal_run && + _PyOS_optind < argc && strcmp(argv[_PyOS_optind], "-") != 0) { #ifdef __VMS filename = decc$translate_vms(argv[_PyOS_optind]); @@ -479,20 +530,14 @@ Py_Initialize(); if (Py_VerboseFlag || - (command == NULL && filename == NULL && module == NULL && stdin_is_interactive)) { + (normal_run && filename == NULL && stdin_is_interactive)) { fprintf(stderr, "Python %s on %s\n", Py_GetVersion(), Py_GetPlatform()); if (!Py_NoSiteFlag) fprintf(stderr, "%s\n", COPYRIGHT); } - if (command != NULL) { - /* Backup _PyOS_optind and force sys.argv[0] = '-c' */ - _PyOS_optind--; - argv[_PyOS_optind] = "-c"; - } - - if (module != NULL) { + if (!normal_run) { /* Backup _PyOS_optind and force sys.argv[0] = '-c' so that PySys_SetArgv correctly sets sys.path[0] to ''*/ _PyOS_optind--; @@ -501,7 +546,7 @@ PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind); - if ((Py_InspectFlag || (command == NULL && filename == NULL && module == NULL)) && + if ((Py_InspectFlag || (normal_run && filename == NULL)) && isatty(fileno(stdin))) { PyObject *v; v = PyImport_ImportModule("readline"); @@ -517,6 +562,9 @@ } else if (module) { sts = RunModule(module); free(module); + } else if (zip_filename) { + sts = RunZip(zip_filename); + free(zip_filename); } else { if (filename == NULL && stdin_is_interactive) { @@ -587,4 +635,3 @@ #ifdef __cplusplus } #endif -