Index: Lib/runzip.py =================================================================== --- Lib/runzip.py (revision 0) +++ Lib/runzip.py (revision 0) @@ -0,0 +1,28 @@ +"""runzip.py + +Support for running a zip file like an executable. +""" +# Written by Andy Chu + +import sys + +def runzip(zip_filename): + """Import/execute the __zipmain__ module at the root of a zip file + + Note that __name__ will not be not '__main__' but it's expected that + __zipmain__ is a special stub inserted at build time, e.g: + + from my.package import my_real_main_module + my_real_main_module.main() + """ + sys.path.insert(0, zip_filename) + import __zipmain__ + + +if __name__ == "__main__": + # Run the zip file specified as the next command line argument + if len(sys.argv) < 2: + print >> sys.stderr, "No module specified for execution" + else: + del sys.argv[0] # Make the requested module sys.argv[0] + runzip(sys.argv[0]) Property changes on: Lib/runzip.py ___________________________________________________________________ Name: svn:executable + * Index: Modules/main.c =================================================================== --- Modules/main.c (revision 55753) +++ 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 runzip.runzip function to implement the -z + interpreter flag. */ +static int RunZip(char *zip_filename) +{ + PyObject *module, *function, *args, *result; + module = PyImport_ImportModule("runzip"); + if (module == NULL) { + fprintf(stderr, "Could not import runzip module\n"); + return -1; + } + function = PyObject_GetAttrString(module, "runzip"); + if (function == NULL) { + fprintf(stderr, "Could not access runzip.runzip\n"); + Py_DECREF(module); + return -1; + } + args = Py_BuildValue("(s)", zip_filename); + if (args == NULL) { + fprintf(stderr, + "Could not create arguments for runzip.runzip\n"); + Py_DECREF(module); + Py_DECREF(function); + return -1; + } + result = PyObject_Call(function, args, NULL); + if (result == NULL) { + PyErr_Print(); + } + Py_DECREF(module); + Py_DECREF(function); + Py_DECREF(args); + 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 -