Anthony Tuininga avatar Anthony Tuininga committed c07b876

Moved code from the experimental branch in preparation for release of the new
version.

Comments (0)

Files changed (51)

Common.c

-//-----------------------------------------------------------------------------
-// Common.c
-//   Routines which are common to running frozen executables.
-//-----------------------------------------------------------------------------
-
-#include <compile.h>
-#include <eval.h>
-#include <osdefs.h>
-
-//-----------------------------------------------------------------------------
-// ExecuteScript()
-//   Execute the script found within the file.
-//-----------------------------------------------------------------------------
-static int ExecuteScript(
-    const char *fileName)		// name of file containing Python code
-{
-    PyObject *module, *importer, *code, *dict, *pathList, *temp;
-    char dirName[MAXPATHLEN + 1];
-    int result;
-    size_t i;
-
-#ifdef __WIN32__
-    char dllName[MAXPATHLEN + 1];
-    HMODULE handle;
-
-    // set the attribute sys.dllname on Windows so that FreezePython can know
-    // which DLL needs to be copied without requiring the presence of the
-    // win32api module
-    temp = PySys_GetObject("dllhandle");
-    if (!temp)
-        return FatalError("cannot get dll handle");
-    handle = (HMODULE) PyInt_AsLong(temp);
-    Py_DECREF(temp);
-    if (PyErr_Occurred())
-        return FatalError("dll handle is not an integer");
-    if (!GetModuleFileName(handle, dllName, sizeof(dllName)))
-        return FatalError("cannot get name of Python DLL");
-    temp = PyString_FromString(dllName);
-    if (!temp)
-        return FatalError("cannot get Python string for DLL name");
-    PySys_SetObject("dllname", temp);
-    Py_DECREF(temp);
-    if (PyErr_Occurred())
-        return FatalError("cannot set dll name in module sys");
-#endif
-
-    // calculate the directory in which the file is located
-    strcpy(dirName, fileName);
-    for (i = strlen(dirName); i > 0 && dirName[i] != SEP; --i);
-    dirName[i] = '\0';
-
-    // add the file to sys.path
-    pathList = PySys_GetObject("path");
-    if (!pathList)
-        return FatalError("cannot acquire sys.path");
-    temp = PyString_FromString(dirName);
-    if (!temp)
-        return FatalError("cannot create Python string for directory name");
-    result = PyList_Insert(pathList, 0, temp);
-    Py_DECREF(temp);
-    if (result < 0)
-        return FatalError("cannot insert directory name in sys.path");
-    temp = PyString_FromString(fileName);
-    if (!temp)
-        return FatalError("cannot create Python string for file name");
-    result = PyList_Insert(pathList, 0, temp);
-    Py_DECREF(temp);
-    if (result < 0)
-        return FatalError("cannot insert file name in sys.path");
-
-    // load and execute initscript
-    module = PyImport_ImportModule("zipimport");
-    if (!module)
-        return FatalError("cannot import zipimport module");
-    importer = PyObject_CallMethod(module, "zipimporter", "s", fileName);
-    Py_DECREF(module);
-    if (!importer)
-        return FatalError("cannot get zipimporter instance");
-    code = PyObject_CallMethod(importer, "get_code", "s", "cx_Freeze__init__");
-    Py_DECREF(importer);
-    if (!code)
-        return FatalError("unable to locate initialization module");
-    dict = PyDict_New();
-    if (!dict)
-        return FatalError("unable to create temporary dictionary");
-    if (PyDict_SetItemString(dict, "__builtins__", PyEval_GetBuiltins()) < 0)
-        return FatalError("unable to set builtins for initialization module");
-    temp = PyEval_EvalCode( (PyCodeObject*) code, dict, dict);
-    Py_DECREF(code);
-    Py_DECREF(dict);
-    if (!temp)
-        return FatalScriptError();
-    Py_DECREF(temp);
-
-    return 0;
-}
-

Console.c

-//-----------------------------------------------------------------------------
-// Console.c
-//   Main routine for frozen programs which run in a console.
-//-----------------------------------------------------------------------------
-
-#include <Python.h>
-#ifdef __WIN32__
-#include <windows.h>
-#endif
-
-//-----------------------------------------------------------------------------
-// FatalError()
-//   Prints a fatal error.
-//-----------------------------------------------------------------------------
-static int FatalError(
-    const char *message)		// message to print
-{
-    PyErr_Print();
-    Py_FatalError(message);
-    return -1;
-}
-
-
-//-----------------------------------------------------------------------------
-// FatalScriptError()
-//   Prints a fatal error in the initialization script.
-//-----------------------------------------------------------------------------
-static int FatalScriptError(void)
-{
-    PyErr_Print();
-    return -1;
-}
-
-
-#include "Common.c"
-
-
-//-----------------------------------------------------------------------------
-// main()
-//   Main routine for frozen programs.
-//-----------------------------------------------------------------------------
-int main(int argc, char **argv)
-{
-    const char *fileName;
-
-    // initialize Python
-    Py_NoSiteFlag = 1;
-    Py_FrozenFlag = 1;
-    Py_IgnoreEnvironmentFlag = 1;
-    Py_SetPythonHome("");
-    Py_SetProgramName(argv[0]);
-    fileName = Py_GetProgramFullPath();
-    Py_Initialize();
-    PySys_SetArgv(argc, argv);
-
-    // do the work
-    if (ExecuteScript(fileName) < 0)
-        return 1;
-
-    Py_Finalize();
-    return 0;
-}
-

ConsoleKeepPath.c

-//-----------------------------------------------------------------------------
-// ConsoleKeepPath.c
-//   Main routine for frozen programs which need a Python installation to do
-// their work (such as FreezePython). This executable will set the attribute
-// sys.dllname on Windows so that no third party modules are required for
-// FreezePython to do its work. It will also examine the command line for the
-// presence of the arguments -O and -OO and set the optimization flag similar
-// to what the Python executable itself does.
-//-----------------------------------------------------------------------------
-
-#include <Python.h>
-#ifdef __WIN32__
-#include <windows.h>
-#endif
-
-//-----------------------------------------------------------------------------
-// FatalError()
-//   Prints a fatal error.
-//-----------------------------------------------------------------------------
-static int FatalError(
-    const char *message)		// message to print
-{
-    PyErr_Print();
-    Py_FatalError(message);
-    return -1;
-}
-
-
-//-----------------------------------------------------------------------------
-// FatalScriptError()
-//   Prints a fatal error in the initialization script.
-//-----------------------------------------------------------------------------
-static int FatalScriptError(void)
-{
-    PyErr_Print();
-    return -1;
-}
-
-
-#include "Common.c"
-
-
-//-----------------------------------------------------------------------------
-// main()
-//   Main routine for frozen programs.
-//-----------------------------------------------------------------------------
-int main(int argc, char **argv)
-{
-    const char *fileName;
-    int i;
-
-    // determine whether or not to set the optimization flag
-    for (i = 1; i < argc; i++) {
-        if (strcmp(argv[i], "-O") == 0)
-            Py_OptimizeFlag = 1;
-        else if (strcmp(argv[i], "-OO") == 0)
-            Py_OptimizeFlag = 2;
-    }
-
-    // initialize Python
-    Py_SetProgramName(argv[0]);
-    fileName = Py_GetProgramFullPath();
-    Py_Initialize();
-    PySys_SetArgv(argc, argv);
-
-    // do the work
-    if (ExecuteScript(fileName) < 0)
-        return 1;
-
-    Py_Finalize();
-    return 0;
-}
-

FreezePython.py

