home *** CD-ROM | disk | FTP | other *** search
- """distutils.command.bdist_wininst
-
- Implements the Distutils 'bdist_wininst' command: create a windows installer
- exe-program."""
-
- # This module should be kept compatible with Python 1.5.2.
-
- __revision__ = "$Id: bdist_wininst.py,v 1.46 2003/06/12 17:23:58 theller Exp $"
-
- import sys, os, string
- from distutils.core import Command
- from distutils.util import get_platform
- from distutils.dir_util import create_tree, remove_tree
- from distutils.errors import *
- from distutils.sysconfig import get_python_version
- from distutils import log
-
- class bdist_wininst (Command):
-
- description = "create an executable installer for MS Windows"
-
- user_options = [('bdist-dir=', None,
- "temporary directory for creating the distribution"),
- ('keep-temp', 'k',
- "keep the pseudo-installation tree around after " +
- "creating the distribution archive"),
- ('target-version=', 'v',
- "require a specific python version" +
- " on the target system"),
- ('no-target-compile', 'c',
- "do not compile .py to .pyc on the target system"),
- ('no-target-optimize', 'o',
- "do not compile .py to .pyo (optimized)"
- "on the target system"),
- ('dist-dir=', 'd',
- "directory to put final built distributions in"),
- ('bitmap=', 'b',
- "bitmap to use for the installer instead of python-powered logo"),
- ('title=', 't',
- "title to display on the installer background instead of default"),
- ('skip-build', None,
- "skip rebuilding everything (for testing/debugging)"),
- ('install-script=', None,
- "basename of installation script to be run after"
- "installation or before deinstallation"),
- ]
-
- boolean_options = ['keep-temp', 'no-target-compile', 'no-target-optimize',
- 'skip-build']
-
- def initialize_options (self):
- self.bdist_dir = None
- self.keep_temp = 0
- self.no_target_compile = 0
- self.no_target_optimize = 0
- self.target_version = None
- self.dist_dir = None
- self.bitmap = None
- self.title = None
- self.skip_build = 0
- self.install_script = None
-
- # initialize_options()
-
-
- def finalize_options (self):
- if self.bdist_dir is None:
- bdist_base = self.get_finalized_command('bdist').bdist_base
- self.bdist_dir = os.path.join(bdist_base, 'wininst')
- if not self.target_version:
- self.target_version = ""
- if self.distribution.has_ext_modules():
- short_version = get_python_version()
- if self.target_version and self.target_version != short_version:
- raise DistutilsOptionError, \
- "target version can only be" + short_version
- self.target_version = short_version
-
- self.set_undefined_options('bdist', ('dist_dir', 'dist_dir'))
-
- if self.install_script:
- for script in self.distribution.scripts:
- if self.install_script == os.path.basename(script):
- break
- else:
- raise DistutilsOptionError, \
- "install_script '%s' not found in scripts" % \
- self.install_script
- # finalize_options()
-
-
- def run (self):
- if (sys.platform != "win32" and
- (self.distribution.has_ext_modules() or
- self.distribution.has_c_libraries())):
- raise DistutilsPlatformError \
- ("distribution contains extensions and/or C libraries; "
- "must be compiled on a Windows 32 platform")
-
- if not self.skip_build:
- self.run_command('build')
-
- install = self.reinitialize_command('install', reinit_subcommands=1)
- install.root = self.bdist_dir
- install.skip_build = self.skip_build
- install.warn_dir = 0
-
- install_lib = self.reinitialize_command('install_lib')
- # we do not want to include pyc or pyo files
- install_lib.compile = 0
- install_lib.optimize = 0
-
- # Use a custom scheme for the zip-file, because we have to decide
- # at installation time which scheme to use.
- for key in ('purelib', 'platlib', 'headers', 'scripts', 'data'):
- value = string.upper(key)
- if key == 'headers':
- value = value + '/Include/$dist_name'
- setattr(install,
- 'install_' + key,
- value)
-
- log.info("installing to %s", self.bdist_dir)
- install.ensure_finalized()
-
- # avoid warning of 'install_lib' about installing
- # into a directory not in sys.path
- sys.path.insert(0, os.path.join(self.bdist_dir, 'PURELIB'))
-
- install.run()
-
- del sys.path[0]
-
- # And make an archive relative to the root of the
- # pseudo-installation tree.
- from tempfile import mktemp
- archive_basename = mktemp()
- fullname = self.distribution.get_fullname()
- arcname = self.make_archive(archive_basename, "zip",
- root_dir=self.bdist_dir)
- # create an exe containing the zip-file
- self.create_exe(arcname, fullname, self.bitmap)
- # remove the zip-file again
- log.debug("removing temporary file '%s'", arcname)
- os.remove(arcname)
-
- if not self.keep_temp:
- remove_tree(self.bdist_dir, dry_run=self.dry_run)
-
- # run()
-
- def get_inidata (self):
- # Return data describing the installation.
-
- lines = []
- metadata = self.distribution.metadata
-
- # Write the [metadata] section. Values are written with
- # repr()[1:-1], so they do not contain unprintable characters, and
- # are not surrounded by quote chars.
- lines.append("[metadata]")
-
- # 'info' will be displayed in the installer's dialog box,
- # describing the items to be installed.
- info = (metadata.long_description or '') + '\n'
-
- for name in ["author", "author_email", "description", "maintainer",
- "maintainer_email", "name", "url", "version"]:
- data = getattr(metadata, name, "")
- if data:
- info = info + ("\n %s: %s" % \
- (string.capitalize(name), data))
- lines.append("%s=%s" % (name, repr(data)[1:-1]))
-
- # The [setup] section contains entries controlling
- # the installer runtime.
- lines.append("\n[Setup]")
- if self.install_script:
- lines.append("install_script=%s" % self.install_script)
- lines.append("info=%s" % repr(info)[1:-1])
- lines.append("target_compile=%d" % (not self.no_target_compile))
- lines.append("target_optimize=%d" % (not self.no_target_optimize))
- if self.target_version:
- lines.append("target_version=%s" % self.target_version)
-
- title = self.title or self.distribution.get_fullname()
- lines.append("title=%s" % repr(title)[1:-1])
- import time
- import distutils
- build_info = "Build %s with distutils-%s" % \
- (time.ctime(time.time()), distutils.__version__)
- lines.append("build_info=%s" % build_info)
- return string.join(lines, "\n")
-
- # get_inidata()
-
- def create_exe (self, arcname, fullname, bitmap=None):
- import struct
-
- self.mkpath(self.dist_dir)
-
- cfgdata = self.get_inidata()
-
- if self.target_version:
- # if we create an installer for a specific python version,
- # it's better to include this in the name
- installer_name = os.path.join(self.dist_dir,
- "%s.win32-py%s.exe" %
- (fullname, self.target_version))
- else:
- installer_name = os.path.join(self.dist_dir,
- "%s.win32.exe" % fullname)
- self.announce("creating %s" % installer_name)
-
- if bitmap:
- bitmapdata = open(bitmap, "rb").read()
- bitmaplen = len(bitmapdata)
- else:
- bitmaplen = 0
-
- file = open(installer_name, "wb")
- file.write(self.get_exe_bytes())
- if bitmap:
- file.write(bitmapdata)
-
- file.write(cfgdata)
- header = struct.pack("<iii",
- 0x1234567A, # tag
- len(cfgdata), # length
- bitmaplen, # number of bytes in bitmap
- )
- file.write(header)
- file.write(open(arcname, "rb").read())
-
- # create_exe()
-
- def get_exe_bytes (self):
- # wininst.exe is in the same directory as this file
- directory = os.path.dirname(__file__)
- filename = os.path.join(directory, "wininst.exe")
- return open(filename, "rb").read()
- # class bdist_wininst
-