symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/distutils/command/bdist_wininst.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 """distutils.command.bdist_wininst
       
     2 
       
     3 Implements the Distutils 'bdist_wininst' command: create a windows installer
       
     4 exe-program."""
       
     5 
       
     6 # This module should be kept compatible with Python 2.1.
       
     7 
       
     8 __revision__ = "$Id: bdist_wininst.py 63755 2008-05-28 01:54:55Z mark.hammond $"
       
     9 
       
    10 import sys, os, string
       
    11 from distutils.core import Command
       
    12 from distutils.util import get_platform
       
    13 from distutils.dir_util import create_tree, remove_tree
       
    14 from distutils.errors import *
       
    15 from distutils.sysconfig import get_python_version
       
    16 from distutils import log
       
    17 
       
    18 class bdist_wininst (Command):
       
    19 
       
    20     description = "create an executable installer for MS Windows"
       
    21 
       
    22     user_options = [('bdist-dir=', None,
       
    23                      "temporary directory for creating the distribution"),
       
    24                     ('plat-name=', 'p',
       
    25                      "platform name to embed in generated filenames "
       
    26                      "(default: %s)" % get_platform()),
       
    27                     ('keep-temp', 'k',
       
    28                      "keep the pseudo-installation tree around after " +
       
    29                      "creating the distribution archive"),
       
    30                     ('target-version=', None,
       
    31                      "require a specific python version" +
       
    32                      " on the target system"),
       
    33                     ('no-target-compile', 'c',
       
    34                      "do not compile .py to .pyc on the target system"),
       
    35                     ('no-target-optimize', 'o',
       
    36                      "do not compile .py to .pyo (optimized)"
       
    37                      "on the target system"),
       
    38                     ('dist-dir=', 'd',
       
    39                      "directory to put final built distributions in"),
       
    40                     ('bitmap=', 'b',
       
    41                      "bitmap to use for the installer instead of python-powered logo"),
       
    42                     ('title=', 't',
       
    43                      "title to display on the installer background instead of default"),
       
    44                     ('skip-build', None,
       
    45                      "skip rebuilding everything (for testing/debugging)"),
       
    46                     ('install-script=', None,
       
    47                      "basename of installation script to be run after"
       
    48                      "installation or before deinstallation"),
       
    49                     ('pre-install-script=', None,
       
    50                      "Fully qualified filename of a script to be run before "
       
    51                      "any files are installed.  This script need not be in the "
       
    52                      "distribution"),
       
    53                     ('user-access-control=', None,
       
    54                      "specify Vista's UAC handling - 'none'/default=no "
       
    55                      "handling, 'auto'=use UAC if target Python installed for "
       
    56                      "all users, 'force'=always use UAC"),
       
    57                    ]
       
    58 
       
    59     boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
       
    60                        'skip-build']
       
    61 
       
    62     def initialize_options (self):
       
    63         self.bdist_dir = None
       
    64         self.plat_name = None
       
    65         self.keep_temp = 0
       
    66         self.no_target_compile = 0
       
    67         self.no_target_optimize = 0
       
    68         self.target_version = None
       
    69         self.dist_dir = None
       
    70         self.bitmap = None
       
    71         self.title = None
       
    72         self.skip_build = 0
       
    73         self.install_script = None
       
    74         self.pre_install_script = None
       
    75         self.user_access_control = None
       
    76 
       
    77     # initialize_options()
       
    78 
       
    79 
       
    80     def finalize_options (self):
       
    81         if self.bdist_dir is None:
       
    82             if self.skip_build and self.plat_name:
       
    83                 # If build is skipped and plat_name is overridden, bdist will
       
    84                 # not see the correct 'plat_name' - so set that up manually.
       
    85                 bdist = self.distribution.get_command_obj('bdist')
       
    86                 bdist.plat_name = self.plat_name
       
    87                 # next the command will be initialized using that name
       
    88             bdist_base = self.get_finalized_command('bdist').bdist_base
       
    89             self.bdist_dir = os.path.join(bdist_base, 'wininst')
       
    90         if not self.target_version:
       
    91             self.target_version = ""
       
    92         if not self.skip_build and self.distribution.has_ext_modules():
       
    93             short_version = get_python_version()
       
    94             if self.target_version and self.target_version != short_version:
       
    95                 raise DistutilsOptionError, \
       
    96                       "target version can only be %s, or the '--skip_build'" \
       
    97                       " option must be specified" % (short_version,)
       
    98             self.target_version = short_version
       
    99 
       
   100         self.set_undefined_options('bdist',
       
   101                                    ('dist_dir', 'dist_dir'),
       
   102                                    ('plat_name', 'plat_name'),
       
   103                                   )
       
   104 
       
   105         if self.install_script:
       
   106             for script in self.distribution.scripts:
       
   107                 if self.install_script == os.path.basename(script):
       
   108                     break
       
   109             else:
       
   110                 raise DistutilsOptionError, \
       
   111                       "install_script '%s' not found in scripts" % \
       
   112                       self.install_script
       
   113     # finalize_options()
       
   114 
       
   115 
       
   116     def run (self):
       
   117         if (sys.platform != "win32" and
       
   118             (self.distribution.has_ext_modules() or
       
   119              self.distribution.has_c_libraries())):
       
   120             raise DistutilsPlatformError \
       
   121                   ("distribution contains extensions and/or C libraries; "
       
   122                    "must be compiled on a Windows 32 platform")
       
   123 
       
   124         if not self.skip_build:
       
   125             self.run_command('build')
       
   126 
       
   127         install = self.reinitialize_command('install', reinit_subcommands=1)
       
   128         install.root = self.bdist_dir
       
   129         install.skip_build = self.skip_build
       
   130         install.warn_dir = 0
       
   131         install.plat_name = self.plat_name
       
   132 
       
   133         install_lib = self.reinitialize_command('install_lib')
       
   134         # we do not want to include pyc or pyo files
       
   135         install_lib.compile = 0
       
   136         install_lib.optimize = 0
       
   137 
       
   138         if self.distribution.has_ext_modules():
       
   139             # If we are building an installer for a Python version other
       
   140             # than the one we are currently running, then we need to ensure
       
   141             # our build_lib reflects the other Python version rather than ours.
       
   142             # Note that for target_version!=sys.version, we must have skipped the
       
   143             # build step, so there is no issue with enforcing the build of this
       
   144             # version.
       
   145             target_version = self.target_version
       
   146             if not target_version:
       
   147                 assert self.skip_build, "Should have already checked this"
       
   148                 target_version = sys.version[0:3]
       
   149             plat_specifier = ".%s-%s" % (self.plat_name, target_version)
       
   150             build = self.get_finalized_command('build')
       
   151             build.build_lib = os.path.join(build.build_base,
       
   152                                            'lib' + plat_specifier)
       
   153 
       
   154         # Use a custom scheme for the zip-file, because we have to decide
       
   155         # at installation time which scheme to use.
       
   156         for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
       
   157             value = string.upper(key)
       
   158             if key == 'headers':
       
   159                 value = value + '/Include/$dist_name'
       
   160             setattr(install,
       
   161                     'install_' + key,
       
   162                     value)
       
   163 
       
   164         log.info("installing to %s", self.bdist_dir)
       
   165         install.ensure_finalized()
       
   166 
       
   167         # avoid warning of 'install_lib' about installing
       
   168         # into a directory not in sys.path
       
   169         sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
       
   170 
       
   171         install.run()
       
   172 
       
   173         del sys.path[0]
       
   174 
       
   175         # And make an archive relative to the root of the
       
   176         # pseudo-installation tree.
       
   177         from tempfile import mktemp
       
   178         archive_basename = mktemp()
       
   179         fullname = self.distribution.get_fullname()
       
   180         arcname = self.make_archive(archive_basename, "zip",
       
   181                                     root_dir=self.bdist_dir)
       
   182         # create an exe containing the zip-file
       
   183         self.create_exe(arcname, fullname, self.bitmap)
       
   184         if self.distribution.has_ext_modules():
       
   185             pyversion = get_python_version()
       
   186         else:
       
   187             pyversion = 'any'
       
   188         self.distribution.dist_files.append(('bdist_wininst', pyversion,
       
   189                                              self.get_installer_filename(fullname)))
       
   190         # remove the zip-file again
       
   191         log.debug("removing temporary file '%s'", arcname)
       
   192         os.remove(arcname)
       
   193 
       
   194         if not self.keep_temp:
       
   195             remove_tree(self.bdist_dir, dry_run=self.dry_run)
       
   196 
       
   197     # run()
       
   198 
       
   199     def get_inidata (self):
       
   200         # Return data describing the installation.
       
   201 
       
   202         lines = []
       
   203         metadata = self.distribution.metadata
       
   204 
       
   205         # Write the [metadata] section.
       
   206         lines.append("[metadata]")
       
   207 
       
   208         # 'info' will be displayed in the installer's dialog box,
       
   209         # describing the items to be installed.
       
   210         info = (metadata.long_description or '') + '\n'
       
   211 
       
   212         # Escape newline characters
       
   213         def escape(s):
       
   214             return string.replace(s, "\n", "\\n")
       
   215 
       
   216         for name in ["author", "author_email", "description", "maintainer",
       
   217                      "maintainer_email", "name", "url", "version"]:
       
   218             data = getattr(metadata, name, "")
       
   219             if data:
       
   220                 info = info + ("\n    %s: %s" % \
       
   221                                (string.capitalize(name), escape(data)))
       
   222                 lines.append("%s=%s" % (name, escape(data)))
       
   223 
       
   224         # The [setup] section contains entries controlling
       
   225         # the installer runtime.
       
   226         lines.append("\n[Setup]")
       
   227         if self.install_script:
       
   228             lines.append("install_script=%s" % self.install_script)
       
   229         lines.append("info=%s" % escape(info))
       
   230         lines.append("target_compile=%d" % (not self.no_target_compile))
       
   231         lines.append("target_optimize=%d" % (not self.no_target_optimize))
       
   232         if self.target_version:
       
   233             lines.append("target_version=%s" % self.target_version)
       
   234         if self.user_access_control:
       
   235             lines.append("user_access_control=%s" % self.user_access_control)
       
   236 
       
   237         title = self.title or self.distribution.get_fullname()
       
   238         lines.append("title=%s" % escape(title))
       
   239         import time
       
   240         import distutils
       
   241         build_info = "Built %s with distutils-%s" % \
       
   242                      (time.ctime(time.time()), distutils.__version__)
       
   243         lines.append("build_info=%s" % build_info)
       
   244         return string.join(lines, "\n")
       
   245 
       
   246     # get_inidata()
       
   247 
       
   248     def create_exe (self, arcname, fullname, bitmap=None):
       
   249         import struct
       
   250 
       
   251         self.mkpath(self.dist_dir)
       
   252 
       
   253         cfgdata = self.get_inidata()
       
   254 
       
   255         installer_name = self.get_installer_filename(fullname)
       
   256         self.announce("creating %s" % installer_name)
       
   257 
       
   258         if bitmap:
       
   259             bitmapdata = open(bitmap, "rb").read()
       
   260             bitmaplen = len(bitmapdata)
       
   261         else:
       
   262             bitmaplen = 0
       
   263 
       
   264         file = open(installer_name, "wb")
       
   265         file.write(self.get_exe_bytes())
       
   266         if bitmap:
       
   267             file.write(bitmapdata)
       
   268 
       
   269         # Convert cfgdata from unicode to ascii, mbcs encoded
       
   270         try:
       
   271             unicode
       
   272         except NameError:
       
   273             pass
       
   274         else:
       
   275             if isinstance(cfgdata, unicode):
       
   276                 cfgdata = cfgdata.encode("mbcs")
       
   277 
       
   278         # Append the pre-install script
       
   279         cfgdata = cfgdata + "\0"
       
   280         if self.pre_install_script:
       
   281             script_data = open(self.pre_install_script, "r").read()
       
   282             cfgdata = cfgdata + script_data + "\n\0"
       
   283         else:
       
   284             # empty pre-install script
       
   285             cfgdata = cfgdata + "\0"
       
   286         file.write(cfgdata)
       
   287 
       
   288         # The 'magic number' 0x1234567B is used to make sure that the
       
   289         # binary layout of 'cfgdata' is what the wininst.exe binary
       
   290         # expects.  If the layout changes, increment that number, make
       
   291         # the corresponding changes to the wininst.exe sources, and
       
   292         # recompile them.
       
   293         header = struct.pack("<iii",
       
   294                              0x1234567B,       # tag
       
   295                              len(cfgdata),     # length
       
   296                              bitmaplen,        # number of bytes in bitmap
       
   297                              )
       
   298         file.write(header)
       
   299         file.write(open(arcname, "rb").read())
       
   300 
       
   301     # create_exe()
       
   302 
       
   303     def get_installer_filename(self, fullname):
       
   304         # Factored out to allow overriding in subclasses
       
   305         if self.target_version:
       
   306             # if we create an installer for a specific python version,
       
   307             # it's better to include this in the name
       
   308             installer_name = os.path.join(self.dist_dir,
       
   309                                           "%s.%s-py%s.exe" %
       
   310                                            (fullname, self.plat_name, self.target_version))
       
   311         else:
       
   312             installer_name = os.path.join(self.dist_dir,
       
   313                                           "%s.%s.exe" % (fullname, self.plat_name))
       
   314         return installer_name
       
   315     # get_installer_filename()
       
   316 
       
   317     def get_exe_bytes (self):
       
   318         from distutils.msvccompiler import get_build_version
       
   319         # If a target-version other than the current version has been
       
   320         # specified, then using the MSVC version from *this* build is no good.
       
   321         # Without actually finding and executing the target version and parsing
       
   322         # its sys.version, we just hard-code our knowledge of old versions.
       
   323         # NOTE: Possible alternative is to allow "--target-version" to
       
   324         # specify a Python executable rather than a simple version string.
       
   325         # We can then execute this program to obtain any info we need, such
       
   326         # as the real sys.version string for the build.
       
   327         cur_version = get_python_version()
       
   328         if self.target_version and self.target_version != cur_version:
       
   329             # If the target version is *later* than us, then we assume they
       
   330             # use what we use
       
   331             # string compares seem wrong, but are what sysconfig.py itself uses
       
   332             if self.target_version > cur_version:
       
   333                 bv = get_build_version()
       
   334             else:
       
   335                 if self.target_version < "2.4":
       
   336                     bv = 6.0
       
   337                 else:
       
   338                     bv = 7.1
       
   339         else:
       
   340             # for current version - use authoritative check.
       
   341             bv = get_build_version()
       
   342 
       
   343         # wininst-x.y.exe is in the same directory as this file
       
   344         directory = os.path.dirname(__file__)
       
   345         # we must use a wininst-x.y.exe built with the same C compiler
       
   346         # used for python.  XXX What about mingw, borland, and so on?
       
   347         if self.plat_name == 'win32':
       
   348             sfix = ''
       
   349         else:
       
   350             sfix = self.plat_name[3:] # strip 'win' - leaves eg '-amd64'
       
   351         filename = os.path.join(directory, "wininst-%.1f%s.exe" % (bv, sfix))
       
   352         return open(filename, "rb").read()
       
   353 # class bdist_wininst