-import optparse
-import os
-import shutil
-import stat
-import sys
-
-import Freezer
-import ModuleFinder
-
-USAGE = \
-"""
-%prog [options] [SCRIPT]
-
-Freeze a Python script and all of its referenced modules to a base
-executable which can then be distributed without requiring a Python
-installation."""
-
-VERSION = \
-"""
-%prog HEAD
-Copyright (c) 2002-2006 Computronix Corporation. All rights reserved."""
-
-# parse the command line
-parser = optparse.OptionParser(version = VERSION.strip(),
-        usage = USAGE.strip())
-parser.add_option("-O",
-        action = "store_true",
-        dest = "optimized",
-        help = "optimize generated bytecode as per PYTHONOPTIMIZE; "
-               "use -OO in order to remove doc strings")
-parser.add_option("-c", "--compress",
-        action = "store_true",
-        dest = "compress",
-        help = "compress byte code in zip files")
-parser.add_option("--base-name", "--base-binary",
-        dest = "baseName",
-        metavar = "NAME",
-        help = "file on which to base the target file; if the name of the "
-               "file is not an absolute file name, the subdirectory bases "
-               "(rooted in the directory in which the freezer is found) "
-               "will be searched for a file matching the name")
-parser.add_option("--init-script",
-        dest = "initScript",
-        metavar = "NAME",
-        help = "script which will be executed upon startup; if the name of "
-               "the file is not an absolute file name, the subdirectory "
-               "initscripts (rooted in the directory in which the freezer is "
-               "found) will be searched for a file matching the name")
-parser.add_option("--target-dir", "--install-dir",
-        dest = "targetDir",
-        metavar = "DIR",
-        help = "the directory in which to place the target file and "
-               "any dependent files")
-parser.add_option("--target-name",
-        dest = "targetName",
-        metavar = "NAME",
-        help = "the name of the file to create instead of the base name "
-               "of the script and the extension of the base binary")
-parser.add_option("--shared-lib-name",
-        dest = "sharedLibName",
-        metavar = "NAME",
-        help = "the name of the shared library (DLL) implementing the Python "
-               "runtime which is required for a frozen binary to work")
-parser.add_option("--no-copy-deps", "--keep-path",
-        dest = "copyDeps",
-        default = True,
-        action = "store_false",
-        help = "do not copy the dependent files (extensions, shared "
-               "libraries, etc.) to the target directory; this also modifies "
-               "the default init script to ConsoleKeepPath.py and means that "
-               "the target executable requires a Python installation to "
-               "execute properly")
-parser.add_option("--default-path",
-        action = "append",
-        dest = "defaultPath",
-        metavar = "DIRS",
-        help = "list of paths separated by the standard path separator for "
-               "the platform which will be used to initialize sys.path prior "
-               "to running the module finder")
-parser.add_option("--include-path",
-        action = "append",
-        dest = "includePath",
-        metavar = "DIRS",
-        help = "list of paths separated by the standard path separator for "
-               "the platform which will be used to modify sys.path prior to "
-               "running the module finder")
-parser.add_option("--replace-paths",
-        dest = "replacePaths",
-        metavar = "DIRECTIVES",
-        help = "replace all the paths in modules found in the given paths "
-               "with the given replacement string; multiple values are "
-               "separated by the standard path separator and each value is of "
-               "the form path=replacement_string; path can be * which means "
-               "all paths not already specified")
-parser.add_option("--include-modules",
-        dest = "includeModules",
-        metavar = "NAMES",
-        help = "comma separated list of modules to include")
-parser.add_option("--exclude-modules",
-        dest = "excludeModules",
-        metavar = "NAMES",
-        help = "comma separated list of modules to exclude")
-parser.add_option("--ext-list-file",
-        dest = "extListFile",
-        metavar = "NAME",
-        help = "name of file in which to place the list of dependent files "
-               "which were copied into the target directory")
-parser.add_option("-z", "--zip-include",
-        dest = "zipIncludes",
-        action = "append",
-        default = [],
-        metavar = "SPEC",
-        help = "name of file to add to the zip file or a specification of the "
-               "form name=arcname which will specify the archive name to use; "
-               "multiple --zip-include arguments can be used")
-options, args = parser.parse_args()
-
-# perform some massaging of the arguments and options
-if len(args) == 1:
-    options.script, = args
-elif len(args) == 0:
-    options.script = None
-else:
-    parser.error("too many arguments")
-
-if options.script is None and options.includeModules is None \
-        and options.copyDeps:
-    parser.error("a script or a list of modules must be specified")
-
-if options.targetName is None and options.script is None:
-    parser.error("a script or a target name must be specified")
-
-defaultName = "Console"
-if not options.copyDeps:
-    defaultName = "ConsoleKeepPath"
-if sys.platform == "win32":
-    defaultName += ".exe"
-options.baseName = Freezer.FullFileName("bases", options.baseName, defaultName)
-
-defaultName = "Console.py"
-if not options.copyDeps:
-    defaultName = "ConsoleKeepPath.py"
-options.initScript = Freezer.FullFileName("initscripts", options.initScript,
-        defaultName)
-
-if options.targetName is None:
-    if options.script is None:
-        parser.error("a script or a target name must be specified")
-    name, ext = os.path.splitext(os.path.basename(options.script))
-    baseName, ext = os.path.splitext(os.path.basename(options.baseName))
-    options.targetName = name + ext
-
-if options.targetDir is None:
-    options.targetName = os.path.abspath(options.targetName)
-    options.targetDir = os.path.dirname(options.targetName)
-else:
-    options.targetName = os.path.join(options.targetDir, options.targetName)
-
-# determine the list of modules to exclude from the output
-excludes = []
-if options.excludeModules:
-    excludes = options.excludeModules.split(",")
-
-# modify sys.path as needed
-if options.defaultPath is not None:
-    sys.path = [p for mp in options.defaultPath for p in mp.split(os.pathsep)]
-if options.includePath is not None:
-    paths = [p for mp in options.includePath for p in mp.split(os.pathsep)]
-    sys.path = paths + sys.path
-if options.script is not None:
-    sys.path.insert(0, os.path.dirname(options.script))
-
-# determine path replacements
-replacePaths = {}
-if options.replacePaths:
-    starDirective = None
-    for directive in options.replacePaths.split(os.pathsep):
-        fromPath, replacement = directive.split("=")
-        if fromPath == "*":
-            starDirective = replacement
-        else:
-            replacePaths[fromPath] = replacement
-    if starDirective is not None:
-        for path in sys.path:
-            if not path:
-                continue
-            path = path + os.sep
-            if path and path not in replacePaths:
-                replacePaths[path] = starDirective
-
-# locate all of the modules
-finder = ModuleFinder.ModuleFinder(excludes, replacePaths)
-if options.script is not None:
-    finder.run_script(options.script)
-if options.includeModules:
-    for name in options.includeModules.split(","):
-        finder.import_hook(name)
-if options.compress:
-    finder.import_hook("zlib")
-finder.load_file(options.initScript, "cx_Freeze__init__")
-if options.copyDeps:
-    Freezer.CreateExtensionLoaders(finder)
-
-# report the result of the module location process
-finder.report()
-
-# start the freezing process
-if not os.path.exists(options.targetDir):
-    os.makedirs(options.targetDir)
-if os.path.exists(options.targetName):
-    os.chmod(options.targetName, 0777)
-    os.remove(options.targetName)
-shutil.copy(options.baseName, options.targetName)
-if not os.access(options.targetName, os.W_OK):
-    mode = os.stat(options.targetName).st_mode
-    os.chmod(options.targetName, mode | stat.S_IWUSR)
-Freezer.Freeze(options.targetName, finder, options.zipIncludes,
-        options.compress)
-if options.copyDeps:
-    sharedLibName = options.sharedLibName or getattr(sys, "dllname", None)
-    if sharedLibName is not None:
-        finder.AddDependentFile(sharedLibName)
-    finder.CopyDependentFiles(options.targetDir, options.extListFile)
-
-print "Frozen binary %s created." % options.targetName
-print "Done."
-

Freezer.py

-"""Utility module for freezing Python modules to a base binary."""
-
-import imp
-import marshal
-import os
-import sys
-import struct
-import time
-import zipfile
-
-# NOTE: the try: except: block in this code is not necessary under Python 2.4
-# and higher and can be removed once support for Python 2.3 is no longer needed
-EXTENSION_LOADER_SOURCE = \
-"""
-import imp, os, sys
-
-found = False
-for p in sys.path:
-    if not os.path.isdir(p):
-        continue
-    f = os.path.join(p, "%s")
-    if not os.path.exists(f):
-        continue
-    try:
-        m = imp.load_dynamic(__name__, f)
-    except ImportError:
-        del sys.modules[__name__]
-        raise
-    sys.modules[__name__] = m
-    found = True
-    break
-if not found:
-    del sys.modules[__name__]
-    raise ImportError, "No module named %%s" %% __name__
-"""
-
-
-def CreateExtensionLoaders(moduleFinder):
-    """Create extension loaders for all modules which are extensions which
-       would not be found using the normal import mechanism; these include such
-       things as extensions found within packages and modules which have names
-       that don't correspond to the file name in which they are found."""
-    for name, module in moduleFinder.modules.items():
-        if module.__code__ is not None or module.__file__ is None:
-            continue
-        fileName = os.path.basename(module.__file__)
-        baseFileName, ext = os.path.splitext(fileName)
-        if baseFileName != name and name != "zlib":
-            if "." in name:
-                fileName = name + ext
-            generatedFileName = "ExtensionLoader_%s.py" % \
-                    name.replace(".", "_")
-            module.__code__ = compile(EXTENSION_LOADER_SOURCE % fileName,
-                    generatedFileName, "exec")
-            moduleFinder.scan_code(module.__code__, module)
-        moduleFinder.AddDependentFile(module.__file__, fileName)
-
-
-def FullFileName(subDir, name, defaultName):
-    """Return the full name of the file to use."""
-    if name is None:
-        name = defaultName
-    defaultBaseName, defaultExt = \
-            os.path.splitext(os.path.normcase(defaultName))
-    name, ext = os.path.splitext(os.path.normcase(name))
-    if not ext:
-        ext = defaultExt
-    if os.path.isfile(sys.path[0]):
-        baseDir = os.path.dirname(sys.path[0])
-    else:
-        baseDir = os.path.dirname(os.path.abspath(sys.argv[0]))
-    return os.path.join(baseDir, subDir, name + ext)
-
-
-def Freeze(targetFileName, moduleFinder, zipIncludes, compress):
-    """Freeze the modules found by the finder to the end of the file."""
-    outFile = zipfile.PyZipFile(targetFileName, "a", zipfile.ZIP_DEFLATED)
-    for name, module in moduleFinder.modules.iteritems():
-        if module.__code__ is None:
-            continue
-        fileName = "/".join(name.split("."))
-        if module.__path__:
-            fileName += "/__init__"
-        if os.path.exists(module.__file__):
-            mtime = os.stat(module.__file__).st_mtime
-        else:
-            mtime = time.time()
-        zipTime = time.localtime(mtime)[:6]
-        data = imp.get_magic() + struct.pack("<i", mtime) + \
-                marshal.dumps(module.__code__)
-        zinfo = zipfile.ZipInfo(fileName + ".pyc", zipTime)
-        if compress:
-            zinfo.compress_type = zipfile.ZIP_DEFLATED
-        outFile.writestr(zinfo, data)
-    for spec in zipIncludes:
-        if '=' in spec:
-            fileName, archiveName = spec.split('=', 1)
-        else:
-            fileName = archiveName = spec
-        outFile.write(fileName, archiveName)
-
+Changes from 3.0.3 to 4.0b1
+ 1) Added support for placing modules in library.zip or in a separate zip file
+    for each executable that is produced.
+ 2) Added support for copying binary dependent files (DLLs and shared
+    libraries)
+ 3) Added support for including all submodules in a package
+ 4) Added support for including icons in Windows executables
+ 5) Added support for constants module which can be used for determining
+    certain build constants at runtime
+ 6) Added support for relative imports available in Python 2.5 and up
+ 7) Added support for building Windows installers (Python 2.5 and up) and
+    RPM packages
+ 8) Added support for distutils configuration scripts
+ 9) Added support for hooks which can force inclusion or exclusion of modules
+    when certain modules are included
+10) Added documentation and samples
+11) Added setup.py for building the cx_Freeze package instead of a script
+    used to build only the frozen bases
+12) FreezePython renamed to a script called freeze in the Python distribution
+13) On Linux and other platforms that support it set LD_RUN_PATH to include
+    the directory in which the executable is located
+
 Changes from 3.0.2 to 3.0.3
  1) In Common.c, used MAXPATHLEN defined in the Python OS independent include
     file rather than the PATH_MAX define which is OS dependent and is not
