home *** CD-ROM | disk | FTP | other *** search
/ PC World 2005 June / PCWorld_2005-06_cd.bin / software / vyzkuste / firewally / firewally.exe / framework-2.3.exe / bdist_wininst.py < prev    next >
Text File  |  2003-12-30  |  9KB  |  243 lines

  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 1.5.2.
  7.  
  8. __revision__ = "$Id: bdist_wininst.py,v 1.46 2003/06/12 17:23:58 theller Exp $"
  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.                     ('keep-temp', 'k',
  25.                      "keep the pseudo-installation tree around after " +
  26.                      "creating the distribution archive"),
  27.                     ('target-version=', 'v',
  28.                      "require a specific python version" +
  29.                      " on the target system"),
  30.                     ('no-target-compile', 'c',
  31.                      "do not compile .py to .pyc on the target system"),
  32.                     ('no-target-optimize', 'o',
  33.                      "do not compile .py to .pyo (optimized)"
  34.                      "on the target system"),
  35.                     ('dist-dir=', 'd',
  36.                      "directory to put final built distributions in"),
  37.                     ('bitmap=', 'b',
  38.                      "bitmap to use for the installer instead of python-powered logo"),
  39.                     ('title=', 't',
  40.                      "title to display on the installer background instead of default"),
  41.                     ('skip-build', None,
  42.                      "skip rebuilding everything (for testing/debugging)"),
  43.                     ('install-script=', None,
  44.                      "basename of installation script to be run after"
  45.                      "installation or before deinstallation"),
  46.                    ]
  47.  
  48.     boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
  49.                        'skip-build']
  50.  
  51.     def initialize_options (self):
  52.         self.bdist_dir = None
  53.         self.keep_temp = 0
  54.         self.no_target_compile = 0
  55.         self.no_target_optimize = 0
  56.         self.target_version = None
  57.         self.dist_dir = None
  58.         self.bitmap = None
  59.         self.title = None
  60.         self.skip_build = 0
  61.         self.install_script = None
  62.  
  63.     # initialize_options()
  64.  
  65.  
  66.     def finalize_options (self):
  67.         if self.bdist_dir is None:
  68.             bdist_base = self.get_finalized_command('bdist').bdist_base
  69.             self.bdist_dir = os.path.join(bdist_base, 'wininst')
  70.         if not self.target_version:
  71.             self.target_version = ""
  72.         if self.distribution.has_ext_modules():
  73.             short_version = get_python_version()
  74.             if self.target_version and self.target_version != short_version:
  75.                 raise DistutilsOptionError, \
  76.                       "target version can only be" + short_version
  77.             self.target_version = short_version
  78.  
  79.         self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
  80.  
  81.         if self.install_script:
  82.             for script in self.distribution.scripts:
  83.                 if self.install_script == os.path.basename(script):
  84.                     break
  85.             else:
  86.                 raise DistutilsOptionError, \
  87.                       "install_script '%s' not found in scripts" % \
  88.                       self.install_script
  89.     # finalize_options()
  90.  
  91.  
  92.     def run (self):
  93.         if (sys.platform != "win32" and
  94.             (self.distribution.has_ext_modules() or
  95.              self.distribution.has_c_libraries())):
  96.             raise DistutilsPlatformError \
  97.                   ("distribution contains extensions and/or C libraries; "
  98.                    "must be compiled on a Windows 32 platform")
  99.  
  100.         if not self.skip_build:
  101.             self.run_command('build')
  102.  
  103.         install = self.reinitialize_command('install', reinit_subcommands=1)
  104.         install.root = self.bdist_dir
  105.         install.skip_build = self.skip_build
  106.         install.warn_dir = 0
  107.  
  108.         install_lib = self.reinitialize_command('install_lib')
  109.         # we do not want to include pyc or pyo files
  110.         install_lib.compile = 0
  111.         install_lib.optimize = 0
  112.  
  113.         # Use a custom scheme for the zip-file, because we have to decide
  114.         # at installation time which scheme to use.
  115.         for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
  116.             value = string.upper(key)
  117.             if key == 'headers':
  118.                 value = value + '/Include/$dist_name'
  119.             setattr(install,
  120.                     'install_' + key,
  121.                     value)
  122.  
  123.         log.info("installing to %s", self.bdist_dir)
  124.         install.ensure_finalized()
  125.  
  126.         # avoid warning of 'install_lib' about installing
  127.         # into a directory not in sys.path
  128.         sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
  129.  
  130.         install.run()
  131.  
  132.         del sys.path[0]
  133.  
  134.         # And make an archive relative to the root of the
  135.         # pseudo-installation tree.
  136.         from tempfile import mktemp
  137.         archive_basename = mktemp()
  138.         fullname = self.distribution.get_fullname()
  139.         arcname = self.make_archive(archive_basename, "zip",
  140.                                     root_dir=self.bdist_dir)
  141.         # create an exe containing the zip-file
  142.         self.create_exe(arcname, fullname, self.bitmap)
  143.         # remove the zip-file again
  144.         log.debug("removing temporary file '%s'", arcname)
  145.         os.remove(arcname)
  146.  
  147.         if not self.keep_temp:
  148.             remove_tree(self.bdist_dir, dry_run=self.dry_run)
  149.  
  150.     # run()
  151.  
  152.     def get_inidata (self):
  153.         # Return data describing the installation.
  154.  
  155.         lines = []
  156.         metadata = self.distribution.metadata
  157.  
  158.         # Write the [metadata] section.  Values are written with
  159.         # repr()[1:-1], so they do not contain unprintable characters, and
  160.         # are not surrounded by quote chars.
  161.         lines.append("[metadata]")
  162.  
  163.         # 'info' will be displayed in the installer's dialog box,
  164.         # describing the items to be installed.
  165.         info = (metadata.long_description or '') + '\n'
  166.  
  167.         for name in ["author", "author_email", "description", "maintainer",
  168.                      "maintainer_email", "name", "url", "version"]:
  169.             data = getattr(metadata, name, "")
  170.             if data:
  171.                 info = info + ("\n    %s: %s" % \
  172.                                (string.capitalize(name), data))
  173.                 lines.append("%s=%s" % (name, repr(data)[1:-1]))
  174.  
  175.         # The [setup] section contains entries controlling
  176.         # the installer runtime.
  177.         lines.append("\n[Setup]")
  178.         if self.install_script:
  179.             lines.append("install_script=%s" % self.install_script)
  180.         lines.append("info=%s" % repr(info)[1:-1])
  181.         lines.append("target_compile=%d" % (not self.no_target_compile))
  182.         lines.append("target_optimize=%d" % (not self.no_target_optimize))
  183.         if self.target_version:
  184.             lines.append("target_version=%s" % self.target_version)
  185.  
  186.         title = self.title or self.distribution.get_fullname()
  187.         lines.append("title=%s" % repr(title)[1:-1])
  188.         import time
  189.         import distutils
  190.         build_info = "Build %s with distutils-%s" % \
  191.                      (time.ctime(time.time()), distutils.__version__)
  192.         lines.append("build_info=%s" % build_info)
  193.         return string.join(lines, "\n")
  194.  
  195.     # get_inidata()
  196.  
  197.     def create_exe (self, arcname, fullname, bitmap=None):
  198.         import struct
  199.  
  200.         self.mkpath(self.dist_dir)
  201.  
  202.         cfgdata = self.get_inidata()
  203.  
  204.         if self.target_version:
  205.             # if we create an installer for a specific python version,
  206.             # it's better to include this in the name
  207.             installer_name = os.path.join(self.dist_dir,
  208.                                           "%s.win32-py%s.exe" %
  209.                                            (fullname, self.target_version))
  210.         else:
  211.             installer_name = os.path.join(self.dist_dir,
  212.                                           "%s.win32.exe" % fullname)
  213.         self.announce("creating %s" % installer_name)
  214.  
  215.         if bitmap:
  216.             bitmapdata = open(bitmap, "rb").read()
  217.             bitmaplen = len(bitmapdata)
  218.         else:
  219.             bitmaplen = 0
  220.  
  221.         file = open(installer_name, "wb")
  222.         file.write(self.get_exe_bytes())
  223.         if bitmap:
  224.             file.write(bitmapdata)
  225.  
  226.         file.write(cfgdata)
  227.         header = struct.pack("<iii",
  228.                              0x1234567A,       # tag
  229.                              len(cfgdata),     # length
  230.                              bitmaplen,        # number of bytes in bitmap
  231.                              )
  232.         file.write(header)
  233.         file.write(open(arcname, "rb").read())
  234.  
  235.     # create_exe()
  236.  
  237.     def get_exe_bytes (self):
  238.         # wininst.exe is in the same directory as this file
  239.         directory = os.path.dirname(__file__)
  240.         filename = os.path.join(directory, "wininst.exe")
  241.         return open(filename, "rb").read()
  242. # class bdist_wininst
  243.