"""Base class for freezing scripts into executables."""importdatetimeimportdistutils.sysconfigimportimpimportmarshalimportosimportshutilimportsocketimportstatimportstructimportsysimporttimeimportzipfileimportcx_Freeze__all__=["ConfigError","ConstantsModule","Executable","Freezer"]EXTENSION_LOADER_SOURCE= \
"""import imp, os, sysfound = Falsefor p in sys.path: if not os.path.isdir(p): continue f = os.path.join(p, "%s") if not os.path.exists(f): continue m = imp.load_dynamic(__name__, f) import sys sys.modules[__name__] = m found = True breakif not found: del sys.modules[__name__] raise ImportError("No module named %%s" %% __name__)"""MSVCR_MANIFEST_TEMPLATE="""<?xml version="1.0" encoding="UTF-8" standalone="yes"?><assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"><noInheritable/><assemblyIdentity type="win32" name="Microsoft.VC90.CRT" version="9.0.21022.8" processorArchitecture="{PROC_ARCH}" publicKeyToken="1fc8b3b9a1e18e3b"/><file name="MSVCR90.DLL"/><file name="MSVCM90.DLL"/><file name="MSVCP90.DLL"/></assembly>"""classFreezer(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=[],binPathIncludes=[],binPathExcludes=[],icon=None,includeFiles=[],zipIncludes=[],silent=False,namespacePackages=[],metadata=None,includeMSVCR=False):self.executables=list(executables)self.constantsModules=list(constantsModules)self.includes=list(includes)self.excludes=list(excludes)self.packages=list(packages)self.namespacePackages=list(namespacePackages)self.replacePaths=list(replacePaths)self.compress=compressself.optimizeFlag=optimizeFlagself.copyDependentFiles=copyDependentFilesself.initScript=initScriptself.base=baseself.path=pathself.createLibraryZip=createLibraryZipself.includeMSVCR=includeMSVCRself.appendScriptToExe=appendScriptToExeself.appendScriptToLibrary=appendScriptToLibraryself.targetDir=targetDirself.binIncludes=[os.path.normcase(n) \
forninself._GetDefaultBinIncludes()+binIncludes]self.binExcludes=[os.path.normcase(n) \
forninself._GetDefaultBinExcludes()+binExcludes]self.binPathIncludes=[os.path.normcase(n)forninbinPathIncludes]self.binPathExcludes=[os.path.normcase(n) \
forninself._GetDefaultBinPathExcludes()+binPathExcludes]self.icon=iconself.includeFiles=list(includeFiles)self.includeFiles=self._ProcessPathSpecs(includeFiles)self.zipIncludes=self._ProcessPathSpecs(zipIncludes)self.silent=silentself.metadata=metadataself._VerifyConfiguration()def_AddVersionResource(self,fileName):try:fromwin32verstampimportstampexcept:print("*** WARNING *** unable to create version resource")print("install pywin32 extensions first")returnversionInfo=VersionInfo(self.metadata.version,comments=self.metadata.long_description,description=self.metadata.description,company=self.metadata.author,product=self.metadata.name)stamp(fileName,versionInfo)def_CopyFile(self,source,target,copyDependentFiles=False,includeMode=False):normalizedSource=os.path.normcase(os.path.normpath(source))normalizedTarget=os.path.normcase(os.path.normpath(target))ifnormalizedTargetinself.filesCopied:returnifnormalizedSource==normalizedTarget:returnself._RemoveFile(target)targetDir=os.path.dirname(target)self._CreateDirectory(targetDir)ifnotself.silent:sys.stdout.write("copying %s -> %s\n"%(source,target))shutil.copyfile(source,target)shutil.copystat(source,target)ifincludeMode:shutil.copymode(source,target)self.filesCopied[normalizedTarget]=NoneifcopyDependentFiles:forsourceinself._GetDependentFiles(source):target=os.path.join(targetDir,os.path.basename(source))self._CopyFile(source,target,copyDependentFiles)def_CreateDirectory(self,path):ifnotos.path.isdir(path):ifnotself.silent:sys.stdout.write("creating directory %s\n"%path)os.makedirs(path)def_FreezeExecutable(self,exe):ifself.createLibraryZip:finder=self.finderelse:finder=self._GetModuleFinder(exe)ifexe.scriptisNone:scriptModule=Noneelse:scriptModule=finder.IncludeFile(exe.script,exe.moduleName)self._CopyFile(exe.base,exe.targetName,exe.copyDependentFiles,includeMode=True)ifself.includeMSVCR:self._IncludeMSVCR(exe)ifexe.iconisnotNone:ifsys.platform=="win32":importcx_Freeze.utilcx_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)ifnotos.access(exe.targetName,os.W_OK):mode=os.stat(exe.targetName).st_modeos.chmod(exe.targetName,mode|stat.S_IWUSR)ifself.metadataisnotNoneandsys.platform=="win32":self._AddVersionResource(exe.targetName)ifnotexe.appendScriptToLibrary:ifexe.appendScriptToExe:fileName=exe.targetNameelse:baseFileName,ext=os.path.splitext(exe.targetName)fileName=baseFileName+".zip"self._RemoveFile(fileName)ifnotself.createLibraryZipandexe.copyDependentFiles:scriptModule=Noneself._WriteModules(fileName,exe.initScript,finder,exe.compress,exe.copyDependentFiles,scriptModule)def_GetBaseFileName(self,argsSource=None):ifargsSourceisNone:argsSource=selfname=argsSource.baseifnameisNone:ifargsSource.copyDependentFiles:name="Console"else:name="ConsoleKeepPath"argsSource.base=self._GetFileName("bases",name)ifargsSource.baseisNone:raiseConfigError("no base named %s",name)def_GetDefaultBinExcludes(self):"""Return the file names of libraries that need not be included because they would normally be expected to be found on the target system or because they are part of a package which requires independent installation anyway."""ifsys.platform=="win32":return["comctl32.dll","oci.dll","cx_Logging.pyd"]else:return["libclntsh.so","libwtc9.so"]def_GetDefaultBinIncludes(self):"""Return the file names of libraries which must be included for the frozen executable to work."""ifsys.platform=="win32":pythonDll="python%s%s.dll"%sys.version_info[:2]return[pythonDll,"gdiplus.dll","mfc71.dll","msvcp71.dll","msvcr71.dll"]else:soName=distutils.sysconfig.get_config_var("INSTSONAME")ifsoNameisNone:return[]pythonSharedLib=self._RemoveVersionNumbers(soName)return[pythonSharedLib]def_GetDefaultBinPathExcludes(self):"""Return the paths of directories which contain files that should not be included, generally because they contain standard system libraries."""ifsys.platform=="win32":importcx_Freeze.utilsystemDir=cx_Freeze.util.GetSystemDir()windowsDir=cx_Freeze.util.GetWindowsDir()return[windowsDir,systemDir,os.path.join(windowsDir,"WinSxS")]elifsys.platform=="darwin":return["/lib","/usr/lib","/System/Library/Frameworks"]else:return["/lib","/lib32","/lib64","/usr/lib","/usr/lib32","/usr/lib64"]def_GetDependentFiles(self,path):"""Return the file's dependencies using platform-specific tools (the imagehlp library on Windows, otool on Mac OS X and ldd on Linux); limit this list by the exclusion lists as needed"""dependentFiles=self.dependentFiles.get(path)ifdependentFilesisNone:ifsys.platform=="win32":origPath=os.environ["PATH"]os.environ["PATH"]=origPath+os.pathsep+ \
os.pathsep.join(sys.path)importcx_Freeze.utildependentFiles=cx_Freeze.util.GetDependentFiles(path)os.environ["PATH"]=origPathelse:dependentFiles=[]ifsys.platform=="darwin":command='otool -L "%s"'%pathsplitString=" (compatibility"dependentFileIndex=0else:command='ldd "%s"'%pathsplitString=" => "dependentFileIndex=1forlineinos.popen(command):parts=line.expandtabs().strip().split(splitString)iflen(parts)!=2:continuedependentFile=parts[dependentFileIndex].strip()ifdependentFilein("not found","(file not found)"):fileName=parts[0]iffileNamenotinself.linkerWarnings:self.linkerWarnings[fileName]=Nonemessage="WARNING: cannot find %s\n"%fileNamesys.stdout.write(message)continueifdependentFile.startswith("("):continuepos=dependentFile.find(" (")ifpos>=0:dependentFile=dependentFile[:pos].strip()ifdependentFile:dependentFiles.append(dependentFile)dependentFiles=self.dependentFiles[path]= \
[fforfindependentFilesifself._ShouldCopyFile(f)]returndependentFilesdef_GetFileName(self,dir,name,ext=None):ifos.path.isabs(name):returnnamename=os.path.normcase(name)fullDir=os.path.join(os.path.dirname(cx_Freeze.__file__),dir)ifos.path.isdir(fullDir):forfileNameinos.listdir(fullDir):checkName,checkExt= \
os.path.splitext(os.path.normcase(fileName))ifname==checkNameand(extisNoneorext==checkExt):returnos.path.join(fullDir,fileName)def_GetInitScriptFileName(self,argsSource=None):ifargsSourceisNone:argsSource=selfname=argsSource.initScriptifnameisNone:ifargsSource.copyDependentFiles:name="Console"else:name="ConsoleKeepPath"ifsys.version_info[0]>=3:name+="3"argsSource.initScript=self._GetFileName("initscripts",name,".py")ifargsSource.initScriptisNone:raiseConfigError("no initscript named %s",name)def_GetModuleFinder(self,argsSource=None):ifargsSourceisNone:argsSource=selffinder=cx_Freeze.ModuleFinder(self.includeFiles,argsSource.excludes,argsSource.path,argsSource.replacePaths,argsSource.copyDependentFiles,compress=argsSource.compress)fornameinargsSource.namespacePackages:package=finder.IncludeModule(name,namespace=True)package.ExtendPath()fornameinargsSource.includes:finder.IncludeModule(name)fornameinargsSource.packages:finder.IncludePackage(name)returnfinderdef_IncludeMSVCR(self,exe):msvcRuntimeDll=NonetargetDir=os.path.dirname(exe.targetName)forfullNameinself.filesCopied:path,name=os.path.split(os.path.normcase(fullName))ifname.startswith("msvcr")andname.endswith(".dll"):msvcRuntimeDll=nameforotherNamein[name.replace("r",c)forcin"mp"]:sourceName=os.path.join(self.msvcRuntimeDir,otherName)ifnotos.path.exists(sourceName):continuetargetName=os.path.join(targetDir,otherName)self._CopyFile(sourceName,targetName)breakifmsvcRuntimeDllisnotNoneandmsvcRuntimeDll=="msvcr90.dll":arch="x86"ifstruct.calcsize("P")==4else"amd64"manifest=MSVCR_MANIFEST_TEMPLATE.strip().replace("{PROC_ARCH}",arch)fileName=os.path.join(targetDir,"Microsoft.VC90.CRT.manifest")sys.stdout.write("creating %s\n"%fileName)open(fileName,"w").write(manifest)def_PrintReport(self,fileName,modules):sys.stdout.write("writing zip file %s\n\n"%fileName)sys.stdout.write(" %-25s%s\n"%("Name","File"))sys.stdout.write(" %-25s%s\n"%("----","----"))formoduleinmodules:ifmodule.path:sys.stdout.write("P")else:sys.stdout.write("m")sys.stdout.write(" %-25s%s\n"%(module.name,module.fileor""))sys.stdout.write("\n")def_ProcessPathSpecs(self,specs):processedSpecs=[]forspecinspecs:ifnotisinstance(spec,(list,tuple)):source=target=speceliflen(spec)!=2:raiseConfigError("path spec must be a list or tuple of ""length two")else:source,target=specsource=os.path.normpath(source)ifnottarget:dirName,target=os.path.split(source)elifos.path.isabs(target):raiseConfigError("target path for include file may not be ""an absolute path")processedSpecs.append((source,target))returnprocessedSpecsdef_RemoveFile(self,path):ifos.path.exists(path):os.chmod(path,stat.S_IWRITE)os.remove(path)def_RemoveVersionNumbers(self,libName):tweaked=Falseparts=libName.split(".")whileparts:ifnotparts[-1].isdigit():breakparts.pop(-1)tweaked=Trueiftweaked:libName=".".join(parts)returnlibNamedef_ShouldCopyFile(self,path):"""Return true if the file should be copied to the target machine. This is done by checking the binPathIncludes, binPathExcludes, binIncludes and binExcludes configuration variables using first the full file name, then just the base file name, then the file name without any version numbers. Files are included unless specifically excluded but inclusions take precedence over exclusions."""# check for C runtime, if desiredpath=os.path.normcase(path)dirName,fileName=os.path.split(path)iffileName.startswith("msvcr")andfileName.endswith(".dll"):self.msvcRuntimeDir=dirNamereturnself.includeMSVCR# check the full pathifpathinself.binIncludes:returnTrueifpathinself.binExcludes:returnFalse# check the file name by itself (with any included version numbers)iffileNameinself.binIncludes:returnTrueiffileNameinself.binExcludes:returnFalse# check the file name by itself (version numbers removed)name=self._RemoveVersionNumbers(fileName)ifnameinself.binIncludes:returnTrueifnameinself.binExcludes:returnFalse# check the path for inclusion/exclusionforpathinself.binPathIncludes:ifdirName.startswith(path):returnTrueforpathinself.binPathExcludes:ifdirName.startswith(path):returnFalsereturnTruedef_VerifyCanAppendToLibrary(self):ifnotself.createLibraryZip:raiseConfigError("script cannot be appended to library zip if ""one is not being created")def_VerifyConfiguration(self):ifself.compressisNone:self.compress=Trueifself.copyDependentFilesisNone:self.copyDependentFiles=Trueifself.createLibraryZipisNone:self.createLibraryZip=Trueifself.appendScriptToExeisNone:self.appendScriptToExe=Falseifself.appendScriptToLibraryisNone:self.appendScriptToLibrary= \
self.createLibraryZipandnotself.appendScriptToExeifself.targetDirisNone:self.targetDir=os.path.abspath("dist")self._GetInitScriptFileName()self._GetBaseFileName()ifself.pathisNone:self.path=sys.pathifself.appendScriptToLibrary:self._VerifyCanAppendToLibrary()forsourceFileName,targetFileNamein \
self.includeFiles+self.zipIncludes:ifnotos.path.exists(sourceFileName):raiseConfigError("cannot find file/directory named %s",sourceFileName)ifos.path.isabs(targetFileName):raiseConfigError("target file/directory cannot be absolute")forexecutableinself.executables:executable._VerifyConfiguration(self)def_WriteModules(self,fileName,initScript,finder,compress,copyDependentFiles,scriptModule=None):initModule=finder.IncludeFile(initScript,"cx_Freeze__init__")ifscriptModuleisNone:formoduleinself.constantsModules:module.Create(finder)modules=[mforminfinder.modules \
ifm.namenotinself.excludeModules]else:modules=[initModule,scriptModule]self.excludeModules[initModule.name]=Noneself.excludeModules[scriptModule.name]=NoneitemsToSort=[(m.name,m)forminmodules]itemsToSort.sort()modules=[mforn,minitemsToSort]ifnotself.silent:self._PrintReport(fileName,modules)ifscriptModuleisNone:finder.ReportMissingModules()targetDir=os.path.dirname(fileName)self._CreateDirectory(targetDir)filesToCopy=[]ifos.path.exists(fileName):mode="a"else:mode="w"outFile=zipfile.PyZipFile(fileName,mode,zipfile.ZIP_DEFLATED)formoduleinmodules:ifmodule.codeisNoneandmodule.fileisnotNone:fileName=os.path.basename(module.file)baseFileName,ext=os.path.splitext(fileName)ifbaseFileName!=module.nameandmodule.name!="zlib":if"."inmodule.name:fileName=module.name+extgeneratedFileName="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))ifmodule.codeisNone:continuefileName="/".join(module.name.split("."))ifmodule.path:fileName+="/__init__"ifmodule.fileisnotNoneandos.path.exists(module.file):mtime=os.stat(module.file).st_mtimeelse:mtime=time.time()zipTime=time.localtime(mtime)[:6]# starting with Python 3.3 the pyc file format contains the source# size; it is not actually used for anything except determining if# the file is up to date so we can safely set this value to zeroifsys.version_info[:2]<(3,3):header=imp.get_magic()+struct.pack("<i",int(mtime))else:header=imp.get_magic()+struct.pack("<ii",int(mtime),0)data=header+marshal.dumps(module.code)zinfo=zipfile.ZipInfo(fileName+".pyc",zipTime)ifcompress:zinfo.compress_type=zipfile.ZIP_DEFLATEDoutFile.writestr(zinfo,data)forsourceFileName,targetFileNameinself.zipIncludes:outFile.write(sourceFileName,targetFileName)outFile.close()origPath=os.environ["PATH"]formodule,targetinfilesToCopy:try:ifmodule.parentisnotNone:path=os.pathsep.join([origPath]+module.parent.path)os.environ["PATH"]=pathself._CopyFile(module.file,target,copyDependentFiles)finally:os.environ["PATH"]=origPathdefFreeze(self):self.finder=Noneself.excludeModules={}self.dependentFiles={}self.filesCopied={}self.linkerWarnings={}self.msvcRuntimeDir=Noneimportcx_Freeze.utilcx_Freeze.util.SetOptimizeFlag(self.optimizeFlag)ifself.createLibraryZip:self.finder=self._GetModuleFinder()forexecutableinself.executables:self._FreezeExecutable(executable)ifself.createLibraryZip:fileName=os.path.join(self.targetDir,"library.zip")self._RemoveFile(fileName)self._WriteModules(fileName,self.initScript,self.finder,self.compress,self.copyDependentFiles)forsourceFileName,targetFileNameinself.includeFiles:ifos.path.isdir(sourceFileName):forpath,dirNames,fileNamesinos.walk(sourceFileName):shortPath=path[len(sourceFileName)+1:]if".svn"indirNames:dirNames.remove(".svn")if"CVS"indirNames:dirNames.remove("CVS")fullTargetDir=os.path.join(self.targetDir,targetFileName,shortPath)self._CreateDirectory(fullTargetDir)forfileNameinfileNames:fullSourceName=os.path.join(path,fileName)fullTargetName=os.path.join(fullTargetDir,fileName)self._CopyFile(fullSourceName,fullTargetName,copyDependentFiles=False)else:fullName=os.path.join(self.targetDir,targetFileName)self._CopyFile(sourceFileName,fullName,copyDependentFiles=False)classConfigError(Exception):def__init__(self,format,*args):self.what=format%argsdef__str__(self):returnself.whatclassExecutable(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,namespacePackages=None,shortcutName=None,shortcutDir=None):self.script=scriptself.initScript=initScriptself.base=baseself.path=pathself.targetDir=targetDirself.targetName=targetNameself.includes=includesself.excludes=excludesself.packages=packagesself.namespacePackages=namespacePackagesself.replacePaths=replacePathsself.compress=compressself.copyDependentFiles=copyDependentFilesself.appendScriptToExe=appendScriptToExeself.appendScriptToLibrary=appendScriptToLibraryself.icon=iconself.shortcutName=shortcutNameself.shortcutDir=shortcutDirdef__repr__(self):return"<Executable script=%s>"%self.scriptdef_VerifyConfiguration(self,freezer):ifself.pathisNone:self.path=freezer.pathifself.targetDirisNone:self.targetDir=freezer.targetDirifself.includesisNone:self.includes=freezer.includesifself.excludesisNone:self.excludes=freezer.excludesifself.packagesisNone:self.packages=freezer.packagesifself.namespacePackagesisNone:self.namespacePackages=freezer.namespacePackagesifself.replacePathsisNone:self.replacePaths=freezer.replacePathsifself.compressisNone:self.compress=freezer.compressifself.copyDependentFilesisNone:self.copyDependentFiles=freezer.copyDependentFilesifself.appendScriptToExeisNone:self.appendScriptToExe=freezer.appendScriptToExeifself.appendScriptToLibraryisNone:self.appendScriptToLibrary=freezer.appendScriptToLibraryifself.initScriptisNone:self.initScript=freezer.initScriptelse:freezer._GetInitScriptFileName(self)ifself.baseisNone:self.base=freezer.baseelse:freezer._GetBaseFileName(self)ifself.appendScriptToLibrary:freezer._VerifyCanAppendToLibrary()ifself.iconisNone:self.icon=freezer.iconifself.targetNameisNone:name,ext=os.path.splitext(os.path.basename(self.script))baseName,ext=os.path.splitext(self.base)self.targetName=name+extifself.appendScriptToLibrary:name,ext=os.path.splitext(self.targetName)self.moduleName="%s__main__"%os.path.normcase(name)else:self.moduleName="__main__"self.targetName=os.path.join(self.targetDir,self.targetName)classConstantsModule(object):def__init__(self,releaseString=None,copyright=None,moduleName="BUILD_CONSTANTS",timeFormat="%B %d, %Y %H:%M:%S"):self.moduleName=moduleNameself.timeFormat=timeFormatself.values={}self.values["BUILD_RELEASE_STRING"]=releaseStringself.values["BUILD_COPYRIGHT"]=copyrightdefCreate(self,finder):"""Create the module which consists of declaration statements for each of the values."""today=datetime.datetime.today()sourceTimestamp=0formoduleinfinder.modules:ifmodule.fileisNone:continueifmodule.inZipFile:continueifnotos.path.exists(module.file):raiseConfigError("no file named %s (for module %s)",module.file,module.name)timestamp=os.stat(module.file).st_mtimesourceTimestamp=max(sourceTimestamp,timestamp)sourceTimestamp=datetime.datetime.fromtimestamp(sourceTimestamp)self.values["BUILD_TIMESTAMP"]=today.strftime(self.timeFormat)self.values["BUILD_HOST"]=socket.gethostname().split(".")[0]self.values["SOURCE_TIMESTAMP"]= \
sourceTimestamp.strftime(self.timeFormat)module=finder._AddModule(self.moduleName)sourceParts=[]names=list(self.values.keys())names.sort()fornameinnames:value=self.values[name]sourceParts.append("%s = %r"%(name,value))source="\n".join(sourceParts)module.code=compile(source,"%s.py"%self.moduleName,"exec")returnmoduleclassVersionInfo(object):def__init__(self,version,internalName=None,originalFileName=None,comments=None,company=None,description=None,copyright=None,trademarks=None,product=None,dll=False,debug=False,verbose=True):parts=version.split(".")whilelen(parts)<4:parts.append("0")self.version=".".join(parts)self.internal_name=internalNameself.original_filename=originalFileNameself.comments=commentsself.company=companyself.description=descriptionself.copyright=copyrightself.trademarks=trademarksself.product=productself.dll=dllself.debug=debugself.verbose=verbose