+Copyright � 2007, Colt Engineering, Edmonton, Alberta, Canada.
 Copyright � 2001-2006, Computronix (Canada) Ltd., Edmonton, Alberta, Canada.
 All rights reserved.
 
        notice, this list of conditions, and the following disclaimer in the
        documentation and/or other materials provided with the distribution.
 
-    3. Neither the name of Computronix nor the names of its contributors may
-       be used to endorse or promote products derived from this software
+    3. Neither the name of Colt Engineering nor the names of its contributors
+       may be used to endorse or promote products derived from this software
        without specific prior written permission.
 
 DISCLAIMER:
-THIS SOFTWARE IS PROVIDED BY COMPUTRONIX AND CONTRIBUTORS *AS IS*
+THIS SOFTWARE IS PROVIDED BY COLT ENGINEERING AND CONTRIBUTORS *AS IS*
 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COMPUTRONIX
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COLT ENGINEERING
 OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 SUCH DAMAGE.
 
-Computronix� is a registered trademark of Computronix (Canada) Ltd.
-

MANIFEST

-Common.c
-Console.c
-ConsoleKeepPath.c
-ModuleFinder.py
-FreezePython.py
-Freezer.py
-HISTORY.txt
-LICENSE.txt
-MakeFrozenBases.py
-README.txt
-Win32GUI.c
-initscripts
+include MANIFEST.in
+include *.txt
+recursive-include doc *.html
+recursive-include initscripts *.py
+recursive-include samples *.py
+recursive-include source *.c *.rc

MakeFrozenBases.py

-"""Make the frozen base executables."""
-
-import distutils.sysconfig
-import os
-import sys
-
-CC = os.environ.get("CC", "gcc")
-
-# define function for building a base executable
-def BuildBase(name, linkerFlags = "", sharedLib = False):
-    vars = distutils.sysconfig.get_config_vars()
-    sourceName = name + ".c"
-    objectName = name + ".o"
-    targetName = name
-    if sharedLib:
-        if sys.platform == "win32":
-            targetName += ".dll"
-        else:
-            targetName += vars["SO"]
-        linkerFlags = "-shared %s" % linkerFlags
-    else:
-        targetName += vars["EXE"]
-    compilerFlags = "-c -I. -I%s -I%s" % \
-            (distutils.sysconfig.get_python_inc(),
-             distutils.sysconfig.get_python_inc(1))
-    linkerFlags += " -s"
-    if sys.platform == "win32":
-        import win32api
-        linkerFlags += " " + win32api.GetModuleFileName(sys.dllhandle)
-    else:
-        linkerFlags += " %s %s %s/%s" % \
-                (vars["LDFLAGS"], vars["LINKFORSHARED"], vars["LIBPL"],
-                 vars["INSTSONAME"])
-        if sys.platform == "hp-ux11":
-            linkerFlags += " -lcl"
-        linkerFlags += " %s %s %s %s" % \
-                (vars["LIBS"], vars["LIBM"], vars["LOCALMODLIBS"],
-                 vars["BASEMODLIBS"])
-    command = "%s %s -o %s %s" % (CC, compilerFlags, objectName, sourceName)
-    print command
-    if os.system(command) != 0:
-        raise "Failed to compile %s" % sourceName
-    command = "%s -o %s %s %s" % \
-            (CC, os.path.join("bases", targetName), objectName, linkerFlags)
-    print command
-    if os.system(command) != 0:
-        raise "Failed to link %s" % sourceName
-    os.unlink(objectName)
-
-# create the directory, if necessary
-if not os.path.exists("bases"):
-    os.mkdir("bases")
-
-# build the base executables
-BuildBase("Console")
-BuildBase("ConsoleKeepPath")
-if sys.platform == "win32":
-    BuildBase("Win32GUI", "-mwindows")
-

ModuleFinder.py

-"""Wrapper for the standard library Python module modulefinder which manages
-   a few of the things that the standard module does not manage."""
-
-import glob
-import imp
-import modulefinder
-import os
-import shutil
-import sys
-
-# ensure that PyXML is handled properly if found
-modulefinder.ReplacePackage("_xmlplus", "xml")
-
-class ModuleFinder(modulefinder.ModuleFinder):
-    """Subclass of modulefinder which handles a few situations that the
-       base class does not handle very well."""
-
-    def __init__(self, excludes, replacePaths):
-        modulefinder.ModuleFinder.__init__(self, excludes = excludes,
-                replace_paths = replacePaths.items())
-        self.dependentFiles = {}
-
-    def AddDependentFile(self, sourceName, targetName = None):
-        """Add a dependent file to the list of dependent files."""
-        if targetName is None:
-            targetName = os.path.basename(sourceName)
-        self.dependentFiles[targetName] = sourceName
-
-    def CopyDependentFiles(self, dir, listFileName = None):
-        """Copy the required files to the directory and optionally include the
-           list of files in the file specified."""
-        for targetName, sourceName in self.dependentFiles.iteritems():
-            sourceName = os.path.abspath(sourceName)
-            targetName = os.path.join(dir, targetName)
-            if targetName == sourceName:
-                print "Skipping", sourceName
-                continue
-            print "Copying", sourceName
-            if os.path.exists(targetName):
-                os.chmod(targetName, 0777)
-                os.remove(targetName)
-            shutil.copy2(sourceName, targetName)
-        if listFileName is not None:
-            fileNames = [os.path.join(dir, n) for n in self.dependentFiles]
-            fileNames.sort()
-            print >> file(listFileName, "w"), "\n".join(fileNames)
-
-    def find_module(self, name, path, parent = None):
-        """Find the module and return a reference to it."""
-        if path is None and name in ("pythoncom", "pywintypes"):
-            try:
-                module = __import__(name)
-                return None, module.__file__, (".dll", "rb", imp.C_EXTENSION)
-            except ImportError:
-                pass
-        fp, modulePath, stuff = modulefinder.ModuleFinder.find_module(self,
-                name, path, parent)
-        if name == "win32com":
-            modulefinder.AddPackagePath(name,
-                    os.path.join(os.path.dirname(modulePath), "win32comext"))
-        return fp, modulePath, stuff
-
-    def load_module(self, fqname, fp, path, stuff):
-        """Load the module and return a reference to it."""
-        try:
-            module = modulefinder.ModuleFinder.load_module(self, fqname, fp,
-                    path, stuff)
-        except SyntaxError, value:
-            raise "Module %s from file %s has %s." % (fqname, path, value)
-        suffix, mode, type = stuff
-        if type == imp.C_EXTENSION \
-                and (fqname.startswith("wxPython.") \
-                or fqname.startswith("wx.")):
-            if sys.platform == "win32":
-                dir = os.path.dirname(module.__file__)
-                for dll in glob.glob(os.path.join(dir, "wx*.dll")):
-                    self.AddDependentFile(dll)
-            else:
-                for line in os.popen("ldd %s" % module.__file__).readlines():
-                    line = line.strip()
-                    if not line.startswith("libwx"):
-                        continue
-                    libName, libLocation = line.split(" => ")
-                    if libLocation == "not found":
-                        raise "Library %s not found." % libName
-                    self.AddDependentFile(libLocation.split()[0])
-        return module
-
-    def load_file(self, pathname, moduleName):
-        """Load a module from a given file."""
-        fp = file(pathname, "r")
-        name, ext = os.path.splitext(pathname)
-        stuff = (ext, "r", imp.PY_SOURCE)
-        self.load_module(moduleName, fp, pathname, stuff)
-

PKG-INFO

