bdist_wininst.py (9950B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\carbon\common\stdlib\distutils\command\bdist_wininst.py 2 __revision__ = '$Id: bdist_wininst.py 87602 2011-01-01 04:24:26Z richard.tew $' 3 import sys 4 import os 5 import string 6 from sysconfig import get_python_version 7 from distutils.core import Command 8 from distutils.dir_util import remove_tree 9 from distutils.errors import DistutilsOptionError, DistutilsPlatformError 10 from distutils import log 11 from distutils.util import get_platform 12 13 class bdist_wininst(Command): 14 description = 'create an executable installer for MS Windows' 15 user_options = [('bdist-dir=', None, 'temporary directory for creating the distribution'), 16 ('plat-name=', 'p', 'platform name to embed in generated filenames (default: %s)' % get_platform()), 17 ('keep-temp', 'k', 'keep the pseudo-installation tree around after ' + 'creating the distribution archive'), 18 ('target-version=', None, 'require a specific python version' + ' on the target system'), 19 ('no-target-compile', 'c', 'do not compile .py to .pyc on the target system'), 20 ('no-target-optimize', 'o', 'do not compile .py to .pyo (optimized)on the target system'), 21 ('dist-dir=', 'd', 'directory to put final built distributions in'), 22 ('bitmap=', 'b', 'bitmap to use for the installer instead of python-powered logo'), 23 ('title=', 't', 'title to display on the installer background instead of default'), 24 ('skip-build', None, 'skip rebuilding everything (for testing/debugging)'), 25 ('install-script=', None, 'basename of installation script to be run afterinstallation or before deinstallation'), 26 ('pre-install-script=', None, 'Fully qualified filename of a script to be run before any files are installed. This script need not be in the distribution'), 27 ('user-access-control=', None, "specify Vista's UAC handling - 'none'/default=no handling, 'auto'=use UAC if target Python installed for all users, 'force'=always use UAC")] 28 boolean_options = ['keep-temp', 29 'no-target-compile', 30 'no-target-optimize', 31 'skip-build'] 32 33 def initialize_options(self): 34 self.bdist_dir = None 35 self.plat_name = None 36 self.keep_temp = 0 37 self.no_target_compile = 0 38 self.no_target_optimize = 0 39 self.target_version = None 40 self.dist_dir = None 41 self.bitmap = None 42 self.title = None 43 self.skip_build = 0 44 self.install_script = None 45 self.pre_install_script = None 46 self.user_access_control = None 47 48 def finalize_options(self): 49 if self.bdist_dir is None: 50 if self.skip_build and self.plat_name: 51 bdist = self.distribution.get_command_obj('bdist') 52 bdist.plat_name = self.plat_name 53 bdist_base = self.get_finalized_command('bdist').bdist_base 54 self.bdist_dir = os.path.join(bdist_base, 'wininst') 55 if not self.target_version: 56 self.target_version = '' 57 if not self.skip_build and self.distribution.has_ext_modules(): 58 short_version = get_python_version() 59 if self.target_version and self.target_version != short_version: 60 raise DistutilsOptionError, "target version can only be %s, or the '--skip-build' option must be specified" % (short_version,) 61 self.target_version = short_version 62 self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'), ('plat_name', 'plat_name')) 63 if self.install_script: 64 for script in self.distribution.scripts: 65 if self.install_script == os.path.basename(script): 66 break 67 else: 68 raise DistutilsOptionError, "install_script '%s' not found in scripts" % self.install_script 69 70 def run(self): 71 if sys.platform != 'win32' and (self.distribution.has_ext_modules() or self.distribution.has_c_libraries()): 72 raise DistutilsPlatformError('distribution contains extensions and/or C libraries; must be compiled on a Windows 32 platform') 73 if not self.skip_build: 74 self.run_command('build') 75 install = self.reinitialize_command('install', reinit_subcommands=1) 76 install.root = self.bdist_dir 77 install.skip_build = self.skip_build 78 install.warn_dir = 0 79 install.plat_name = self.plat_name 80 install_lib = self.reinitialize_command('install_lib') 81 install_lib.compile = 0 82 install_lib.optimize = 0 83 if self.distribution.has_ext_modules(): 84 target_version = self.target_version 85 if not target_version: 86 target_version = sys.version[0:3] 87 plat_specifier = '.%s-%s' % (self.plat_name, target_version) 88 build = self.get_finalized_command('build') 89 build.build_lib = os.path.join(build.build_base, 'lib' + plat_specifier) 90 for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'): 91 value = string.upper(key) 92 if key == 'headers': 93 value = value + '/Include/$dist_name' 94 setattr(install, 'install_' + key, value) 95 96 log.info('installing to %s', self.bdist_dir) 97 install.ensure_finalized() 98 sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB')) 99 install.run() 100 del sys.path[0] 101 from tempfile import mktemp 102 archive_basename = mktemp() 103 fullname = self.distribution.get_fullname() 104 arcname = self.make_archive(archive_basename, 'zip', root_dir=self.bdist_dir) 105 self.create_exe(arcname, fullname, self.bitmap) 106 if self.distribution.has_ext_modules(): 107 pyversion = get_python_version() 108 else: 109 pyversion = 'any' 110 self.distribution.dist_files.append(('bdist_wininst', pyversion, self.get_installer_filename(fullname))) 111 log.debug("removing temporary file '%s'", arcname) 112 os.remove(arcname) 113 if not self.keep_temp: 114 remove_tree(self.bdist_dir, dry_run=self.dry_run) 115 116 def get_inidata(self): 117 lines = [] 118 metadata = self.distribution.metadata 119 lines.append('[metadata]') 120 info = (metadata.long_description or '') + '\n' 121 122 def escape(s): 123 return string.replace(s, '\n', '\\n') 124 125 for name in ['author', 126 'author_email', 127 'description', 128 'maintainer', 129 'maintainer_email', 130 'name', 131 'url', 132 'version']: 133 data = getattr(metadata, name, '') 134 if data: 135 info = info + '\n %s: %s' % (string.capitalize(name), escape(data)) 136 lines.append('%s=%s' % (name, escape(data))) 137 138 lines.append('\n[Setup]') 139 if self.install_script: 140 lines.append('install_script=%s' % self.install_script) 141 lines.append('info=%s' % escape(info)) 142 lines.append('target_compile=%d' % (not self.no_target_compile)) 143 lines.append('target_optimize=%d' % (not self.no_target_optimize)) 144 if self.target_version: 145 lines.append('target_version=%s' % self.target_version) 146 if self.user_access_control: 147 lines.append('user_access_control=%s' % self.user_access_control) 148 title = self.title or self.distribution.get_fullname() 149 lines.append('title=%s' % escape(title)) 150 import time 151 import distutils 152 build_info = 'Built %s with distutils-%s' % (time.ctime(time.time()), distutils.__version__) 153 lines.append('build_info=%s' % build_info) 154 return string.join(lines, '\n') 155 156 def create_exe(self, arcname, fullname, bitmap = None): 157 import struct 158 self.mkpath(self.dist_dir) 159 cfgdata = self.get_inidata() 160 installer_name = self.get_installer_filename(fullname) 161 self.announce('creating %s' % installer_name) 162 if bitmap: 163 bitmapdata = open(bitmap, 'rb').read() 164 bitmaplen = len(bitmapdata) 165 else: 166 bitmaplen = 0 167 file = open(installer_name, 'wb') 168 file.write(self.get_exe_bytes()) 169 if bitmap: 170 file.write(bitmapdata) 171 try: 172 unicode 173 except NameError: 174 pass 175 else: 176 if isinstance(cfgdata, unicode): 177 cfgdata = cfgdata.encode('mbcs') 178 179 cfgdata = cfgdata + '\x00' 180 if self.pre_install_script: 181 script_data = open(self.pre_install_script, 'r').read() 182 cfgdata = cfgdata + script_data + '\n\x00' 183 else: 184 cfgdata = cfgdata + '\x00' 185 file.write(cfgdata) 186 header = struct.pack('<iii', 305419899, len(cfgdata), bitmaplen) 187 file.write(header) 188 file.write(open(arcname, 'rb').read()) 189 190 def get_installer_filename(self, fullname): 191 if self.target_version: 192 installer_name = os.path.join(self.dist_dir, '%s.%s-py%s.exe' % (fullname, self.plat_name, self.target_version)) 193 else: 194 installer_name = os.path.join(self.dist_dir, '%s.%s.exe' % (fullname, self.plat_name)) 195 return installer_name 196 197 def get_exe_bytes(self): 198 from distutils.msvccompiler import get_build_version 199 cur_version = get_python_version() 200 if self.target_version and self.target_version != cur_version: 201 if self.target_version > cur_version: 202 bv = get_build_version() 203 elif self.target_version < '2.4': 204 bv = 6.0 205 else: 206 bv = 7.1 207 else: 208 bv = get_build_version() 209 directory = os.path.dirname(__file__) 210 if self.plat_name != 'win32' and self.plat_name[:3] == 'win': 211 sfix = self.plat_name[3:] 212 else: 213 sfix = '' 214 filename = os.path.join(directory, 'wininst-%.1f%s.exe' % (bv, sfix)) 215 f = open(filename, 'rb') 216 try: 217 return f.read() 218 finally: 219 f.close()