-Metadata-Version: 1.0
-Name: cx_Freeze
-Version: HEAD
-Author: Anthony Tuininga
-Author-email: anthony at computronix com
-Maintainer: Anthony Tuininga
-Maintainer-email: anthony at computronix com
-Home-page: http://starship.python.net/crew/atuining
-Summary: cross platform method of freezing Python scripts into executables
-Description: cross platform method of freezing Python scripts into executables
-Keywords: freeze
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Environment :: Console
-Classifier: Environment :: Win32 (MS Windows)
-Classifier: Environment :: X11 Applications
-Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Python Software Foundation License
-Classifier: Natural Language :: English
-Classifier: Operating System :: OS Independent
-Classifier: Programming Language :: C
-Classifier: Programming Language :: Python
-Classifier: Topic :: Software Development :: Build Tools
-Classifier: Topic :: System :: Software Distribution
-Classifier: Topic :: Utilities
-WHAT?
-cx_Freeze is a set of utilities for freezing Python scripts into executables
-using many of the techniques found in Thomas Heller's py2exe, Gordon
-McMillan's Installer and the Freeze utility that ships with Python itself.
-
-
-WHY?
-Why did I go to the trouble of creating another set of utilities when these
-three utilities already existed?  The Freeze utility that comes with Python
-itself requires a source distribution, a C compiler and linker which makes for
-a complex environment for creating executables. In addition, this method is
-very slow for creating executables as compared to the other methods. py2exe
-is intended for development on Windows only and cx_Freeze is intended for
-cross platform development. Installer uses an import hook which means that the
-development environment and runtime environment are considerably different.
-
-
-HOW?
-How does it work? A base executable is created which contains code for
-unpacking the list of frozen modules, starting up the Python interpreter and
-passing control to the script which is being frozen. When a script is frozen,
-the script is searched for all references to modules and these modules are then
-byte compiled and written to the end of the base executable. If the modules
-that are referenced are extensions written in C, these modules must be
-included in the path in which the frozen executable is deployed.
-
-
-BINARY INSTALLATION
-Simply extract the archive into a directory. FreezePython searches for base
-executables and initscripts relative to the directory in which FreezePython
-is found. Note that it is important that the binary installation of cx_Freeze
-is compatible with the installation of Python on your machine. If they are
-not, you will get errors with respect to builtin modules not being found or
-missing symbols. If this occurs, proceed to the source installation section.
-
-
-SOURCE INSTALLATION
-Extract the archive into a directory. In order to build cx_Freeze you need to
-have gcc and Python development include files and libraries available. Run the
-following commands.
-
-python MakeFrozenBases.py
-python FreezePython.py --no-copy-deps FreezePython.py
-
-When these commands have completed successfully, the directory will be in the
-same state as a binary installation. Note that on Windows these scripts assume
-the presence of a mingw32 installation which can be acquired from
-http://www.mingw.org.
-
-
-FREEZING
-
-Options and arguments to FreezePython can be seen by executing the command:
-
-FreezePython --help
-
-The default initscript is "Console" unless the --no-copy-deps/--keep-path
-option is specified in which case the default is "ConsoleKeepPath". Each of
-the initscripts is internally documented. You can add additional initscripts
-by simply adding them to the "initscripts" directory. The initscript is
-searched for modules as well as the script being frozen.
-
-The default base executable is "Console". You can add additional base
-executables by simply adding them to the "bases" directory.
-
-The script specified on the command line is searched for modules by examining
-the script for import statements. Each of those modules is then written to a
-zip file and the zip file is appended to the base executable. Note that
-imports done within extension modules and imports done with the __import__()
-routine cannot be examined. In order to get these modules to be included in
-the target executable, either add an explicit import in your script or use
-the --include-modules command line option. You can examine the output of
-FreezePython to determine which modules were actually included and where they
-came from.
-
-
-EXAMPLE
-
-Assume that you have a script called "hello.py" containing the line
-"print 'Hello World!'". To freeze this script you would issue the following
-commands:
-
-FreezePython --install-dir dist hello.py
-
-This would create the following files (the exact number and names of files
-will depend on the platform and version of Python that is used):
-
-dist/hello
-dist/pcre.so
-dist/pwdmodule.so
-dist/strop.so
-
-These files can then be packaged in a zip or tar archive or RPM and
-distributed to the target machine.
-
-
-FEEDBACK
-If you have any feedback, contact me at anthony.tuininga@gmail.com. In
-particular, if any of the authors of the three other methods for freezing
-executables wish to pool resources and merge technology, I am willing to
-pursue that course.
-
+Please see cx_Freeze.html for documentation.

Win32GUI.c

-//-----------------------------------------------------------------------------
-// Win32GUI.c
-//   Main routine for frozen programs written for the Win32 GUI subsystem.
-//-----------------------------------------------------------------------------
-
-#include <Python.h>
-#include <windows.h>
-
-//-----------------------------------------------------------------------------
-// FatalError()
-//   Handle a fatal error.
-//-----------------------------------------------------------------------------
-static int FatalError(
-    char *a_Message)			// message to display
-{
-    MessageBox(NULL, a_Message, "cx_Freeze Fatal Error", MB_ICONERROR);
-    Py_Finalize();
-    return -1;
-}
-
-
-//-----------------------------------------------------------------------------
-// StringifyObject()
-//   Stringify a Python object.
-//-----------------------------------------------------------------------------
-static char *StringifyObject(
-    PyObject *object,			// object to stringify
-    PyObject **stringRep)		// string representation
-{
-    if (object) {
-        *stringRep = PyObject_Str(object);
-        if (*stringRep)
-            return PyString_AS_STRING(*stringRep);
-        return "Unable to stringify";
-    }
-
-    // object is NULL
-    *stringRep = NULL;
-    return "None";
-}
-
-
-//-----------------------------------------------------------------------------
-// FatalPythonErrorNoTraceback()
-//   Handle a fatal Python error without traceback.
-//-----------------------------------------------------------------------------
-static int FatalPythonErrorNoTraceback(
-    PyObject *origType,			// exception type
-    PyObject *origValue,		// exception value
-    char *message)			// message to display
-{
-    PyObject *typeStrRep, *valueStrRep, *origTypeStrRep, *origValueStrRep;
-    char *totalMessage, *typeStr, *valueStr, *origTypeStr, *origValueStr;
-    PyObject *type, *value, *traceback;
-    int totalMessageLength;
-    char *messageFormat;
-
-    // fetch error and string representations of the error
-    PyErr_Fetch(&type, &value, &traceback);
-    origTypeStr = StringifyObject(origType, &origTypeStrRep);
-    origValueStr = StringifyObject(origValue, &origValueStrRep);
-    typeStr = StringifyObject(type, &typeStrRep);
-    valueStr = StringifyObject(value, &valueStrRep);
-
-    // fill out the message to be displayed
-    messageFormat = "Type: %s\nValue: %s\nOther Type: %s\nOtherValue: %s\n%s";
-    totalMessageLength = strlen(origTypeStr) + strlen(origValueStr) +
-            strlen(typeStr) + strlen(valueStr) + strlen(message) +
-            strlen(messageFormat) + 1;
-    totalMessage = malloc(totalMessageLength);
-    if (!totalMessage)
-        return FatalError("Out of memory!");
-    sprintf(totalMessage, messageFormat, typeStr, valueStr, origTypeStr,
-            origValueStr, message);
-
-    // display the message
-    MessageBox(NULL, totalMessage,
-            "cx_Freeze: Python error in main script (traceback unavailable)",
-            MB_ICONERROR);
-    free(totalMessage);
-    return -1;
-}
-
-
-//-----------------------------------------------------------------------------
-// ArgumentValue()
-//   Return a suitable argument value by replacing NULL with Py_None.
-//-----------------------------------------------------------------------------
-static PyObject *ArgumentValue(
-    PyObject *object)			// object to stringify
-{
-    if (object) {
-        Py_INCREF(object);
-        return object;
-    }
-    Py_INCREF(Py_None);
-    return Py_None;
-}
-
-
-//-----------------------------------------------------------------------------
-// FatalScriptError()
-//   Handle a fatal Python error with traceback.
-//-----------------------------------------------------------------------------
-static int FatalScriptError()
-{
-    PyObject *type, *value, *traceback, *argsTuple, *module, *method, *result;
-    const char *messages[3];
-    int tracebackLength, i;
-    char *tracebackStr;
-
-    // get the exception details
-    PyErr_Fetch(&type, &value, &traceback);
-
-    // import the traceback module
-    module = PyImport_ImportModule("traceback");
-    if (!module)
-        return FatalPythonErrorNoTraceback(type, value,
-                "Cannot import traceback module.");
-
-    // get the format_exception method
-    method = PyObject_GetAttrString(module, "format_exception");
-    Py_DECREF(module);
-    if (!method)
-        return FatalPythonErrorNoTraceback(type, value,
-              "Cannot get format_exception method.");
-
-    // create a tuple for the arguments
-    argsTuple = PyTuple_New(3);
-    if (!argsTuple) {
-        Py_DECREF(method);
-        return FatalPythonErrorNoTraceback(type, value,
-                "Cannot create arguments tuple for traceback.");
-    }
-    PyTuple_SET_ITEM(argsTuple, 0, ArgumentValue(type));
-    PyTuple_SET_ITEM(argsTuple, 1, ArgumentValue(value));
-    PyTuple_SET_ITEM(argsTuple, 2, ArgumentValue(traceback));
-
-    // call the format_exception method
-    result = PyObject_CallObject(method, argsTuple);
-    Py_DECREF(method);
-    Py_DECREF(argsTuple);
-    if (!result)
-        return FatalPythonErrorNoTraceback(type, value,
-                "Failed calling format_exception method.");
-
-    // determine length of string representation of formatted traceback
-    tracebackLength = 1;
-    for (i = 0; i < PyList_GET_SIZE(result); i++)
-        tracebackLength += PyString_GET_SIZE(PyList_GET_ITEM(result, i));
-
-    // create a string representation of the formatted traceback
-    tracebackStr = malloc(tracebackLength);
-    if (!tracebackStr) {
-        Py_DECREF(result);
-        return FatalError("Out of memory!");
-    }
-    tracebackStr[0] = '\0';
-    for (i = 0; i < PyList_GET_SIZE(result); i++)
-        strcat(tracebackStr, PyString_AS_STRING(PyList_GET_ITEM(result, i)));
-    Py_DECREF(result);
-
-    // bring up the error
-    MessageBox(NULL, tracebackStr, "cx_Freeze: Python error in main script",
-            MB_ICONERROR);
-    Py_Finalize();
-    return 1;
-}
-
-
-#include "Common.c"
-
-
-//-----------------------------------------------------------------------------
-// WinMain()
-//   Main routine for the executable in Windows.
-//-----------------------------------------------------------------------------
-int WINAPI WinMain(
-    HINSTANCE instance,			// handle to application
-    HINSTANCE prevInstance,		// previous handle to application
-    LPSTR commandLine,			// command line
-    int showFlag)			// show flag
-{
-    PyObject *pathList, *temp;
-    const char *fileName;
-    int result;
-
-    // initialize Python
-    Py_NoSiteFlag = 1;
-    Py_FrozenFlag = 1;
-    Py_IgnoreEnvironmentFlag = 1;
-    Py_SetPythonHome("");
-    Py_SetProgramName(__argv[0]);
-    fileName = Py_GetProgramFullPath();
-    Py_Initialize();
-    PySys_SetArgv(__argc, __argv);
-
-    // do the work
-    if (ExecuteScript(fileName) < 0)
-        return 1;
-
-    // terminate Python
-    Py_Finalize();
-    return 0;
-}
-

cx_Freeze/__init__.py

+import sys
+
+from dist import *
+if sys.platform == "win32":
+    from windist import *
+from finder import *
+from freezer import *
+from main import *
+
+del dist
+del finder
+del freezer
+

cx_Freeze/dist.py

+import distutils.command.bdist_rpm
+import distutils.command.build
+import distutils.command.install
+import distutils.core
+import distutils.dir_util
+import distutils.dist
+import distutils.util
+import distutils.version
+import os
+import sys
+
+import cx_Freeze
+
+__all__ = [ "bdist_rpm", "build", "build_exe", "install", "install_exe",
+            "setup" ]
+
+class Distribution(distutils.dist.Distribution):
+
+    def __init__(self, attrs):
+        self.executables = []
+        distutils.dist.Distribution.__init__(self, attrs)
+
+
+class bdist_rpm(distutils.command.bdist_rpm.bdist_rpm):
+
+    def finalize_options(self):
+        distutils.command.bdist_rpm.bdist_rpm.finalize_options(self)
+        self.use_rpm_opt_flags = 1
+
+    def _make_spec_file(self):
+        contents = distutils.command.bdist_rpm.bdist_rpm._make_spec_file(self)
+        return [c for c in contents if c != 'BuildArch: noarch']
+
+
+class build(distutils.command.build.build):
+    user_options = distutils.command.build.build.user_options + [
+        ('build-exe=', None, 'build directory for executables')
+    ]
+
+    def get_sub_commands(self):
+        subCommands = distutils.command.build.build.get_sub_commands(self)
+        if self.distribution.executables:
+            subCommands.append("build_exe")
+        return subCommands
+
+    def initialize_options(self):
+        distutils.command.build.build.initialize_options(self)
+        self.build_exe = None
+
+    def finalize_options(self):
+        distutils.command.build.build.finalize_options(self)
+        if self.build_exe is None:
+            dirName = "exe.%s-%s" % \
+                    (distutils.util.get_platform(), sys.version[0:3])
+            self.build_exe = os.path.join(self.build_base, dirName)
+
+
+class build_exe(distutils.core.Command):
+    description = "build executables from Python scripts"
+    user_options = [
+        ('build-exe=', 'b',
+         'directory for built executables'),
+        ('optimize=', 'O',
+         'optimization level: -O1 for "python -O", '
+         '-O2 for "python -OO" and -O0 to disable [default: -O0]'),
+        ('excludes=', 'e',
+         'comma-separated list of modules to exclude'),
+        ('includes=', 'i',
+         'comma-separated list of modules to include'),
+        ('packages=', 'p',
+         'comma-separated list of packages to include'),
+        ('replace-paths=', None,
+         'comma-separated list of paths to replace in included modules'),
+        ('path=', None,
+         'comma-separated list of paths to search'),
+        ('init-script=', 'i',
+         'name of script to use during initialization'),
+        ('base=', None,
+         'name of base executable to use'),
+        ('compressed', 'c',
+         'create a compressed zipfile'),
+        ('copy-dependent-files', None,
+         'copy all dependent files'),
+        ('create-shared-zip', None,
+         'create a shared zip file containing shared modules'),
+        ('append-script-to-exe', None,
+         'append the script module to the exe'),
+        ('include-in-shared-zip', None,
+         'include the script module in the shared zip file'),
+        ('icon', None,
+         'include the icon along with the frozen executable(s)'),
+        ('constants=', None,
+         'comma-separated list of constants to include')
+    ]
+    boolean_options = ["compressed", "copy_dependent_files",
+            "create_shared_zip", "append_script_to_exe",
+            "include_in_shared_zip"]
+
+    def _normalize(self, attrName):
+        value = getattr(self, attrName)
+        if value is None:
+            normalizedValue = []
+        elif isinstance(value, basestring):
+            normalizedValue = value.split()
+        else:
+            normalizedValue = list(value)
+        setattr(self, attrName, normalizedValue)
+
+    def initialize_options(self):
+        self.optimize = 0
+        self.build_exe = None
+        self.excludes = []
+        self.includes = []
+        self.packages = []
+        self.replace_paths = []
+        self.compressed = None
+        self.copy_dependent_files = None
+        self.init_script = None
+        self.base = None
+        self.path = None
+        self.create_shared_zip = None
+        self.append_script_to_exe = None
+        self.include_in_shared_zip = None
+        self.icon = None
+        self.constants = []
+
+    def finalize_options(self):
+        self.set_undefined_options('build', ('build_exe', 'build_exe'))
+        self.optimize = int(self.optimize)
+        self._normalize("excludes")
+        self._normalize("includes")
+        self._normalize("packages")
+        self._normalize("constants")
+
+    def run(self):
+        metadata = self.distribution.metadata
+        constantsModule = cx_Freeze.ConstantsModule(metadata.version)
+        for constant in self.constants:
+            parts = constant.split("=")
+            if len(parts) == 1:
+                name = constant
+                value = None
+            else:
+                name, stringValue = parts
+                value = eval(stringValue)
+            constantsModule.values[name] = value
+        freezer = cx_Freeze.Freezer(self.distribution.executables,
+                [constantsModule], self.includes, self.excludes, self.packages,
+                self.replace_paths, self.compressed, self.optimize,
+                self.copy_dependent_files, self.init_script, self.base,
+                self.path, self.create_shared_zip, self.append_script_to_exe,
+                self.include_in_shared_zip, self.build_exe, icon = self.icon)
+        freezer.Freeze()
+
+
+class install(distutils.command.install.install):
+    user_options = distutils.command.install.install.user_options + [
+            ('install-exe=', None,
+             'installation directory for executables')
+    ]
+
+    def expand_dirs(self):
+        distutils.command.install.install.expand_dirs(self)
+        self._expand_attrs(['install_exe'])
+
+    def get_sub_commands(self):
+        subCommands = distutils.command.install.install.get_sub_commands(self)
+        if self.distribution.executables:
+            subCommands.append("install_exe")
+        return [s for s in subCommands if s != "install_egg_info"]
+
+    def initialize_options(self):
+        distutils.command.install.install.initialize_options(self)
+        self.install_exe = None
+
+    def finalize_options(self):
+        if self.prefix is None and sys.platform == "win32":
+            import _winreg
+            key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE,
+                    r"Software\Microsoft\Windows\CurrentVersion")
+            prefix = str(_winreg.QueryValueEx(key, "ProgramFilesDir")[0])
+            metadata = self.distribution.metadata
+            dirName = "%s-%s" % (metadata.name, metadata.version)
+            self.prefix = "%s/%s" % (prefix, dirName)
+        distutils.command.install.install.finalize_options(self)
+        self.convert_paths('exe')
+        if self.root is not None:
+            self.change_roots('exe')
+
+    def select_scheme(self, name):
+        distutils.command.install.install.select_scheme(self, name)
+        if self.install_exe is None:
+            if sys.platform == "win32":
+                self.install_exe = '$base'
+            else:
+                metadata = self.distribution.metadata
+                dirName = "%s-%s" % (metadata.name, metadata.version)
+                self.install_exe = '$base/lib/%s' % dirName
+
+
+class install_exe(distutils.core.Command):
+    description = "install executables built from Python scripts"
+    user_options = [
+        ('install-dir=', 'd', 'directory to install executables to'),
+        ('build-dir=', 'b', 'build directory (where to install from)'),
+        ('force', 'f', 'force installation (overwrite existing files)'),
+        ('skip-build', None, 'skip the build steps')
+    ]
+
+    def initialize_options(self):
+        self.install_dir = None
+        self.force = 0
+        self.build_dir = None
+        self.skip_build = None
+
+    def finalize_options(self):
+        self.set_undefined_options('build', ('build_exe', 'build_dir'))
+        self.set_undefined_options('install',
+                ('install_exe', 'install_dir'),
+                ('force', 'force'),
+                ('skip_build', 'skip_build'))
+
+    def run(self):
+        if not self.skip_build:
+            self.run_command('build_exe')
+        self.outfiles = self.copy_tree(self.build_dir, self.install_dir)
+        if sys.platform != "win32":
+            baseDir = os.path.dirname(os.path.dirname(self.install_dir))
+            binDir = os.path.join(baseDir, "bin")
+            if not os.path.exists(binDir):
+                os.makedirs(binDir)
+            sourceDir = os.path.join("..", self.install_dir[len(baseDir) + 1:])
+            for executable in self.distribution.executables:
+                name = os.path.basename(executable.targetName)
+                source = os.path.join(sourceDir, name)
+                target = os.path.join(binDir, name)
+                if os.path.exists(target):
+                    os.unlink(target)
+                os.symlink(source, target)
+                self.outfiles.append(target)
+
+    def get_inputs(self):
+        return self.distribution.executables or []
+
+    def get_outputs(self):
+        return self.outfiles or []
+
+
+def _AddCommandClass(commandClasses, name, cls):
+    if name not in commandClasses:
+        commandClasses[name] = cls
+
+
+def setup(**attrs):
+    attrs["distclass"] = Distribution
+    commandClasses = attrs.setdefault("cmdclass", {})
+    if sys.platform == "win32":
+        _AddCommandClass(commandClasses, "bdist_msi", cx_Freeze.bdist_msi)
+    else:
+        _AddCommandClass(commandClasses, "bdist_rpm", cx_Freeze.bdist_rpm)
+    _AddCommandClass(commandClasses, "build", build)
+    _AddCommandClass(commandClasses, "build_exe", build_exe)
+    _AddCommandClass(commandClasses, "install", install)
+    _AddCommandClass(commandClasses, "install_exe", install_exe)
+    distutils.core.setup(**attrs)
+

cx_Freeze/finder.py

+"""
+Base class for finding modules.
+"""
+
+import dis
+import imp
+import marshal
+import new
+import opcode
+import os
+import sys
+
+import cx_Freeze.hooks
+
+LOAD_CONST = opcode.opmap["LOAD_CONST"]
+IMPORT_NAME = opcode.opmap["IMPORT_NAME"]
+STORE_NAME = opcode.opmap["STORE_NAME"]
+STORE_GLOBAL = opcode.opmap["STORE_GLOBAL"]
+STORE_OPS = (STORE_NAME, STORE_GLOBAL)
+
+__all__ = [ "Module", "ModuleFinder" ]
+
+class ModuleFinder(object):
+
+    def __init__(self, excludes = [], path = None, replacePaths = []):
+        self.excludes = dict.fromkeys(excludes)
+        self.replacePaths = replacePaths
+        self.path = path or sys.path
+        self.modules = []
+        self.aliases = {}
+        self._modules = dict.fromkeys(excludes)
+        self._builtinModules = dict.fromkeys(sys.builtin_module_names)
+        self._badModules = {}
+        cx_Freeze.hooks.initialize(self)
+
+    def _AddModule(self, name):
+        """Add a module to the list of modules but if one is already found,
+           then return it instead; this is done so that packages can be
+           handled properly."""
+        module = self._modules.get(name)
+        if module is None:
+            module = self._modules[name] = Module(name)
+            self.modules.append(module)
+            if name in self._badModules:
+                del self._badModules[name]
+        return module
+
+    def _DetermineParent(self, caller):
+        """Determine the parent to use when searching packages."""
+        if caller is not None:
+            if caller.path is not None:
+                return caller
+            return self._GetParentByName(caller.name)
+
+    def _EnsureFromList(self, caller, packageModule, fromList,
+            deferredImports):
+        """Ensure that the from list is satisfied. This is only necessary for
+           package modules. If the caller is the package itself, actually
+           attempt to import right then since it must be a submodule; otherwise
+           defer until after all global names are defined in order to avoid
+           spurious complaints about missing modules."""
+        if caller is not packageModule:
+            deferredImports.append((packageModule, fromList))
+        else:
+            for name in fromList:
+                if name == "*" or name in packageModule.globalNames:
+                    continue
+                subModuleName = "%s.%s" % (packageModule.name, name)
+                self._ImportModule(subModuleName, deferredImports, caller)
+
+    def _GetParentByName(self, name):
+        """Return the parent module given the name of a module."""
+        pos = name.rfind(".")
+        if pos > 0:
+            parentName = name[:pos]
+            return self._modules[parentName]
+
+    def _ImportAllSubModules(self, module, deferredImports, recursive = True):
+        """Import all sub modules to the given package."""
+        suffixes = dict.fromkeys([s[0] for s in imp.get_suffixes()])
+        for dir in module.path:
+            try:
+                fileNames = os.listdir(dir)
+            except os.error:
+                continue
+            for fileName in fileNames:
+                name, ext = os.path.splitext(fileName)
+                if ext not in suffixes:
+                    continue
+                if name == "__init__":
+                    continue
+                subModuleName = "%s.%s" % (module.name, name)
+                subModule, returnError = \
+                        self._InternalImportModule(subModuleName,
+                                deferredImports)
+                if returnError and subModule is None:
+                    raise ImportError, "No module named %s" % subModuleName
+                module.globalNames[name] = None
+                if subModule.path and recursive:
+                    self._ImportAllSubModules(subModule, deferredImports,
+                            recursive)
+
+    def _ImportDeferredImports(self, deferredImports):
+        """Import any sub modules that were deferred, if applicable."""
+        for packageModule, subModuleNames in deferredImports:
+            self._EnsureFromList(packageModule, packageModule, subModuleNames,
+                    deferredImports)
+
+    def _ImportModule(self, name, deferredImports, caller = None,
+            relativeImportIndex = 0):
+        """Attempt to find the named module and return it or None if no module
+           by that name could be found."""
+
+        # absolute import (available in Python 2.5 and up)
+        # the name given is the only name that will be searched
+        if relativeImportIndex == 0:
+            module, returnError = self._InternalImportModule(name,
+                    deferredImports)
+
+        # old style relative import (only possibility in Python 2.4 and prior)
+        # the name given is tried in all parents until a match is found and if
+        # no match is found, the global namespace is searched
+        elif relativeImportIndex < 0:
+            parent = self._DetermineParent(caller)
+            while parent is not None:
+                fullName = "%s.%s" % (parent.name, name)
+                module, returnError = self._InternalImportModule(fullName,
+                        deferredImports)
+                if module is not None:
+                    parent.globalNames[name] = None
+                    return module
+                parent = self._GetParentByName(parent.name)
+            module, returnError = self._InternalImportModule(name,
+                    deferredImports)
+
+        # new style relative import (available in Python 2.5 and up)
+        # the index indicates how many levels to traverse and only that level
+        # is searched for the named module
+        elif relativeImportIndex > 0:
+            parent = caller
+            if parent.path is not None:
+                relativeImportIndex -= 1
+            while parent is not None and relativeImportIndex > 0:
+                parent = self._GetParentByName(parent.name)
+                relativeImportIndex -= 1
+            if parent is None:
+                module = None
+                returnError = True
+            elif not name:
+                module = parent
+            else:
+                name = "%s.%s" % (parent.name, name)
+                module, returnError = self._InternalImportModule(name,
+                        deferredImports)
+
+        # if module not found, track that fact
+        if module is None:
+            if caller is None:
+                raise ImportError, "No module named %s" % name
+            if returnError and name not in caller.ignoreNames:
+                callers = self._badModules.setdefault(name, {})
+                callers[caller.name] = None
+
+        return module
+
+    def _InternalImportModule(self, name, deferredImports):
+        """Internal method used for importing a module which assumes that the
+           name given is an absolute name. None is returned if the module
+           cannot be found."""
+        try:
+            return self._modules[name], False
+        except KeyError:
+            pass
+        if name in self._builtinModules:
+            return self._AddModule(name), False
+        pos = name.rfind(".")
+        if pos < 0:
+            path = self.path
+            searchName = name
+            parentModule = None
+        else:
+            parentName = name[:pos]
+            parentModule, returnError = \
+                    self._InternalImportModule(parentName, deferredImports)
+            if parentModule is None:
+                return None, returnError
+            path = parentModule.path
+            searchName = name[pos + 1:]
+        if name in self.aliases:
+            actualName = self.aliases[name]
+            module, returnError = \
+                    self._InternalImportModule(actualName, deferredImports)
+            self._modules[name] = module
+            return module, returnError
+        try:
+            fp, path, info = imp.find_module(searchName, path)
+        except ImportError:
+            self._modules[name] = None
+            return None, True
+        module = self._LoadModule(name, fp, path, info, deferredImports,
+                parentModule)
+        return module, False
+
+    def _LoadModule(self, name, fp, path, info, deferredImports,
+            parent = None):
+        """Load the module, given the information acquired by the finder."""
+        suffix, mode, type = info
+        if type == imp.PKG_DIRECTORY:
+            return self._LoadPackage(name, path, parent, deferredImports)
+        module = self._AddModule(name)
+        module.file = path
+        module.parent = parent
+        if type == imp.PY_SOURCE:
+            module.code = compile(fp.read() + "\n", path, "exec")
+        elif type == imp.PY_COMPILED:
+            if fp.read(4) != imp.get_magic():
+                raise ImportError, "Bad magic number in %s" % path
+            fp.read(4)
+            module.code = marshal.load(fp)
+        self._RunHook(module)
+        if module.code is not None:
+            if self.replacePaths:
+                topLevelModule = module
+                while topLevelModule.parent is not None:
+                    topLevelModule = topLevelModule.parent
+                module.code = self._ReplacePathsInCode(topLevelModule,
+                        module.code)
+            self._ScanCode(module.code, module, deferredImports)
+        return module
+
+    def _LoadPackage(self, name, path, parent, deferredImports):
+        """Load the package, given its name and path."""
+        module = self._AddModule(name)
+        module.path = [path]
+        fp, path, info = imp.find_module("__init__", module.path)
+        self._LoadModule(name, fp, path, info, deferredImports, parent)
+        return module
+
+    def _ReplacePathsInCode(self, topLevelModule, co):
+        """Replace paths in the code as directed, returning a new code object
+           with the modified paths in place."""
+        origFileName = newFileName = os.path.normpath(co.co_filename)
+        for searchValue, replaceValue in self.replacePaths:
+            if searchValue == "*":
+                searchValue = os.path.dirname(topLevelModule.file)
+                if topLevelModule.path:
+                    searchValue = os.path.dirname(searchValue)
+                if searchValue:
+                    searchValue = searchValue + os.pathsep
+            elif not origFileName.startswith(searchValue):
+                continue
+            newFileName = replaceValue + origFileName[len(searchValue):]
+            break
+        constants = list(co.co_consts)
+        for i, value in enumerate(constants):
+            if isinstance(value, type(co)):
+                constants[i] = self._ReplacePathsInCode(topLevelModule, value)
+        return new.code(co.co_argcount, co.co_nlocals, co.co_stacksize,
+                co.co_flags, co.co_code, tuple(constants), co.co_names,
+                co.co_varnames, newFileName, co.co_name, co.co_firstlineno,
+                co.co_lnotab, co.co_freevars, co.co_cellvars)
+
+    def _RunHook(self, module):
+        """Run hook for the given module if one is present."""
+        name = "load_%s" % module.name.replace(".", "_")
+        method = getattr(cx_Freeze.hooks, name, None)
+        if method is not None:
+            method(self, module)
+
+    def _ScanCode(self, co, module, deferredImports):
+        """Scan code, looking for imported modules and keeping track of the
+           constants that have been created in order to better tell which
+           modules are truly missing."""
+        opIndex = 0
+        arguments = []
+        code = co.co_code
+        numOps = len(code)
+        while opIndex < numOps:
+            op = ord(code[opIndex])
+            opIndex += 1
+            if op >= dis.HAVE_ARGUMENT:
+                opArg = ord(code[opIndex]) + ord(code[opIndex + 1]) * 256
+                opIndex += 2
+            if op == LOAD_CONST:
+                arguments.append(co.co_consts[opArg])
+            elif op == IMPORT_NAME:
+                name = co.co_names[opArg]
+                if len(arguments) == 2:
+                    relativeImportIndex, fromList = arguments
+                else:
+                    relativeImportIndex = -1
+                    fromList, = arguments
+                if name not in module.excludeNames:
+                    subModule = self._ImportModule(name, deferredImports,
+                            module, relativeImportIndex)
+                    if subModule is not None:
+                        module.globalNames.update(subModule.globalNames)
+                        if fromList and subModule.path is not None:
+                            self._EnsureFromList(module, subModule, fromList,
+                                    deferredImports)
+            else:
+                arguments = []
+                if op in STORE_OPS:
+                    name = co.co_names[opArg]
+                    module.globalNames[name] = None
+        for constant in co.co_consts:
+            if isinstance(constant, type(co)):
+                self._ScanCode(constant, module, deferredImports)
+
+    def AddAlias(self, name, aliasFor):
+        """Add an alias for a particular module; when an attempt is made to
+           import a module using the alias name, import the actual name
+           instead."""
+        self.aliases[name] = aliasFor
+
+    def ExcludeModule(self, name):
+        """Exclude the named module from the resulting frozen executable."""
+        self.excludes[name] = None
+        self._modules[name] = None
+
+    def IncludeFile(self, path, moduleName = None):
+        """Include the named file as a module in the frozen executable."""
+        name, ext = os.path.splitext(os.path.basename(path))
+        if moduleName is None:
+            moduleName = name
+        info = (ext, "r", imp.PY_SOURCE)
+        deferredImports = []
+        module = self._LoadModule(moduleName, file(path, "U"), path, info,
+                deferredImports)
+        self._ImportDeferredImports(deferredImports)
+        return module
+
+    def IncludeModule(self, name):
+        """Include the named module in the frozen executable."""
+        deferredImports = []
+        module = self._ImportModule(name, deferredImports)
+        self._ImportDeferredImports(deferredImports)
+        return module
+
+    def IncludePackage(self, name):
+        """Include the named package and any submodules in the frozen
+           executable."""
+        deferredImports = []
+        module = self._ImportModule(name, deferredImports)
+        if module.path:
+            self._ImportAllSubModules(module, deferredImports)
+        self._ImportDeferredImports(deferredImports)
+        return module
+
+    def ReportMissingModules(self):
+        if self._badModules:
+            print "Missing modules:"
+            names = self._badModules.keys()
+            names.sort()
+            for name in names:
+                callers = self._badModules[name].keys()
+                callers.sort()
+                print "?", name, "imported from", ", ".join(callers)
+            print
+
+
+class Module(object):
+
+    def __init__(self, name):
+        self.name = name
+        self.file = None
+        self.path = None
+        self.code = None
+        self.parent = None
+        self.globalNames = {}
+        self.excludeNames = {}
+        self.ignoreNames = {}
+
+    def __repr__(self):
+        parts = ["name=%s" % repr(self.name)]
+        if self.file is not None:
+            parts.append("file=%s" % repr(self.file))
+        if self.path is not None:
+            parts.append("path=%s" % repr(self.path))
+        return "<Module %s>" % ", ".join(parts)
+
+    def AddGlobalName(self, name):
+        self.globalNames[name] = None
+
+    def ExcludeName(self, name):
+        self.excludeNames[name] = None
+
+    def IgnoreName(self, name):
+        self.ignoreNames[name] = None
+

cx_Freeze/freezer.py

+"""
+Base class for freezing scripts into executables.
+"""
+
+import datetime
+import distutils.sysconfig
+import imp
+import marshal
+import os
+import shutil
+import socket
+import stat
+import struct
+import sys
+import time
+import zipfile
+
+import cx_Freeze
+import cx_Freeze.util
+
+__all__ = [ "ConfigError", "ConstantsModule", "Executable", "Freezer" ]
+
+if sys.platform == "win32":
+    pythonDll = "python%s%s.dll" % sys.version_info[:2]
+    GLOBAL_BIN_PATH_EXCLUDES = [cx_Freeze.util.GetSystemDir().lower()]
+    GLOBAL_BIN_INCLUDES = [
+            pythonDll,
+            "gdiplus.dll",
+            "mfc71.dll",
+            "msvcp71.dll",
+            "msvcr71.dll"
+    ]
+    GLOBAL_BIN_EXCLUDES = [
+            "oci.dll"
+    ]
+else:
+    extension = distutils.sysconfig.get_config_var("SO")
+    pythonSharedLib = "libpython%s.%s%s" % \
+            (sys.version_info[:2] + (extension,))
+    GLOBAL_BIN_INCLUDES = [pythonSharedLib]
+    GLOBAL_BIN_EXCLUDES = [
+            "libclntsh.so",
+            "libwtc9.so"
+    ]
+    GLOBAL_BIN_PATH_EXCLUDES = ["/lib", "/usr/lib"]
+
+
+# NOTE: the try: except: block in this code is not necessary under Python 2.4
+# and higher and can be removed once support for Python 2.3 is no longer needed
+EXTENSION_LOADER_SOURCE = \
+"""
+import imp, os, sys
+
+found = False
+for p in sys.path:
+    if not os.path.isdir(p):
+        continue
+    f = os.path.join(p, "%s")
+    if not os.path.exists(f):
+        continue
+    try:
+        m = imp.load_dynamic(__name__, f)
+    except ImportError:
+        del sys.modules[__name__]
+        raise
+    sys.modules[__name__] = m
+    found = True
+    break
+if not found:
+    del sys.modules[__name__]
+    raise ImportError, "No module named %%s" %% __name__
+"""
+
+
+class Freezer(object):
+
+    def __init__(self, executables, constantsModules = [], includes = [],
+            excludes = [], packages = [], replacePaths = [], compress = None,
+            optimizeFlag = 0, copyDependentFiles = None, initScript = None,
+            base = None, path = None, createLibraryZip = None,
+            appendScriptToExe = None, appendScriptToLibrary = None,
+            targetDir = None, binIncludes = [], binExcludes = [],
+            binPathExcludes = [], icon = None):
+        self.executables = executables
+        self.constantsModules = constantsModules
+        self.includes = includes
+        self.excludes = excludes
+        self.packages = packages
+        self.replacePaths = replacePaths
+        self.compress = compress
+        self.optimizeFlag = optimizeFlag
+        self.copyDependentFiles = copyDependentFiles
+        self.initScript = initScript
+        self.base = base
+        self.path = path
+        self.createLibraryZip = createLibraryZip
+        self.appendScriptToExe = appendScriptToExe
+        self.appendScriptToLibrary = appendScriptToLibrary
+        self.targetDir = targetDir
+        self.binIncludes = dict.fromkeys(GLOBAL_BIN_INCLUDES)
+        for name in binIncludes:
+            self.binIncludes[name.lower()] = None
+        self.binExcludes = dict.fromkeys(GLOBAL_BIN_EXCLUDES)
+        for name in binExcludes:
+            self.binExcludes[name.lower()] = None
+        self.binPathExcludes = dict.fromkeys(GLOBAL_BIN_PATH_EXCLUDES)
+        for name in binPathExcludes:
+            self.binPathExcludes[name.lower()] = None
+        self.icon = icon
+        self._VerifyConfiguration()
+
+    def _CopyFile(self, source, target, copyDependentFiles,
+            includeMode = False):
+        normalizedSource = os.path.normcase(os.path.normpath(source))
+        normalizedTarget = os.path.normcase(os.path.normpath(target))
+        if normalizedTarget in self.filesCopied:
+            return
+        if normalizedSource == normalizedTarget:
+            return
+        self._RemoveFile(target)
+        targetDir = os.path.dirname(target)
+        self._CreateDirectory(targetDir)
+        print "copying", source, "->", target
+        shutil.copyfile(source, target)
+        if includeMode:
+            shutil.copymode(source, target)
+        self.filesCopied[normalizedTarget] = None
+        if copyDependentFiles:
+            for source in self._GetDependentFiles(source):
+                target = os.path.join(targetDir, os.path.basename(source))
+                self._CopyFile(source, target, copyDependentFiles)
+
+    def _CreateDirectory(self, path):
+        if not os.path.isdir(path):
+            print "creating directory", path
+            os.makedirs(path)
+
+    def _FreezeExecutable(self, exe):
+        if self.createLibraryZip:
+            finder = self.finder
+        else:
+            finder = self._GetModuleFinder(exe)
+        if exe.script is None:
+            scriptModule = None
+        else:
+            scriptModule = finder.IncludeFile(exe.script, exe.moduleName)
+        self._CopyFile(exe.base, exe.targetName, exe.copyDependentFiles,
+                includeMode = True)
+        if exe.icon is not None:
+            if sys.platform == "win32":
+                cx_Freeze.util.AddIcon(exe.targetName, exe.icon)
+            else:
+                targetName = os.path.join(os.path.dirname(exe.targetName),
+                        os.path.basename(exe.icon))
+                self._CopyFile(exe.icon, targetName,
+                        copyDependentFiles = False)
+        if not os.access(exe.targetName, os.W_OK):
+            mode = os.stat(exe.targetName).st_mode
+            os.chmod(exe.targetName, mode | stat.S_IWUSR)
+        if not exe.appendScriptToLibrary:
+            if exe.appendScriptToExe:
+                fileName = exe.targetName
+            else:
+                baseFileName, ext = os.path.splitext(exe.targetName)
+                fileName = baseFileName + ".zip"
+                self._RemoveFile(fileName)
+            if not self.createLibraryZip and exe.copyDependentFiles:
+                scriptModule = None
+            self._WriteModules(fileName, exe.initScript, finder, exe.compress,
+                    exe.copyDependentFiles, scriptModule)
+
+    def _GetBaseFileName(self, argsSource = None):
+        if argsSource is None:
+            argsSource = self
+        name = argsSource.base
+        if name is None:
+            if argsSource.copyDependentFiles:
+                name = "Console"
+            else:
+                name = "ConsoleKeepPath"
+        argsSource.base = self._GetFileName("bases", name)
+        if argsSource.base is None:
+            raise ConfigError("no base named %s", name)
+
+    def _GetDependentFiles(self, path):
+        dependentFiles = self.dependentFiles.get(path)
+        if dependentFiles is None:
+            if sys.platform == "win32":
+                origPath = os.environ["PATH"]
+                os.environ["PATH"] = origPath + os.pathsep + \
+                        os.pathsep.join(sys.path)
+                dependentFiles = cx_Freeze.util.GetDependentFiles(path)
+                os.environ["PATH"] = origPath
+            else:
+                dependentFiles = []
+                for line in os.popen('ldd "%s"' % path):
+                    parts = line.strip().split(" => ")
+                    if len(parts) != 2:
+                        continue
+                    dependentFile = parts[1]
+                    pos = dependentFile.find(" (")
+                    if pos >= 0:
+                        dependentFile = dependentFile[:pos].strip()
+                    if dependentFile:
+                        dependentFiles.append(dependentFile)
+            dependentFiles = self.dependentFiles[path] = \
+                    [f for f in dependentFiles if self._ShouldCopyFile(f)]
+        return dependentFiles
+
+    def _GetFileName(self, dir, name):
+        if os.path.isabs(name):
+            return name
+        name = name.lower()
+        fullDir = os.path.join(os.path.dirname(cx_Freeze.__file__), dir)
+        if os.path.isdir(fullDir):
+            for fileName in os.listdir(fullDir):
+                if name == os.path.splitext(fileName.lower())[0]:
+                    return os.path.join(fullDir, fileName)
+
+    def _GetInitScriptFileName(self, argsSource = None):
+        if argsSource is None:
+            argsSource = self
+        name = argsSource.initScript
+        if name is None:
+            if argsSource.copyDependentFiles:
+                name = "Console"
+            else:
+                name = "ConsoleKeepPath"
+        argsSource.initScript = self._GetFileName("initscripts", name)
+        if argsSource.initScript is None:
+            raise ConfigError("no initscript named %s", name)
+
+    def _GetModuleFinder(self, argsSource = None):
+        if argsSource is None:
+            argsSource = self
+        finder = cx_Freeze.ModuleFinder(argsSource.excludes, argsSource.path,
+                argsSource.replacePaths)
+        if argsSource.copyDependentFiles:
+            finder.IncludeModule("imp")
+            finder.IncludeModule("os")
+            finder.IncludeModule("sys")
+            if argsSource.compress:
+                finder.IncludeModule("zlib")
+        for name in argsSource.includes:
+            finder.IncludeModule(name)
+        for name in argsSource.packages:
+            finder.IncludePackage(name)
+        return finder
+
+    def _PrintReport(self, fileName, modules):
+        print "writing zip file", fileName
+        print
+        print "  %-25s %s" % ("Name", "File")
+        print "  %-25s %s" % ("----", "----")
+        for module in modules:
+            if module.path:
+                print "P",
+            else:
+                print "m",
+            print "%-25s" % module.name, module.file or ""
+        print
+
+    def _RemoveFile(self, path):
+        if os.path.exists(path):
+            os.chmod(path, 0777)
+            os.remove(path)
+
+    def _ShouldCopyFile(self, path):
+        dir, name = os.path.split(os.path.normcase(path))
+        parts = name.split(".")
+        tweaked = False
+        while True:
+            if not parts[-1].isdigit():
+                break
+            parts.pop(-1)
+            tweaked = True
+        if tweaked:
+            name = ".".join(parts)
+        if name in self.binIncludes:
+            return True
+        if name in self.binExcludes:
+            return False
+        if dir in self.binPathExcludes:
+            return False
+        return True
+
+    def _VerifyCanAppendToLibrary(self):
+        if not self.createLibraryZip:
+            raise ConfigError("script cannot be appended to library zip if "
+                    "one is not being created")
+
+    def _VerifyConfiguration(self):
+        if self.compress is None:
+            self.compress = True
+        if self.copyDependentFiles is None:
+            self.copyDependentFiles = True
+        if self.createLibraryZip is None:
+            self.createLibraryZip = True
+        if self.appendScriptToExe is None:
+            self.appendScriptToExe = False
+        if self.appendScriptToLibrary is None:
+            self.appendScriptToLibrary = \
+                    self.createLibraryZip and not self.appendScriptToExe
+        if self.targetDir is None:
+            self.targetDir = os.path.abspath("dist")
+        self._GetInitScriptFileName()
+        self._GetBaseFileName()
+        if self.path is None:
+            self.path = sys.path
+        if self.appendScriptToLibrary:
+            self._VerifyCanAppendToLibrary()
+        for executable in self.executables:
+            executable._VerifyConfiguration(self)
+
+    def _WriteModules(self, fileName, initScript, finder, compress,
+            copyDependentFiles, scriptModule = None):
+        initModule = finder.IncludeFile(initScript, "cx_Freeze__init__")
+        if scriptModule is None:
+            for module in self.constantsModules:
+                module.Create(finder)
+            modules = [m for m in finder.modules \
+                    if m.name not in self.excludeModules]
+        else:
+            modules = [initModule, scriptModule]
+            self.excludeModules[initModule.name] = None
+            self.excludeModules[scriptModule.name] = None
+        itemsToSort = [(m.name, m) for m in modules]
+        itemsToSort.sort()
+        modules = [m for n, m in itemsToSort]
+        self._PrintReport(fileName, modules)
+        if scriptModule is None:
+            finder.ReportMissingModules()
+        targetDir = os.path.dirname(fileName)
+        self._CreateDirectory(targetDir)
+        filesToCopy = []
+        if os.path.exists(fileName):
+            mode = "a"
+        else:
+            mode = "w"
+        outFile = zipfile.PyZipFile(fileName, mode, zipfile.ZIP_DEFLATED)
+        for module in modules:
+            if module.code is None and module.file is not None:
+                fileName = os.path.basename(module.file)
+                baseFileName, ext = os.path.splitext(fileName)
+                if baseFileName != module.name and module.name != "zlib":
+                    if "." in module.name:
+                        fileName = module.name + ext
+                    generatedFileName = "ExtensionLoader_%s.py" % \
+                            module.name.replace(".", "_")
+                    module.code = compile(EXTENSION_LOADER_SOURCE % fileName,
+                            generatedFileName, "exec")
+                target = os.path.join(targetDir, fileName)
+                filesToCopy.append((module, target))
+            if module.code is None:
+                continue
+            fileName = "/".join(module.name.split("."))
+            if module.path:
+                fileName += "/__init__"
+            if module.file is not None and os.path.exists(module.file):
+                mtime = os.stat(module.file).st_mtime
+            else:
+                mtime = time.time()
+            zipTime = time.localtime(mtime)[:6]
+            data = imp.get_magic() + struct.pack("<i", mtime) + \
+                    marshal.dumps(module.code)
+            zinfo = zipfile.ZipInfo(fileName + ".pyc", zipTime)
+            if compress:
+                zinfo.compress_type = zipfile.ZIP_DEFLATED
+            outFile.writestr(zinfo, data)
+        origPath = os.environ["PATH"]
+        for module, target in filesToCopy:
+            try:
+                if module.parent is not None:
+                    path = os.pathsep.join([origPath] + module.parent.path)
+                    os.environ["PATH"] = path
+                self._CopyFile(module.file, target, copyDependentFiles)
+            finally:
+                os.environ["PATH"] = origPath
+
+    def Freeze(self):
+        self.finder = None
+        self.excludeModules = {}
+        self.dependentFiles = {}
+        self.filesCopied = {}
+        cx_Freeze.util.SetOptimizeFlag(self.optimizeFlag)
+        if self.createLibraryZip:
+            self.finder = self._GetModuleFinder()
+        for executable in self.executables:
+            self._FreezeExecutable(executable)
+        if self.createLibraryZip:
+            fileName = os.path.join(self.targetDir, "library.zip")
+            self._RemoveFile(fileName)
+            self._WriteModules(fileName, self.initScript, self.finder,
+                    self.compress, self.copyDependentFiles)
+
+
+class ConfigError(Exception):
+
+    def __init__(self, format, *args):
+        self.what = format % args
+
+    def __str__(self):
+        return self.what
+
+
+class Executable(object):
+
+    def __init__(self, script, initScript = None, base = None, path = None,
+            targetDir = None, targetName = None, includes = None,
+            excludes = None, packages = None, replacePaths = None,
+            compress = None, copyDependentFiles = None,
+            appendScriptToExe = None, appendScriptToLibrary = None,
+            icon = None):
+        self.script = script
+        self.initScript = initScript
+        self.base = base
+        self.path = path