Imported Upstream version 65.0.0 upstream/65.0.0
authorJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:54 +0000 (17:02 +0900)
committerJinWang An <jinwang.an@samsung.com>
Mon, 27 Mar 2023 08:02:54 +0000 (17:02 +0900)
22 files changed:
.bumpversion.cfg
CHANGES.rst
docs/deprecated/distutils/apiref.rst
docs/deprecated/distutils/builtdist.rst
docs/deprecated/distutils/commandref.rst
docs/deprecated/distutils/introduction.rst
docs/references/keywords.rst
docs/userguide/development_mode.rst
setup.cfg
setuptools/_distutils/ccompiler.py
setuptools/_distutils/command/__init__.py
setuptools/_distutils/command/bdist.py
setuptools/_distutils/command/bdist_msi.py [deleted file]
setuptools/_distutils/command/bdist_wininst.py [deleted file]
setuptools/_distutils/cygwinccompiler.py
setuptools/_distutils/msvc9compiler.py [deleted file]
setuptools/_distutils/msvccompiler.py [deleted file]
setuptools/_distutils/tests/test_bdist.py
setuptools/_distutils/tests/test_bdist_msi.py [deleted file]
setuptools/_distutils/tests/test_bdist_wininst.py [deleted file]
setuptools/_distutils/tests/test_msvc9compiler.py [deleted file]
tools/msvc-build-launcher.cmd

index f8ab2b2d242408a057fc8a9440cd012dbe961824..05e78cde6809605c84e662f3dc2a1b6b4b9d7215 100644 (file)
@@ -1,5 +1,5 @@
 [bumpversion]
-current_version = 64.0.3
+current_version = 65.0.0
 commit = True
 tag = True
 
index cceb12bd250273f01c7b3703dffa7c4757077759..d4d6437964ce17b0098257bc104fc507d600852d 100644 (file)
@@ -1,3 +1,18 @@
+v65.0.0
+-------
+
+
+Breaking Changes
+^^^^^^^^^^^^^^^^
+* #3505: Removed 'msvccompiler' and 'msvc9compiler' modules from distutils.
+* #3521: Remove bdist_msi and bdist_wininst commands, which have been deprecated since Python 3.9. Use older Setuptools for these behaviors if needed.
+
+Documentation changes
+^^^^^^^^^^^^^^^^^^^^^
+* #3519: Changed the note in ``keywords`` documentation regarding editable installations
+  to specify which ``setuptools`` version require a minimal ``setup.py`` file or not.
+
+
 v64.0.3
 -------
 
index f00ed74c693d3521610b4db180ee53fd3967e51c..278471a25628bca968884288e2a046774340e2f8 100644 (file)
@@ -1845,30 +1845,6 @@ Subclasses of :class:`Command` must define the following methods.
    :synopsis: Build a "dumb" installer - a simple archive of files
 
 
-.. % todo
-
-
-:mod:`distutils.command.bdist_msi` --- Build a Microsoft Installer binary package
-=================================================================================
-
-.. module:: distutils.command.bdist_msi
-   :synopsis: Build a binary distribution as a Windows MSI file
-
-.. class:: bdist_msi
-
-.. deprecated:: 3.9
-   Use bdist_wheel (wheel packages) instead.
-
-   Builds a `Windows Installer`_ (.msi) binary package.
-
-   .. _Windows Installer: https://msdn.microsoft.com/en-us/library/cc185688(VS.85).aspx
-
-   In most cases, the ``bdist_msi`` installer is a better choice than the
-   ``bdist_wininst`` installer, because it provides better support for
-   Win64 platforms, allows administrators to perform non-interactive
-   installations, and allows installation through group policies.
-
-
 :mod:`distutils.command.bdist_rpm` --- Build a binary distribution as a Redhat RPM and SRPM
 ===========================================================================================
 
@@ -1879,19 +1855,6 @@ Subclasses of :class:`Command` must define the following methods.
 .. % todo
 
 
-:mod:`distutils.command.bdist_wininst` --- Build a Windows installer
-====================================================================
-
-.. module:: distutils.command.bdist_wininst
-   :synopsis: Build a Windows installer
-
-.. deprecated:: 3.8
-   Use bdist_wheel (wheel packages) instead.
-
-
-.. % todo
-
-
 :mod:`distutils.command.sdist` --- Build a source distribution
 ==============================================================
 
index e032c03e229a5cbca6a789c27fab6903ff15638e..052a5850f91fb37f7cc9df065bd5f0bc4b65dbdb 100644 (file)
@@ -96,11 +96,6 @@ The available formats for built distributions are:
 +-------------+------------------------------+---------+
 | ``sdux``    | HP-UX :program:`swinstall`   |         |
 +-------------+------------------------------+---------+
-| ``wininst`` | self-extracting ZIP file for | \(4)    |
-|             | Windows                      |         |
-+-------------+------------------------------+---------+
-| ``msi``     | Microsoft Installer.         |         |
-+-------------+------------------------------+---------+
 
 .. versionchanged:: 3.5
    Added support for the ``xztar`` format.
@@ -141,16 +136,6 @@ generated by each, are:
 +--------------------------+-------------------------------------+
 | :command:`bdist_rpm`     | rpm, srpm                           |
 +--------------------------+-------------------------------------+
-| :command:`bdist_wininst` | wininst                             |
-+--------------------------+-------------------------------------+
-| :command:`bdist_msi`     | msi                                 |
-+--------------------------+-------------------------------------+
-
-.. note::
-   bdist_wininst is deprecated since Python 3.8.
-
-.. note::
-   bdist_msi is deprecated since Python 3.9.
 
 The following sections give details on the individual :command:`bdist_\*`
 commands.
@@ -191,7 +176,7 @@ easily specify multiple formats in one run.  If you need to do both, you can
 explicitly specify multiple :command:`bdist_\*` commands and their options::
 
    python setup.py bdist_rpm --packager="John Doe <jdoe@example.org>" \
-                   bdist_wininst --target-version="2.0"
+                   bdist_dumb --dumb-option=foo
 
 Creating RPM packages is driven by a :file:`.spec` file, much as using the
 Distutils is driven by the setup script.  To make your life easier, the
@@ -298,62 +283,6 @@ file winds up deep in the "build tree," in a temporary directory created by
 .. % \command{bdist\_rpm} command with one that writes whatever else you want
 .. % to the \file{.spec} file.)
 
-
-.. _creating-wininst:
-
-Creating Windows Installers
-===========================
-
-.. warning::
-   bdist_wininst is deprecated since Python 3.8.
-
-.. warning::
-   bdist_msi is deprecated since Python 3.9.
-
-Executable installers are the natural format for binary distributions on
-Windows.  They display a nice graphical user interface, display some information
-about the module distribution to be installed taken from the metadata in the
-setup script, let the user select a few options, and start or cancel the
-installation.
-
-Since the metadata is taken from the setup script, creating Windows installers
-is usually as easy as running::
-
-   python setup.py bdist_wininst
-
-or the :command:`bdist` command with the :option:`!--formats` option::
-
-   python setup.py bdist --formats=wininst
-
-If you have a pure module distribution (only containing pure Python modules and
-packages), the resulting installer will be version independent and have a name
-like :file:`foo-1.0.win32.exe`. Note that creating ``wininst`` binary
-distributions in only supported on Windows systems.
-
-If you have a non-pure distribution, the extensions can only be created on a
-Windows platform, and will be Python version dependent. The installer filename
-will reflect this and now has the form :file:`foo-1.0.win32-py2.0.exe`.  You
-have to create a separate installer for every Python version you want to
-support.
-
-The installer will try to compile pure modules into :term:`bytecode` after installation
-on the target system in normal and optimizing mode.  If you don't want this to
-happen for some reason, you can run the :command:`bdist_wininst` command with
-the :option:`!--no-target-compile` and/or the :option:`!--no-target-optimize`
-option.
-
-By default the installer will display the cool "Python Powered" logo when it is
-run, but you can also supply your own 152x261 bitmap which must be a Windows
-:file:`.bmp` file with the :option:`!--bitmap` option.
-
-The installer will also display a large title on the desktop background window
-when it is run, which is constructed from the name of your distribution and the
-version number.  This can be changed to another text by using the
-:option:`!--title` option.
-
-The installer file will be written to the "distribution directory" --- normally
-:file:`dist/`, but customizable with the :option:`!--dist-dir` option.
-
 .. _cross-compile-windows:
 
 Cross-compiling on Windows
@@ -370,12 +299,7 @@ For example, on a 32bit version of Windows, you could execute::
 
    python setup.py build --plat-name=win-amd64
 
-to build a 64bit version of your extension.  The Windows Installers also
-support this option, so the command::
-
-   python setup.py build --plat-name=win-amd64 bdist_wininst
-
-would create a 64bit installation executable on your 32bit version of Windows.
+to build a 64bit version of your extension.
 
 To cross-compile, you must download the Python source code and cross-compile
 Python itself for the platform you are targeting - it is not possible from a
@@ -462,18 +386,3 @@ built-in functions in the installation script.
    and *iconindex* is the index of the icon in the file *iconpath*.  Again, for
    details consult the Microsoft documentation for the :class:`IShellLink`
    interface.
-
-
-Vista User Access Control (UAC)
-===============================
-
-Starting with Python 2.6, bdist_wininst supports a :option:`!--user-access-control`
-option.  The default is 'none' (meaning no UAC handling is done), and other
-valid values are 'auto' (meaning prompt for UAC elevation if Python was
-installed for all users) and 'force' (meaning always prompt for elevation).
-
-.. note::
-   bdist_wininst is deprecated since Python 3.8.
-
-.. note::
-   bdist_msi is deprecated since Python 3.9.
index 0f6fe2aba865f819edf8914ba0148a93ee7398fc..3e247e68d3a05f4333cdb64545c447f96e9e9ce9 100644 (file)
@@ -101,6 +101,5 @@ anything except backslash or colon.
 .. % \subsection{\protect\command{bdist}}
 .. % \subsection{\protect\command{bdist\_dumb}}
 .. % \subsection{\protect\command{bdist\_rpm}}
-.. % \subsection{\protect\command{bdist\_wininst}}
 
 
index 7491b965a5db2ba2871b142e10301cff5413e95f..58a31283171bc72c34139e0f1004a668a9dc0075 100644 (file)
@@ -112,17 +112,6 @@ the setup script.  The difference is which Distutils *commands* they use: the
 :command:`install` is more often for installers (although most developers will
 want to install their own code occasionally).
 
-If you want to make things really easy for your users, you can create one or
-more built distributions for them.  For instance, if you are running on a
-Windows machine, and want to make things easy for other Windows users, you can
-create an executable installer (the most appropriate type of built distribution
-for this platform) with the :command:`bdist_wininst` command.  For example::
-
-   python setup.py bdist_wininst
-
-will create an executable installer, :file:`foo-1.0.win32.exe`, in the current
-directory.
-
 Other useful built distribution formats are RPM, implemented by the
 :command:`bdist_rpm` command, Solaris :program:`pkgtool`
 (:command:`bdist_pkgtool`), and HP-UX :program:`swinstall`
index cf8fe41cdef2d0264211a754a00a557ae505fcc9..ade147ad75efd8b2db99ceefb9997fba2c27254d 100644 (file)
@@ -20,17 +20,16 @@ tap into special behaviour that requires scripting (such as building C
 extensions).
 
 .. note::
-   When using declarative configs via ``pyproject.toml`` users can still keep a
-   very simple ``setup.py`` just to ensure editable installs are supported, for
-   example::
+   When using declarative configs via ``pyproject.toml``
+   with ``setuptools<64.0.0``, users can still keep a very simple ``setup.py``
+   just to ensure editable installs are supported, for example::
 
        from setuptools import setup
 
        setup()
 
-   Future versions of ``setuptools`` may support editable installs even
-   without ``setup.py``.
-
+   Versions of ``setuptools`` ``>=64.0.0`` do not require this extra minimal
+   ``setup.py`` file.
 
 .. _keyword/name:
 
index d2d5c7055fce7c943616424c8f90ad43a69ce7d1..c911af537dc04b2e060f14f1cb50f04a13a8488c 100644 (file)
@@ -148,7 +148,7 @@ Limitations
   Users are encouraged to use tools like :mod:`importlib.resources` or
   :mod:`importlib.metadata` when trying to access package files directly.
 - Editable installations may not work with
-  :doc:`namespaces created with pkgutil or pkg_resouces
+  :doc:`namespaces created with pkgutil or pkg_resources
   <PyPUG:guides/packaging-namespace-packages>`.
   Please use :pep:`420`-style implicit namespaces [#namespaces]_.
 - Support for :pep:`420`-style implicit namespace packages for
index 23f119a0ddebfce467ebc687c93e50a485cc47e3..25a0541c9b082884de035fa52df12c594f10ad8d 100644 (file)
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
 [metadata]
 name = setuptools
-version = 64.0.3
+version = 65.0.0
 author = Python Packaging Authority
 author_email = distutils-sig@python.org
 description = Easily download, build, install, upgrade, and uninstall Python packages
index 3cf5761cf2aee4bae021687949df770a15c68fc2..c8d3b24bc0eefae34a41301896ef9a7815336f73 100644 (file)
@@ -6,6 +6,8 @@ for the Distutils compiler abstraction model."""
 import sys
 import os
 import re
+import warnings
+
 from distutils.errors import (
     CompileError,
     LinkError,
@@ -925,8 +927,7 @@ int main (int argc, char **argv) {
         obj_names = []
         for src_name in source_filenames:
             base, ext = os.path.splitext(src_name)
-            base = os.path.splitdrive(base)[1]  # Chop off the drive
-            base = base[os.path.isabs(base) :]  # If abs, chop off leading /
+            base = self._mangle_base(base)
             if ext not in self.src_extensions:
                 raise UnknownFileError(
                     "unknown file type '{}' (from '{}')".format(ext, src_name)
@@ -936,6 +937,25 @@ int main (int argc, char **argv) {
             obj_names.append(os.path.join(output_dir, base + self.obj_extension))
         return obj_names
 
+    @staticmethod
+    def _mangle_base(base):
+        """
+        For unknown reasons, absolute paths are mangled.
+        """
+        # Chop off the drive
+        no_drive = os.path.splitdrive(base)[1]
+        # If abs, chop off leading /
+        rel = no_drive[os.path.isabs(no_drive) :]
+        if rel != base:
+            msg = (
+                f"Absolute path {base!r} is being replaced with a "
+                f"relative path {rel!r} for outputs. This behavior is "
+                "deprecated. If this behavior is desired, please "
+                "comment in pypa/distutils#169."
+            )
+            warnings.warn(msg, DeprecationWarning)
+        return rel
+
     def shared_object_filename(self, basename, strip_dir=0, output_dir=''):
         assert output_dir is not None
         if strip_dir:
index a40c1f9471fc2a9a9bdf9573cb15a3de952158f2..028dcfa0fc4b3a07307989c40389b2042ceafc03 100644 (file)
@@ -20,7 +20,6 @@ __all__ = [  # noqa: F822
     'bdist',
     'bdist_dumb',
     'bdist_rpm',
-    'bdist_wininst',
     'check',
     'upload',
 ]
index c9fdbf131ced399fdae9cd337875a699f40a9afd..de37dae0ffcd5ea3b05c2203981f23163707cdd6 100644 (file)
@@ -85,9 +85,7 @@ class bdist(Command):
             'xztar': ('bdist_dumb', "xz'ed tar file"),
             'ztar': ('bdist_dumb', "compressed tar file"),
             'tar': ('bdist_dumb', "tar file"),
-            'wininst': ('bdist_wininst', "Windows executable installer"),
             'zip': ('bdist_dumb', "ZIP file"),
-            'msi': ('bdist_msi', "Microsoft Installer"),
         }
     )
 
diff --git a/setuptools/_distutils/command/bdist_msi.py b/setuptools/_distutils/command/bdist_msi.py
deleted file mode 100644 (file)
index 57931c7..0000000
+++ /dev/null
@@ -1,1114 +0,0 @@
-# Copyright (C) 2005, 2006 Martin von Löwis
-# Licensed to PSF under a Contributor Agreement.
-# The bdist_wininst command proper
-# based on bdist_wininst
-"""
-Implements the bdist_msi command.
-"""
-
-import os
-import sys
-import warnings
-from distutils.core import Command
-from distutils.dir_util import remove_tree
-from distutils.sysconfig import get_python_version
-from distutils.version import StrictVersion
-from distutils.errors import DistutilsOptionError
-from distutils.util import get_platform
-from distutils import log
-import msilib
-from msilib import schema, sequence, text
-from msilib import Directory, Feature, Dialog, add_data
-
-
-class PyDialog(Dialog):
-    """Dialog class with a fixed layout: controls at the top, then a ruler,
-    then a list of buttons: back, next, cancel. Optionally a bitmap at the
-    left."""
-
-    def __init__(self, *args, **kw):
-        """Dialog(database, name, x, y, w, h, attributes, title, first,
-        default, cancel, bitmap=true)"""
-        super().__init__(*args)
-        ruler = self.h - 36
-        self.line("BottomLine", 0, ruler, self.w, 0)
-
-    def title(self, title):
-        "Set the title text of the dialog at the top."
-        # name, x, y, w, h, flags=Visible|Enabled|Transparent|NoPrefix,
-        # text, in VerdanaBold10
-        self.text("Title", 15, 10, 320, 60, 0x30003, r"{\VerdanaBold10}%s" % title)
-
-    def back(self, title, next, name="Back", active=1):
-        """Add a back button with a given title, the tab-next button,
-        its name in the Control table, possibly initially disabled.
-
-        Return the button, so that events can be associated"""
-        if active:
-            flags = 3  # Visible|Enabled
-        else:
-            flags = 1  # Visible
-        return self.pushbutton(name, 180, self.h - 27, 56, 17, flags, title, next)
-
-    def cancel(self, title, next, name="Cancel", active=1):
-        """Add a cancel button with a given title, the tab-next button,
-        its name in the Control table, possibly initially disabled.
-
-        Return the button, so that events can be associated"""
-        if active:
-            flags = 3  # Visible|Enabled
-        else:
-            flags = 1  # Visible
-        return self.pushbutton(name, 304, self.h - 27, 56, 17, flags, title, next)
-
-    def next(self, title, next, name="Next", active=1):
-        """Add a Next button with a given title, the tab-next button,
-        its name in the Control table, possibly initially disabled.
-
-        Return the button, so that events can be associated"""
-        if active:
-            flags = 3  # Visible|Enabled
-        else:
-            flags = 1  # Visible
-        return self.pushbutton(name, 236, self.h - 27, 56, 17, flags, title, next)
-
-    def xbutton(self, name, title, next, xpos):
-        """Add a button with a given title, the tab-next button,
-        its name in the Control table, giving its x position; the
-        y-position is aligned with the other buttons.
-
-        Return the button, so that events can be associated"""
-        return self.pushbutton(
-            name, int(self.w * xpos - 28), self.h - 27, 56, 17, 3, title, next
-        )
-
-
-class bdist_msi(Command):
-
-    description = "create a Microsoft Installer (.msi) binary distribution"
-
-    user_options = [
-        ('bdist-dir=', None, "temporary directory for creating the distribution"),
-        (
-            'plat-name=',
-            'p',
-            "platform name to embed in generated filenames "
-            "(default: %s)" % get_platform(),
-        ),
-        (
-            'keep-temp',
-            'k',
-            "keep the pseudo-installation tree around after "
-            + "creating the distribution archive",
-        ),
-        (
-            'target-version=',
-            None,
-            "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"),
-        ('skip-build', None, "skip rebuilding everything (for testing/debugging)"),
-        (
-            'install-script=',
-            None,
-            "basename of installation script to be run after "
-            "installation or before deinstallation",
-        ),
-        (
-            '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",
-        ),
-    ]
-
-    boolean_options = [
-        'keep-temp',
-        'no-target-compile',
-        'no-target-optimize',
-        'skip-build',
-    ]
-
-    all_versions = [
-        '2.0',
-        '2.1',
-        '2.2',
-        '2.3',
-        '2.4',
-        '2.5',
-        '2.6',
-        '2.7',
-        '2.8',
-        '2.9',
-        '3.0',
-        '3.1',
-        '3.2',
-        '3.3',
-        '3.4',
-        '3.5',
-        '3.6',
-        '3.7',
-        '3.8',
-        '3.9',
-    ]
-    other_version = 'X'
-
-    def __init__(self, *args, **kw):
-        super().__init__(*args, **kw)
-        warnings.warn(
-            "bdist_msi command is deprecated since Python 3.9, "
-            "use bdist_wheel (wheel packages) instead",
-            DeprecationWarning,
-            2,
-        )
-
-    def initialize_options(self):
-        self.bdist_dir = None
-        self.plat_name = None
-        self.keep_temp = 0
-        self.no_target_compile = 0
-        self.no_target_optimize = 0
-        self.target_version = None
-        self.dist_dir = None
-        self.skip_build = None
-        self.install_script = None
-        self.pre_install_script = None
-        self.versions = None
-
-    def finalize_options(self):
-        self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
-
-        if self.bdist_dir is None:
-            bdist_base = self.get_finalized_command('bdist').bdist_base
-            self.bdist_dir = os.path.join(bdist_base, 'msi')
-
-        short_version = get_python_version()
-        if (not self.target_version) and self.distribution.has_ext_modules():
-            self.target_version = short_version
-
-        if self.target_version:
-            self.versions = [self.target_version]
-            if (
-                not self.skip_build
-                and self.distribution.has_ext_modules()
-                and self.target_version != short_version
-            ):
-                raise DistutilsOptionError(
-                    "target version can only be %s, or the '--skip-build'"
-                    " option must be specified" % (short_version,)
-                )
-        else:
-            self.versions = list(self.all_versions)
-
-        self.set_undefined_options(
-            'bdist',
-            ('dist_dir', 'dist_dir'),
-            ('plat_name', 'plat_name'),
-        )
-
-        if self.pre_install_script:
-            raise DistutilsOptionError(
-                "the pre-install-script feature is not yet implemented"
-            )
-
-        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
-                )
-        self.install_script_key = None
-
-    def run(self):  # noqa: C901
-        if not self.skip_build:
-            self.run_command('build')
-
-        install = self.reinitialize_command('install', reinit_subcommands=1)
-        install.prefix = 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
-
-        if self.distribution.has_ext_modules():
-            # If we are building an installer for a Python version other
-            # than the one we are currently running, then we need to ensure
-            # our build_lib reflects the other Python version rather than ours.
-            # Note that for target_version!=sys.version, we must have skipped the
-            # build step, so there is no issue with enforcing the build of this
-            # version.
-            target_version = self.target_version
-            if not target_version:
-                assert self.skip_build, "Should have already checked this"
-                target_version = '%d.%d' % sys.version_info[:2]
-            plat_specifier = ".{}-{}".format(self.plat_name, target_version)
-            build = self.get_finalized_command('build')
-            build.build_lib = os.path.join(build.build_base, 'lib' + plat_specifier)
-
-        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]
-
-        self.mkpath(self.dist_dir)
-        fullname = self.distribution.get_fullname()
-        installer_name = self.get_installer_filename(fullname)
-        installer_name = os.path.abspath(installer_name)
-        if os.path.exists(installer_name):
-            os.unlink(installer_name)
-
-        metadata = self.distribution.metadata
-        author = metadata.author or metadata.maintainer
-        version = metadata.get_version()
-        # ProductVersion must be strictly numeric
-        # XXX need to deal with prerelease versions
-        sversion = "%d.%d.%d" % StrictVersion(version).version
-        # Prefix ProductName with Python x.y, so that
-        # it sorts together with the other Python packages
-        # in Add-Remove-Programs (APR)
-        fullname = self.distribution.get_fullname()
-        if self.target_version:
-            product_name = "Python {} {}".format(self.target_version, fullname)
-        else:
-            product_name = "Python %s" % (fullname)
-        self.db = msilib.init_database(
-            installer_name, schema, product_name, msilib.gen_uuid(), sversion, author
-        )
-        msilib.add_tables(self.db, sequence)
-        props = [('DistVersion', version)]
-        email = metadata.author_email or metadata.maintainer_email
-        if email:
-            props.append(("ARPCONTACT", email))
-        if metadata.url:
-            props.append(("ARPURLINFOABOUT", metadata.url))
-        if props:
-            add_data(self.db, 'Property', props)
-
-        self.add_find_python()
-        self.add_files()
-        self.add_scripts()
-        self.add_ui()
-        self.db.Commit()
-
-        if hasattr(self.distribution, 'dist_files'):
-            tup = 'bdist_msi', self.target_version or 'any', fullname
-            self.distribution.dist_files.append(tup)
-
-        if not self.keep_temp:
-            remove_tree(self.bdist_dir, dry_run=self.dry_run)
-
-    def add_files(self):  # noqa: C901
-        db = self.db
-        cab = msilib.CAB("distfiles")
-        rootdir = os.path.abspath(self.bdist_dir)
-
-        root = Directory(db, cab, None, rootdir, "TARGETDIR", "SourceDir")
-        f = Feature(db, "Python", "Python", "Everything", 0, 1, directory="TARGETDIR")
-
-        items = [(f, root, '')]
-        for version in self.versions + [self.other_version]:
-            target = "TARGETDIR" + version
-            name = default = "Python" + version
-            desc = "Everything"
-            if version is self.other_version:
-                title = "Python from another location"
-                level = 2
-            else:
-                title = "Python %s from registry" % version
-                level = 1
-            f = Feature(db, name, title, desc, 1, level, directory=target)
-            dir = Directory(db, cab, root, rootdir, target, default)
-            items.append((f, dir, version))
-        db.Commit()
-
-        seen = {}
-        for feature, dir, version in items:
-            todo = [dir]
-            while todo:
-                dir = todo.pop()
-                for file in os.listdir(dir.absolute):
-                    afile = os.path.join(dir.absolute, file)
-                    if os.path.isdir(afile):
-                        short = "{}|{}".format(dir.make_short(file), file)
-                        default = file + version
-                        newdir = Directory(db, cab, dir, file, default, short)
-                        todo.append(newdir)
-                    else:
-                        if not dir.component:
-                            dir.start_component(dir.logical, feature, 0)
-                        if afile not in seen:
-                            key = seen[afile] = dir.add_file(file)
-                            if file == self.install_script:
-                                if self.install_script_key:
-                                    raise DistutilsOptionError(
-                                        "Multiple files with name %s" % file
-                                    )
-                                self.install_script_key = '[#%s]' % key
-                        else:
-                            key = seen[afile]
-                            add_data(
-                                self.db,
-                                "DuplicateFile",
-                                [
-                                    (
-                                        key + version,
-                                        dir.component,
-                                        key,
-                                        None,
-                                        dir.logical,
-                                    )
-                                ],
-                            )
-            db.Commit()
-        cab.commit(db)
-
-    def add_find_python(self):
-        """Adds code to the installer to compute the location of Python.
-
-        Properties PYTHON.MACHINE.X.Y and PYTHON.USER.X.Y will be set from the
-        registry for each version of Python.
-
-        Properties TARGETDIRX.Y will be set from PYTHON.USER.X.Y if defined,
-        else from PYTHON.MACHINE.X.Y.
-
-        Properties PYTHONX.Y will be set to TARGETDIRX.Y\\python.exe"""
-
-        start = 402
-        for ver in self.versions:
-            install_path = r"SOFTWARE\Python\PythonCore\%s\InstallPath" % ver
-            machine_reg = "python.machine." + ver
-            user_reg = "python.user." + ver
-            machine_prop = "PYTHON.MACHINE." + ver
-            user_prop = "PYTHON.USER." + ver
-            machine_action = "PythonFromMachine" + ver
-            user_action = "PythonFromUser" + ver
-            exe_action = "PythonExe" + ver
-            target_dir_prop = "TARGETDIR" + ver
-            exe_prop = "PYTHON" + ver
-
-            # Type: msidbLocatorTypeRawValue + msidbLocatorType64bit
-            Type = 2 + 16 * bool(msilib.Win64)
-            add_data(
-                self.db,
-                "RegLocator",
-                [
-                    (machine_reg, 2, install_path, None, Type),
-                    (user_reg, 1, install_path, None, Type),
-                ],
-            )
-            add_data(
-                self.db,
-                "AppSearch",
-                [(machine_prop, machine_reg), (user_prop, user_reg)],
-            )
-            add_data(
-                self.db,
-                "CustomAction",
-                [
-                    (
-                        machine_action,
-                        51 + 256,
-                        target_dir_prop,
-                        "[" + machine_prop + "]",
-                    ),
-                    (user_action, 51 + 256, target_dir_prop, "[" + user_prop + "]"),
-                    (
-                        exe_action,
-                        51 + 256,
-                        exe_prop,
-                        "[" + target_dir_prop + "]\\python.exe",
-                    ),
-                ],
-            )
-            add_data(
-                self.db,
-                "InstallExecuteSequence",
-                [
-                    (machine_action, machine_prop, start),
-                    (user_action, user_prop, start + 1),
-                    (exe_action, None, start + 2),
-                ],
-            )
-            add_data(
-                self.db,
-                "InstallUISequence",
-                [
-                    (machine_action, machine_prop, start),
-                    (user_action, user_prop, start + 1),
-                    (exe_action, None, start + 2),
-                ],
-            )
-            add_data(self.db, "Condition", [("Python" + ver, 0, "NOT TARGETDIR" + ver)])
-            start += 4
-            assert start < 500
-
-    def add_scripts(self):
-        if self.install_script:
-            start = 6800
-            for ver in self.versions + [self.other_version]:
-                install_action = "install_script." + ver
-                exe_prop = "PYTHON" + ver
-                add_data(
-                    self.db,
-                    "CustomAction",
-                    [(install_action, 50, exe_prop, self.install_script_key)],
-                )
-                add_data(
-                    self.db,
-                    "InstallExecuteSequence",
-                    [(install_action, "&Python%s=3" % ver, start)],
-                )
-                start += 1
-        # XXX pre-install scripts are currently refused in finalize_options()
-        #     but if this feature is completed, it will also need to add
-        #     entries for each version as the above code does
-        if self.pre_install_script:
-            scriptfn = os.path.join(self.bdist_dir, "preinstall.bat")
-            with open(scriptfn, "w") as f:
-                # The batch file will be executed with [PYTHON], so that %1
-                # is the path to the Python interpreter; %0 will be the path
-                # of the batch file.
-                # rem ="""
-                # %1 %0
-                # exit
-                # """
-                # <actual script>
-                f.write('rem ="""\n%1 %0\nexit\n"""\n')
-                with open(self.pre_install_script) as fin:
-                    f.write(fin.read())
-            add_data(self.db, "Binary", [("PreInstall", msilib.Binary(scriptfn))])
-            add_data(self.db, "CustomAction", [("PreInstall", 2, "PreInstall", None)])
-            add_data(
-                self.db,
-                "InstallExecuteSequence",
-                [("PreInstall", "NOT Installed", 450)],
-            )
-
-    def add_ui(self):
-        db = self.db
-        x = y = 50
-        w = 370
-        h = 300
-        title = "[ProductName] Setup"
-
-        # see "Dialog Style Bits"
-        modal = 3  # visible | modal
-        modeless = 1  # visible
-
-        # UI customization properties
-        add_data(
-            db,
-            "Property",
-            # See "DefaultUIFont Property"
-            [
-                ("DefaultUIFont", "DlgFont8"),
-                # See "ErrorDialog Style Bit"
-                ("ErrorDialog", "ErrorDlg"),
-                ("Progress1", "Install"),  # modified in maintenance type dlg
-                ("Progress2", "installs"),
-                ("MaintenanceForm_Action", "Repair"),
-                # possible values: ALL, JUSTME
-                ("WhichUsers", "ALL"),
-            ],
-        )
-
-        # Fonts, see "TextStyle Table"
-        add_data(
-            db,
-            "TextStyle",
-            [
-                ("DlgFont8", "Tahoma", 9, None, 0),
-                ("DlgFontBold8", "Tahoma", 8, None, 1),  # bold
-                ("VerdanaBold10", "Verdana", 10, None, 1),
-                ("VerdanaRed9", "Verdana", 9, 255, 0),
-            ],
-        )
-
-        # UI Sequences, see "InstallUISequence Table", "Using a Sequence Table"
-        # Numbers indicate sequence; see sequence.py for how these action integrate
-        add_data(
-            db,
-            "InstallUISequence",
-            [
-                ("PrepareDlg", "Not Privileged or Windows9x or Installed", 140),
-                (
-                    "WhichUsersDlg",
-                    "Privileged and not Windows9x and not Installed",
-                    141,
-                ),
-                # In the user interface, assume all-users installation if privileged.
-                ("SelectFeaturesDlg", "Not Installed", 1230),
-                # XXX no support for resume installations yet
-                # ("ResumeDlg", "Installed AND (RESUME OR Preselected)", 1240),
-                (
-                    "MaintenanceTypeDlg",
-                    "Installed AND NOT RESUME AND NOT Preselected",
-                    1250,
-                ),
-                ("ProgressDlg", None, 1280),
-            ],
-        )
-
-        add_data(db, 'ActionText', text.ActionText)
-        add_data(db, 'UIText', text.UIText)
-        #####################################################################
-        # Standard dialogs: FatalError, UserExit, ExitDialog
-        fatal = PyDialog(
-            db, "FatalError", x, y, w, h, modal, title, "Finish", "Finish", "Finish"
-        )
-        fatal.title("[ProductName] Installer ended prematurely")
-        fatal.back("< Back", "Finish", active=0)
-        fatal.cancel("Cancel", "Back", active=0)
-        fatal.text(
-            "Description1",
-            15,
-            70,
-            320,
-            80,
-            0x30003,
-            "[ProductName] setup ended prematurely because of an error. "
-            "Your system has not been modified.  To install this program "
-            "at a later time, please run the installation again.",
-        )
-        fatal.text(
-            "Description2",
-            15,
-            155,
-            320,
-            20,
-            0x30003,
-            "Click the Finish button to exit the Installer.",
-        )
-        c = fatal.next("Finish", "Cancel", name="Finish")
-        c.event("EndDialog", "Exit")
-
-        user_exit = PyDialog(
-            db, "UserExit", x, y, w, h, modal, title, "Finish", "Finish", "Finish"
-        )
-        user_exit.title("[ProductName] Installer was interrupted")
-        user_exit.back("< Back", "Finish", active=0)
-        user_exit.cancel("Cancel", "Back", active=0)
-        user_exit.text(
-            "Description1",
-            15,
-            70,
-            320,
-            80,
-            0x30003,
-            "[ProductName] setup was interrupted.  Your system has not been modified.  "
-            "To install this program at a later time, please run the installation "
-            "again.",
-        )
-        user_exit.text(
-            "Description2",
-            15,
-            155,
-            320,
-            20,
-            0x30003,
-            "Click the Finish button to exit the Installer.",
-        )
-        c = user_exit.next("Finish", "Cancel", name="Finish")
-        c.event("EndDialog", "Exit")
-
-        exit_dialog = PyDialog(
-            db, "ExitDialog", x, y, w, h, modal, title, "Finish", "Finish", "Finish"
-        )
-        exit_dialog.title("Completing the [ProductName] Installer")
-        exit_dialog.back("< Back", "Finish", active=0)
-        exit_dialog.cancel("Cancel", "Back", active=0)
-        exit_dialog.text(
-            "Description",
-            15,
-            235,
-            320,
-            20,
-            0x30003,
-            "Click the Finish button to exit the Installer.",
-        )
-        c = exit_dialog.next("Finish", "Cancel", name="Finish")
-        c.event("EndDialog", "Return")
-
-        #####################################################################
-        # Required dialog: FilesInUse, ErrorDlg
-        inuse = PyDialog(
-            db,
-            "FilesInUse",
-            x,
-            y,
-            w,
-            h,
-            19,  # KeepModeless|Modal|Visible
-            title,
-            "Retry",
-            "Retry",
-            "Retry",
-            bitmap=False,
-        )
-        inuse.text("Title", 15, 6, 200, 15, 0x30003, r"{\DlgFontBold8}Files in Use")
-        inuse.text(
-            "Description",
-            20,
-            23,
-            280,
-            20,
-            0x30003,
-            "Some files that need to be updated are currently in use.",
-        )
-        inuse.text(
-            "Text",
-            20,
-            55,
-            330,
-            50,
-            3,
-            "The following applications are using files that need to be updated by "
-            "this "
-            "setup. Close these applications and then click Retry to continue the "
-            "installation or Cancel to exit it.",
-        )
-        inuse.control(
-            "List",
-            "ListBox",
-            20,
-            107,
-            330,
-            130,
-            7,
-            "FileInUseProcess",
-            None,
-            None,
-            None,
-        )
-        c = inuse.back("Exit", "Ignore", name="Exit")
-        c.event("EndDialog", "Exit")
-        c = inuse.next("Ignore", "Retry", name="Ignore")
-        c.event("EndDialog", "Ignore")
-        c = inuse.cancel("Retry", "Exit", name="Retry")
-        c.event("EndDialog", "Retry")
-
-        # See "Error Dialog". See "ICE20" for the required names of the controls.
-        error = Dialog(
-            db,
-            "ErrorDlg",
-            50,
-            10,
-            330,
-            101,
-            65543,  # Error|Minimize|Modal|Visible
-            title,
-            "ErrorText",
-            None,
-            None,
-        )
-        error.text("ErrorText", 50, 9, 280, 48, 3, "")
-        error.pushbutton("N", 120, 72, 81, 21, 3, "No", None).event(
-            "EndDialog", "ErrorNo"
-        )
-        error.pushbutton("Y", 240, 72, 81, 21, 3, "Yes", None).event(
-            "EndDialog", "ErrorYes"
-        )
-        error.pushbutton("A", 0, 72, 81, 21, 3, "Abort", None).event(
-            "EndDialog", "ErrorAbort"
-        )
-        error.pushbutton("C", 42, 72, 81, 21, 3, "Cancel", None).event(
-            "EndDialog", "ErrorCancel"
-        )
-        error.pushbutton("I", 81, 72, 81, 21, 3, "Ignore", None).event(
-            "EndDialog", "ErrorIgnore"
-        )
-        error.pushbutton("O", 159, 72, 81, 21, 3, "Ok", None).event(
-            "EndDialog", "ErrorOk"
-        )
-        error.pushbutton("R", 198, 72, 81, 21, 3, "Retry", None).event(
-            "EndDialog", "ErrorRetry"
-        )
-
-        #####################################################################
-        # Global "Query Cancel" dialog
-        cancel = Dialog(db, "CancelDlg", 50, 10, 260, 85, 3, title, "No", "No", "No")
-        cancel.text(
-            "Text",
-            48,
-            15,
-            194,
-            30,
-            3,
-            "Are you sure you want to cancel [ProductName] installation?",
-        )
-        # cancel.control("Icon", "Icon", 15, 15, 24, 24, 5242881, None,
-        #               "py.ico", None, None)
-        c = cancel.pushbutton("Yes", 72, 57, 56, 17, 3, "Yes", "No")
-        c.event("EndDialog", "Exit")
-
-        c = cancel.pushbutton("No", 132, 57, 56, 17, 3, "No", "Yes")
-        c.event("EndDialog", "Return")
-
-        #####################################################################
-        # Global "Wait for costing" dialog
-        costing = Dialog(
-            db,
-            "WaitForCostingDlg",
-            50,
-            10,
-            260,
-            85,
-            modal,
-            title,
-            "Return",
-            "Return",
-            "Return",
-        )
-        costing.text(
-            "Text",
-            48,
-            15,
-            194,
-            30,
-            3,
-            "Please wait while the installer finishes determining your disk space "
-            "requirements.",
-        )
-        c = costing.pushbutton("Return", 102, 57, 56, 17, 3, "Return", None)
-        c.event("EndDialog", "Exit")
-
-        #####################################################################
-        # Preparation dialog: no user input except cancellation
-        prep = PyDialog(
-            db, "PrepareDlg", x, y, w, h, modeless, title, "Cancel", "Cancel", "Cancel"
-        )
-        prep.text(
-            "Description",
-            15,
-            70,
-            320,
-            40,
-            0x30003,
-            "Please wait while the Installer prepares to guide you through the "
-            "installation.",
-        )
-        prep.title("Welcome to the [ProductName] Installer")
-        c = prep.text("ActionText", 15, 110, 320, 20, 0x30003, "Pondering...")
-        c.mapping("ActionText", "Text")
-        c = prep.text("ActionData", 15, 135, 320, 30, 0x30003, None)
-        c.mapping("ActionData", "Text")
-        prep.back("Back", None, active=0)
-        prep.next("Next", None, active=0)
-        c = prep.cancel("Cancel", None)
-        c.event("SpawnDialog", "CancelDlg")
-
-        #####################################################################
-        # Feature (Python directory) selection
-        seldlg = PyDialog(
-            db, "SelectFeaturesDlg", x, y, w, h, modal, title, "Next", "Next", "Cancel"
-        )
-        seldlg.title("Select Python Installations")
-
-        seldlg.text(
-            "Hint",
-            15,
-            30,
-            300,
-            20,
-            3,
-            "Select the Python locations where %s should be installed."
-            % self.distribution.get_fullname(),
-        )
-
-        seldlg.back("< Back", None, active=0)
-        c = seldlg.next("Next >", "Cancel")
-        order = 1
-        c.event("[TARGETDIR]", "[SourceDir]", ordering=order)
-        for version in self.versions + [self.other_version]:
-            order += 1
-            c.event(
-                "[TARGETDIR]",
-                "[TARGETDIR%s]" % version,
-                "FEATURE_SELECTED AND &Python%s=3" % version,
-                ordering=order,
-            )
-        c.event("SpawnWaitDialog", "WaitForCostingDlg", ordering=order + 1)
-        c.event("EndDialog", "Return", ordering=order + 2)
-        c = seldlg.cancel("Cancel", "Features")
-        c.event("SpawnDialog", "CancelDlg")
-
-        c = seldlg.control(
-            "Features",
-            "SelectionTree",
-            15,
-            60,
-            300,
-            120,
-            3,
-            "FEATURE",
-            None,
-            "PathEdit",
-            None,
-        )
-        c.event("[FEATURE_SELECTED]", "1")
-        ver = self.other_version
-        install_other_cond = "FEATURE_SELECTED AND &Python%s=3" % ver
-        dont_install_other_cond = "FEATURE_SELECTED AND &Python%s<>3" % ver
-
-        c = seldlg.text(
-            "Other", 15, 200, 300, 15, 3, "Provide an alternate Python location"
-        )
-        c.condition("Enable", install_other_cond)
-        c.condition("Show", install_other_cond)
-        c.condition("Disable", dont_install_other_cond)
-        c.condition("Hide", dont_install_other_cond)
-
-        c = seldlg.control(
-            "PathEdit",
-            "PathEdit",
-            15,
-            215,
-            300,
-            16,
-            1,
-            "TARGETDIR" + ver,
-            None,
-            "Next",
-            None,
-        )
-        c.condition("Enable", install_other_cond)
-        c.condition("Show", install_other_cond)
-        c.condition("Disable", dont_install_other_cond)
-        c.condition("Hide", dont_install_other_cond)
-
-        #####################################################################
-        # Disk cost
-        cost = PyDialog(
-            db, "DiskCostDlg", x, y, w, h, modal, title, "OK", "OK", "OK", bitmap=False
-        )
-        cost.text(
-            "Title", 15, 6, 200, 15, 0x30003, r"{\DlgFontBold8}Disk Space Requirements"
-        )
-        cost.text(
-            "Description",
-            20,
-            20,
-            280,
-            20,
-            0x30003,
-            "The disk space required for the installation of the selected features.",
-        )
-        cost.text(
-            "Text",
-            20,
-            53,
-            330,
-            60,
-            3,
-            "The highlighted volumes (if any) do not have enough disk space "
-            "available for the currently selected features.  You can either "
-            "remove some files from the highlighted volumes, or choose to "
-            "install less features onto local drive(s), or select different "
-            "destination drive(s).",
-        )
-        cost.control(
-            "VolumeList",
-            "VolumeCostList",
-            20,
-            100,
-            330,
-            150,
-            393223,
-            None,
-            "{120}{70}{70}{70}{70}",
-            None,
-            None,
-        )
-        cost.xbutton("OK", "Ok", None, 0.5).event("EndDialog", "Return")
-
-        #####################################################################
-        # WhichUsers Dialog. Only available on NT, and for privileged users.
-        # This must be run before FindRelatedProducts, because that will
-        # take into account whether the previous installation was per-user
-        # or per-machine. We currently don't support going back to this
-        # dialog after "Next" was selected; to support this, we would need to
-        # find how to reset the ALLUSERS property, and how to re-run
-        # FindRelatedProducts.
-        # On Windows9x, the ALLUSERS property is ignored on the command line
-        # and in the Property table, but installer fails according to the documentation
-        # if a dialog attempts to set ALLUSERS.
-        whichusers = PyDialog(
-            db,
-            "WhichUsersDlg",
-            x,
-            y,
-            w,
-            h,
-            modal,
-            title,
-            "AdminInstall",
-            "Next",
-            "Cancel",
-        )
-        whichusers.title(
-            "Select whether to install [ProductName] for all users of this computer."
-        )
-        # A radio group with two options: allusers, justme
-        g = whichusers.radiogroup(
-            "AdminInstall", 15, 60, 260, 50, 3, "WhichUsers", "", "Next"
-        )
-        g.add("ALL", 0, 5, 150, 20, "Install for all users")
-        g.add("JUSTME", 0, 25, 150, 20, "Install just for me")
-
-        whichusers.back("Back", None, active=0)
-
-        c = whichusers.next("Next >", "Cancel")
-        c.event("[ALLUSERS]", "1", 'WhichUsers="ALL"', 1)
-        c.event("EndDialog", "Return", ordering=2)
-
-        c = whichusers.cancel("Cancel", "AdminInstall")
-        c.event("SpawnDialog", "CancelDlg")
-
-        #####################################################################
-        # Installation Progress dialog (modeless)
-        progress = PyDialog(
-            db,
-            "ProgressDlg",
-            x,
-            y,
-            w,
-            h,
-            modeless,
-            title,
-            "Cancel",
-            "Cancel",
-            "Cancel",
-            bitmap=False,
-        )
-        progress.text(
-            "Title",
-            20,
-            15,
-            200,
-            15,
-            0x30003,
-            r"{\DlgFontBold8}[Progress1] [ProductName]",
-        )
-        progress.text(
-            "Text",
-            35,
-            65,
-            300,
-            30,
-            3,
-            "Please wait while the Installer [Progress2] [ProductName]. "
-            "This may take several minutes.",
-        )
-        progress.text("StatusLabel", 35, 100, 35, 20, 3, "Status:")
-
-        c = progress.text("ActionText", 70, 100, w - 70, 20, 3, "Pondering...")
-        c.mapping("ActionText", "Text")
-
-        # c=progress.text("ActionData", 35, 140, 300, 20, 3, None)
-        # c.mapping("ActionData", "Text")
-
-        c = progress.control(
-            "ProgressBar",
-            "ProgressBar",
-            35,
-            120,
-            300,
-            10,
-            65537,
-            None,
-            "Progress done",
-            None,
-            None,
-        )
-        c.mapping("SetProgress", "Progress")
-
-        progress.back("< Back", "Next", active=False)
-        progress.next("Next >", "Cancel", active=False)
-        progress.cancel("Cancel", "Back").event("SpawnDialog", "CancelDlg")
-
-        ###################################################################
-        # Maintenance type: repair/uninstall
-        maint = PyDialog(
-            db, "MaintenanceTypeDlg", x, y, w, h, modal, title, "Next", "Next", "Cancel"
-        )
-        maint.title("Welcome to the [ProductName] Setup Wizard")
-        maint.text(
-            "BodyText",
-            15,
-            63,
-            330,
-            42,
-            3,
-            "Select whether you want to repair or remove [ProductName].",
-        )
-        g = maint.radiogroup(
-            "RepairRadioGroup",
-            15,
-            108,
-            330,
-            60,
-            3,
-            "MaintenanceForm_Action",
-            "",
-            "Next",
-        )
-        # g.add("Change", 0, 0, 200, 17, "&Change [ProductName]")
-        g.add("Repair", 0, 18, 200, 17, "&Repair [ProductName]")
-        g.add("Remove", 0, 36, 200, 17, "Re&move [ProductName]")
-
-        maint.back("< Back", None, active=False)
-        c = maint.next("Finish", "Cancel")
-        # Change installation: Change progress dialog to "Change", then ask
-        # for feature selection
-        # c.event("[Progress1]", "Change", 'MaintenanceForm_Action="Change"', 1)
-        # c.event("[Progress2]", "changes", 'MaintenanceForm_Action="Change"', 2)
-
-        # Reinstall: Change progress dialog to "Repair", then invoke reinstall
-        # Also set list of reinstalled features to "ALL"
-        c.event("[REINSTALL]", "ALL", 'MaintenanceForm_Action="Repair"', 5)
-        c.event("[Progress1]", "Repairing", 'MaintenanceForm_Action="Repair"', 6)
-        c.event("[Progress2]", "repairs", 'MaintenanceForm_Action="Repair"', 7)
-        c.event("Reinstall", "ALL", 'MaintenanceForm_Action="Repair"', 8)
-
-        # Uninstall: Change progress to "Remove", then invoke uninstall
-        # Also set list of removed features to "ALL"
-        c.event("[REMOVE]", "ALL", 'MaintenanceForm_Action="Remove"', 11)
-        c.event("[Progress1]", "Removing", 'MaintenanceForm_Action="Remove"', 12)
-        c.event("[Progress2]", "removes", 'MaintenanceForm_Action="Remove"', 13)
-        c.event("Remove", "ALL", 'MaintenanceForm_Action="Remove"', 14)
-
-        # Close dialog when maintenance action scheduled
-        c.event("EndDialog", "Return", 'MaintenanceForm_Action<>"Change"', 20)
-
-        maint.cancel("Cancel", "RepairRadioGroup").event("SpawnDialog", "CancelDlg")
-
-    def get_installer_filename(self, fullname):
-        # Factored out to allow overriding in subclasses
-        if self.target_version:
-            base_name = "{}.{}-py{}.msi".format(
-                fullname,
-                self.plat_name,
-                self.target_version,
-            )
-        else:
-            base_name = "{}.{}.msi".format(fullname, self.plat_name)
-        installer_name = os.path.join(self.dist_dir, base_name)
-        return installer_name
diff --git a/setuptools/_distutils/command/bdist_wininst.py b/setuptools/_distutils/command/bdist_wininst.py
deleted file mode 100644 (file)
index 02bd720..0000000
+++ /dev/null
@@ -1,418 +0,0 @@
-"""distutils.command.bdist_wininst
-
-Implements the Distutils 'bdist_wininst' command: create a windows installer
-exe-program."""
-
-import os
-import sys
-import warnings
-from distutils.core import Command
-from distutils.util import get_platform
-from distutils.dir_util import remove_tree
-from distutils.errors import DistutilsOptionError, DistutilsPlatformError
-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"),
-        (
-            'plat-name=',
-            'p',
-            "platform name to embed in generated filenames "
-            "(default: %s)" % get_platform(),
-        ),
-        (
-            'keep-temp',
-            'k',
-            "keep the pseudo-installation tree around after "
-            + "creating the distribution archive",
-        ),
-        (
-            'target-version=',
-            None,
-            "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",
-        ),
-        (
-            '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",
-        ),
-        (
-            '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",
-        ),
-    ]
-
-    boolean_options = [
-        'keep-temp',
-        'no-target-compile',
-        'no-target-optimize',
-        'skip-build',
-    ]
-
-    # bpo-10945: bdist_wininst requires mbcs encoding only available on Windows
-    _unsupported = sys.platform != "win32"
-
-    def __init__(self, *args, **kw):
-        super().__init__(*args, **kw)
-        warnings.warn(
-            "bdist_wininst command is deprecated since Python 3.8, "
-            "use bdist_wheel (wheel packages) instead",
-            DeprecationWarning,
-            2,
-        )
-
-    def initialize_options(self):
-        self.bdist_dir = None
-        self.plat_name = 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 = None
-        self.install_script = None
-        self.pre_install_script = None
-        self.user_access_control = None
-
-    def finalize_options(self):
-        self.set_undefined_options('bdist', ('skip_build', 'skip_build'))
-
-        if self.bdist_dir is None:
-            if self.skip_build and self.plat_name:
-                # If build is skipped and plat_name is overridden, bdist will
-                # not see the correct 'plat_name' - so set that up manually.
-                bdist = self.distribution.get_command_obj('bdist')
-                bdist.plat_name = self.plat_name
-                # next the command will be initialized using that name
-            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 not self.skip_build and 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 %s, or the '--skip-build'"
-                    " option must be specified" % (short_version,)
-                )
-            self.target_version = short_version
-
-        self.set_undefined_options(
-            'bdist',
-            ('dist_dir', 'dist_dir'),
-            ('plat_name', 'plat_name'),
-        )
-
-        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
-                )
-
-    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.plat_name = self.plat_name
-
-        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
-
-        if self.distribution.has_ext_modules():
-            # If we are building an installer for a Python version other
-            # than the one we are currently running, then we need to ensure
-            # our build_lib reflects the other Python version rather than ours.
-            # Note that for target_version!=sys.version, we must have skipped the
-            # build step, so there is no issue with enforcing the build of this
-            # version.
-            target_version = self.target_version
-            if not target_version:
-                assert self.skip_build, "Should have already checked this"
-                target_version = '%d.%d' % sys.version_info[:2]
-            plat_specifier = ".{}-{}".format(self.plat_name, target_version)
-            build = self.get_finalized_command('build')
-            build.build_lib = os.path.join(build.build_base, 'lib' + plat_specifier)
-
-        # 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 = key.upper()
-            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)
-        if self.distribution.has_ext_modules():
-            pyversion = get_python_version()
-        else:
-            pyversion = 'any'
-        self.distribution.dist_files.append(
-            ('bdist_wininst', pyversion, self.get_installer_filename(fullname))
-        )
-        # 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)
-
-    def get_inidata(self):
-        # Return data describing the installation.
-        lines = []
-        metadata = self.distribution.metadata
-
-        # Write the [metadata] section.
-        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'
-
-        # Escape newline characters
-        def escape(s):
-            return s.replace("\n", "\\n")
-
-        for name in [
-            "author",
-            "author_email",
-            "description",
-            "maintainer",
-            "maintainer_email",
-            "name",
-            "url",
-            "version",
-        ]:
-            data = getattr(metadata, name, "")
-            if data:
-                info = info + ("\n    {}: {}".format(name.capitalize(), escape(data)))
-                lines.append("{}={}".format(name, escape(data)))
-
-        # 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" % escape(info))
-        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)
-        if self.user_access_control:
-            lines.append("user_access_control=%s" % self.user_access_control)
-
-        title = self.title or self.distribution.get_fullname()
-        lines.append("title=%s" % escape(title))
-        import time
-        import distutils
-
-        build_info = "Built {} with distutils-{}".format(
-            time.ctime(time.time()),
-            distutils.__version__,
-        )
-        lines.append("build_info=%s" % build_info)
-        return "\n".join(lines)
-
-    def create_exe(self, arcname, fullname, bitmap=None):
-        import struct
-
-        self.mkpath(self.dist_dir)
-
-        cfgdata = self.get_inidata()
-
-        installer_name = self.get_installer_filename(fullname)
-        self.announce("creating %s" % installer_name)
-
-        if bitmap:
-            with open(bitmap, "rb") as f:
-                bitmapdata = f.read()
-            bitmaplen = len(bitmapdata)
-        else:
-            bitmaplen = 0
-
-        with open(installer_name, "wb") as file:
-            file.write(self.get_exe_bytes())
-            if bitmap:
-                file.write(bitmapdata)
-
-            # Convert cfgdata from unicode to ascii, mbcs encoded
-            if isinstance(cfgdata, str):
-                cfgdata = cfgdata.encode("mbcs")
-
-            # Append the pre-install script
-            cfgdata = cfgdata + b"\0"
-            if self.pre_install_script:
-                # We need to normalize newlines, so we open in text mode and
-                # convert back to bytes. "latin-1" simply avoids any possible
-                # failures.
-                with open(self.pre_install_script, encoding="latin-1") as script:
-                    script_data = script.read().encode("latin-1")
-                cfgdata = cfgdata + script_data + b"\n\0"
-            else:
-                # empty pre-install script
-                cfgdata = cfgdata + b"\0"
-            file.write(cfgdata)
-
-            # The 'magic number' 0x1234567B is used to make sure that the
-            # binary layout of 'cfgdata' is what the wininst.exe binary
-            # expects.  If the layout changes, increment that number, make
-            # the corresponding changes to the wininst.exe sources, and
-            # recompile them.
-            header = struct.pack(
-                "<iii",
-                0x1234567B,  # tag
-                len(cfgdata),  # length
-                bitmaplen,  # number of bytes in bitmap
-            )
-            file.write(header)
-            with open(arcname, "rb") as f:
-                file.write(f.read())
-
-    def get_installer_filename(self, fullname):
-        # Factored out to allow overriding in subclasses
-        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,
-                "{}.{}-py{}.exe".format(fullname, self.plat_name, self.target_version),
-            )
-        else:
-            installer_name = os.path.join(
-                self.dist_dir, "{}.{}.exe".format(fullname, self.plat_name)
-            )
-        return installer_name
-
-    def get_exe_bytes(self):  # noqa: C901
-        # If a target-version other than the current version has been
-        # specified, then using the MSVC version from *this* build is no good.
-        # Without actually finding and executing the target version and parsing
-        # its sys.version, we just hard-code our knowledge of old versions.
-        # NOTE: Possible alternative is to allow "--target-version" to
-        # specify a Python executable rather than a simple version string.
-        # We can then execute this program to obtain any info we need, such
-        # as the real sys.version string for the build.
-        cur_version = get_python_version()
-
-        # If the target version is *later* than us, then we assume they
-        # use what we use
-        # string compares seem wrong, but are what sysconfig.py itself uses
-        if self.target_version and self.target_version < cur_version:
-            if self.target_version < "2.4":
-                bv = '6.0'
-            elif self.target_version == "2.4":
-                bv = '7.1'
-            elif self.target_version == "2.5":
-                bv = '8.0'
-            elif self.target_version <= "3.2":
-                bv = '9.0'
-            elif self.target_version <= "3.4":
-                bv = '10.0'
-            else:
-                bv = '14.0'
-        else:
-            # for current version - use authoritative check.
-            try:
-                from msvcrt import CRT_ASSEMBLY_VERSION
-            except ImportError:
-                # cross-building, so assume the latest version
-                bv = '14.0'
-            else:
-                # as far as we know, CRT is binary compatible based on
-                # the first field, so assume 'x.0' until proven otherwise
-                major = CRT_ASSEMBLY_VERSION.partition('.')[0]
-                bv = major + '.0'
-
-        # wininst-x.y.exe is in the same directory as this file
-        directory = os.path.dirname(__file__)
-        # we must use a wininst-x.y.exe built with the same C compiler
-        # used for python.  XXX What about mingw, borland, and so on?
-
-        # if plat_name starts with "win" but is not "win32"
-        # we want to strip "win" and leave the rest (e.g. -amd64)
-        # for all other cases, we don't want any suffix
-        if self.plat_name != 'win32' and self.plat_name[:3] == 'win':
-            sfix = self.plat_name[3:]
-        else:
-            sfix = ''
-
-        filename = os.path.join(directory, "wininst-{}{}.exe".format(bv, sfix))
-        f = open(filename, "rb")
-        try:
-            return f.read()
-        finally:
-            f.close()
index 2c6dbae83fbddf4b16e01296efe8f34971bb924f..63910f2ac88d857669117e9d6d2d6c02abb3cab8 100644 (file)
@@ -6,47 +6,6 @@ the Mingw32CCompiler class which handles the mingw32 port of GCC (same as
 cygwin in no-cygwin mode).
 """
 
-# problems:
-#
-# * if you use a msvc compiled python version (1.5.2)
-#   1. you have to insert a __GNUC__ section in its config.h
-#   2. you have to generate an import library for its dll
-#      - create a def-file for python??.dll
-#      - create an import library using
-#             dlltool --dllname python15.dll --def python15.def \
-#                       --output-lib libpython15.a
-#
-#   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
-#
-# * We put export_symbols in a def-file, and don't use
-#   --export-all-symbols because it doesn't worked reliable in some
-#   tested configurations. And because other windows compilers also
-#   need their symbols specified this no serious problem.
-#
-# tested configurations:
-#
-# * cygwin gcc 2.91.57/ld 2.9.4/dllwrap 0.2.4 works
-#   (after patching python's config.h and for C++ some other include files)
-#   see also http://starship.python.net/crew/kernr/mingw32/Notes.html
-# * mingw32 gcc 2.95.2/ld 2.9.4/dllwrap 0.2.4 works
-#   (ld doesn't support -shared, so we use dllwrap)
-# * cygwin gcc 2.95.2/ld 2.10.90/dllwrap 2.10.90 works now
-#   - its dllwrap doesn't work, there is a bug in binutils 2.10.90
-#     see also http://sources.redhat.com/ml/cygwin/2000-06/msg01274.html
-#   - using gcc -mdll instead dllwrap doesn't work without -static because
-#     it tries to link against dlls instead their import libraries. (If
-#     it finds the dll first.)
-#     By specifying -static we force ld to link against the import libraries,
-#     this is windows standard and there are normally not the necessary symbols
-#     in the dlls.
-#   *** only the version of June 2000 shows these problems
-# * cygwin gcc 3.2/ld 2.13.90 works
-#   (ld supports -shared)
-# * mingw gcc 3.2/ld 2.13 works
-#   (ld supports -shared)
-# * llvm-mingw with Clang 11 works
-#   (lld supports -shared)
-
 import os
 import sys
 import copy
diff --git a/setuptools/_distutils/msvc9compiler.py b/setuptools/_distutils/msvc9compiler.py
deleted file mode 100644 (file)
index 62075c0..0000000
+++ /dev/null
@@ -1,824 +0,0 @@
-"""distutils.msvc9compiler
-
-Contains MSVCCompiler, an implementation of the abstract CCompiler class
-for the Microsoft Visual Studio 2008.
-
-The module is compatible with VS 2005 and VS 2008. You can find legacy support
-for older versions of VS in distutils.msvccompiler.
-"""
-
-# Written by Perry Stoll
-# hacked by Robin Becker and Thomas Heller to do a better job of
-#   finding DevStudio (through the registry)
-# ported to VS2005 and VS 2008 by Christian Heimes
-
-import os
-import subprocess
-import sys
-import re
-
-from distutils.errors import (
-    DistutilsExecError,
-    DistutilsPlatformError,
-    CompileError,
-    LibError,
-    LinkError,
-)
-from distutils.ccompiler import CCompiler, gen_lib_options
-from distutils import log
-from distutils.util import get_platform
-
-import winreg
-
-RegOpenKeyEx = winreg.OpenKeyEx
-RegEnumKey = winreg.EnumKey
-RegEnumValue = winreg.EnumValue
-RegError = winreg.error
-
-HKEYS = (
-    winreg.HKEY_USERS,
-    winreg.HKEY_CURRENT_USER,
-    winreg.HKEY_LOCAL_MACHINE,
-    winreg.HKEY_CLASSES_ROOT,
-)
-
-NATIVE_WIN64 = sys.platform == 'win32' and sys.maxsize > 2**32
-if NATIVE_WIN64:
-    # Visual C++ is a 32-bit application, so we need to look in
-    # the corresponding registry branch, if we're running a
-    # 64-bit Python on Win64
-    VS_BASE = r"Software\Wow6432Node\Microsoft\VisualStudio\%0.1f"
-    WINSDK_BASE = r"Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows"
-    NET_BASE = r"Software\Wow6432Node\Microsoft\.NETFramework"
-else:
-    VS_BASE = r"Software\Microsoft\VisualStudio\%0.1f"
-    WINSDK_BASE = r"Software\Microsoft\Microsoft SDKs\Windows"
-    NET_BASE = r"Software\Microsoft\.NETFramework"
-
-# A map keyed by get_platform() return values to values accepted by
-# 'vcvarsall.bat'.  Note a cross-compile may combine these (eg, 'x86_amd64' is
-# the param to cross-compile on x86 targeting amd64.)
-PLAT_TO_VCVARS = {
-    'win32': 'x86',
-    'win-amd64': 'amd64',
-}
-
-
-class Reg:
-    """Helper class to read values from the registry"""
-
-    def get_value(cls, path, key):
-        for base in HKEYS:
-            d = cls.read_values(base, path)
-            if d and key in d:
-                return d[key]
-        raise KeyError(key)
-
-    get_value = classmethod(get_value)
-
-    def read_keys(cls, base, key):
-        """Return list of registry keys."""
-        try:
-            handle = RegOpenKeyEx(base, key)
-        except RegError:
-            return None
-        L = []
-        i = 0
-        while True:
-            try:
-                k = RegEnumKey(handle, i)
-            except RegError:
-                break
-            L.append(k)
-            i += 1
-        return L
-
-    read_keys = classmethod(read_keys)
-
-    def read_values(cls, base, key):
-        """Return dict of registry keys and values.
-
-        All names are converted to lowercase.
-        """
-        try:
-            handle = RegOpenKeyEx(base, key)
-        except RegError:
-            return None
-        d = {}
-        i = 0
-        while True:
-            try:
-                name, value, type = RegEnumValue(handle, i)
-            except RegError:
-                break
-            name = name.lower()
-            d[cls.convert_mbcs(name)] = cls.convert_mbcs(value)
-            i += 1
-        return d
-
-    read_values = classmethod(read_values)
-
-    def convert_mbcs(s):
-        dec = getattr(s, "decode", None)
-        if dec is not None:
-            try:
-                s = dec("mbcs")
-            except UnicodeError:
-                pass
-        return s
-
-    convert_mbcs = staticmethod(convert_mbcs)
-
-
-class MacroExpander:
-    def __init__(self, version):
-        self.macros = {}
-        self.vsbase = VS_BASE % version
-        self.load_macros(version)
-
-    def set_macro(self, macro, path, key):
-        self.macros["$(%s)" % macro] = Reg.get_value(path, key)
-
-    def load_macros(self, version):
-        self.set_macro("VCInstallDir", self.vsbase + r"\Setup\VC", "productdir")
-        self.set_macro("VSInstallDir", self.vsbase + r"\Setup\VS", "productdir")
-        self.set_macro("FrameworkDir", NET_BASE, "installroot")
-        try:
-            if version >= 8.0:
-                self.set_macro("FrameworkSDKDir", NET_BASE, "sdkinstallrootv2.0")
-            else:
-                raise KeyError("sdkinstallrootv2.0")
-        except KeyError:
-            raise DistutilsPlatformError(
-                """Python was built with Visual Studio 2008;
-extensions must be built with a compiler than can generate compatible binaries.
-Visual Studio 2008 was not found on this system. If you have Cygwin installed,
-you can try compiling with MingW32, by passing "-c mingw32" to setup.py."""
-            )
-
-        if version >= 9.0:
-            self.set_macro("FrameworkVersion", self.vsbase, "clr version")
-            self.set_macro("WindowsSdkDir", WINSDK_BASE, "currentinstallfolder")
-        else:
-            p = r"Software\Microsoft\NET Framework Setup\Product"
-            for base in HKEYS:
-                try:
-                    h = RegOpenKeyEx(base, p)
-                except RegError:
-                    continue
-                key = RegEnumKey(h, 0)
-                d = Reg.get_value(base, r"{}\{}".format(p, key))
-                self.macros["$(FrameworkVersion)"] = d["version"]
-
-    def sub(self, s):
-        for k, v in self.macros.items():
-            s = s.replace(k, v)
-        return s
-
-
-def get_build_version():
-    """Return the version of MSVC that was used to build Python.
-
-    For Python 2.3 and up, the version number is included in
-    sys.version.  For earlier versions, assume the compiler is MSVC 6.
-    """
-    prefix = "MSC v."
-    i = sys.version.find(prefix)
-    if i == -1:
-        return 6
-    i = i + len(prefix)
-    s, rest = sys.version[i:].split(" ", 1)
-    majorVersion = int(s[:-2]) - 6
-    if majorVersion >= 13:
-        # v13 was skipped and should be v14
-        majorVersion += 1
-    minorVersion = int(s[2:3]) / 10.0
-    # I don't think paths are affected by minor version in version 6
-    if majorVersion == 6:
-        minorVersion = 0
-    if majorVersion >= 6:
-        return majorVersion + minorVersion
-    # else we don't know what version of the compiler this is
-    return None
-
-
-def normalize_and_reduce_paths(paths):
-    """Return a list of normalized paths with duplicates removed.
-
-    The current order of paths is maintained.
-    """
-    # Paths are normalized so things like:  /a and /a/ aren't both preserved.
-    reduced_paths = []
-    for p in paths:
-        np = os.path.normpath(p)
-        # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
-        if np not in reduced_paths:
-            reduced_paths.append(np)
-    return reduced_paths
-
-
-def removeDuplicates(variable):
-    """Remove duplicate values of an environment variable."""
-    oldList = variable.split(os.pathsep)
-    newList = []
-    for i in oldList:
-        if i not in newList:
-            newList.append(i)
-    newVariable = os.pathsep.join(newList)
-    return newVariable
-
-
-def find_vcvarsall(version):
-    """Find the vcvarsall.bat file
-
-    At first it tries to find the productdir of VS 2008 in the registry. If
-    that fails it falls back to the VS90COMNTOOLS env var.
-    """
-    vsbase = VS_BASE % version
-    try:
-        productdir = Reg.get_value(r"%s\Setup\VC" % vsbase, "productdir")
-    except KeyError:
-        log.debug("Unable to find productdir in registry")
-        productdir = None
-
-    if not productdir or not os.path.isdir(productdir):
-        toolskey = "VS%0.f0COMNTOOLS" % version
-        toolsdir = os.environ.get(toolskey, None)
-
-        if toolsdir and os.path.isdir(toolsdir):
-            productdir = os.path.join(toolsdir, os.pardir, os.pardir, "VC")
-            productdir = os.path.abspath(productdir)
-            if not os.path.isdir(productdir):
-                log.debug("%s is not a valid directory" % productdir)
-                return None
-        else:
-            log.debug("Env var %s is not set or invalid" % toolskey)
-    if not productdir:
-        log.debug("No productdir found")
-        return None
-    vcvarsall = os.path.join(productdir, "vcvarsall.bat")
-    if os.path.isfile(vcvarsall):
-        return vcvarsall
-    log.debug("Unable to find vcvarsall.bat")
-    return None
-
-
-def query_vcvarsall(version, arch="x86"):
-    """Launch vcvarsall.bat and read the settings from its environment"""
-    vcvarsall = find_vcvarsall(version)
-    interesting = {"include", "lib", "libpath", "path"}
-    result = {}
-
-    if vcvarsall is None:
-        raise DistutilsPlatformError("Unable to find vcvarsall.bat")
-    log.debug("Calling 'vcvarsall.bat %s' (version=%s)", arch, version)
-    popen = subprocess.Popen(
-        '"{}" {} & set'.format(vcvarsall, arch),
-        stdout=subprocess.PIPE,
-        stderr=subprocess.PIPE,
-    )
-    try:
-        stdout, stderr = popen.communicate()
-        if popen.wait() != 0:
-            raise DistutilsPlatformError(stderr.decode("mbcs"))
-
-        stdout = stdout.decode("mbcs")
-        for line in stdout.split("\n"):
-            line = Reg.convert_mbcs(line)
-            if '=' not in line:
-                continue
-            line = line.strip()
-            key, value = line.split('=', 1)
-            key = key.lower()
-            if key in interesting:
-                if value.endswith(os.pathsep):
-                    value = value[:-1]
-                result[key] = removeDuplicates(value)
-
-    finally:
-        popen.stdout.close()
-        popen.stderr.close()
-
-    if len(result) != len(interesting):
-        raise ValueError(str(list(result.keys())))
-
-    return result
-
-
-# More globals
-VERSION = get_build_version()
-# MACROS = MacroExpander(VERSION)
-
-
-class MSVCCompiler(CCompiler):
-    """Concrete class that implements an interface to Microsoft Visual C++,
-    as defined by the CCompiler abstract class."""
-
-    compiler_type = 'msvc'
-
-    # Just set this so CCompiler's constructor doesn't barf.  We currently
-    # don't use the 'set_executables()' bureaucracy provided by CCompiler,
-    # as it really isn't necessary for this sort of single-compiler class.
-    # Would be nice to have a consistent interface with UnixCCompiler,
-    # though, so it's worth thinking about.
-    executables = {}
-
-    # Private class data (need to distinguish C from C++ source for compiler)
-    _c_extensions = ['.c']
-    _cpp_extensions = ['.cc', '.cpp', '.cxx']
-    _rc_extensions = ['.rc']
-    _mc_extensions = ['.mc']
-
-    # Needed for the filename generation methods provided by the
-    # base class, CCompiler.
-    src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions
-    res_extension = '.res'
-    obj_extension = '.obj'
-    static_lib_extension = '.lib'
-    shared_lib_extension = '.dll'
-    static_lib_format = shared_lib_format = '%s%s'
-    exe_extension = '.exe'
-
-    def __init__(self, verbose=0, dry_run=0, force=0):
-        super().__init__(verbose, dry_run, force)
-        self.__version = VERSION
-        self.__root = r"Software\Microsoft\VisualStudio"
-        # self.__macros = MACROS
-        self.__paths = []
-        # target platform (.plat_name is consistent with 'bdist')
-        self.plat_name = None
-        self.__arch = None  # deprecated name
-        self.initialized = False
-
-    def initialize(self, plat_name=None):  # noqa: C901
-        # multi-init means we would need to check platform same each time...
-        assert not self.initialized, "don't init multiple times"
-        if self.__version < 8.0:
-            raise DistutilsPlatformError(
-                "VC %0.1f is not supported by this module" % self.__version
-            )
-        if plat_name is None:
-            plat_name = get_platform()
-        # sanity check for platforms to prevent obscure errors later.
-        ok_plats = 'win32', 'win-amd64'
-        if plat_name not in ok_plats:
-            raise DistutilsPlatformError(
-                "--plat-name must be one of {}".format(ok_plats)
-            )
-
-        if (
-            "DISTUTILS_USE_SDK" in os.environ
-            and "MSSdk" in os.environ
-            and self.find_exe("cl.exe")
-        ):
-            # Assume that the SDK set up everything alright; don't try to be
-            # smarter
-            self.cc = "cl.exe"
-            self.linker = "link.exe"
-            self.lib = "lib.exe"
-            self.rc = "rc.exe"
-            self.mc = "mc.exe"
-        else:
-            # On x86, 'vcvars32.bat amd64' creates an env that doesn't work;
-            # to cross compile, you use 'x86_amd64'.
-            # On AMD64, 'vcvars32.bat amd64' is a native build env; to cross
-            # compile use 'x86' (ie, it runs the x86 compiler directly)
-            if plat_name == get_platform() or plat_name == 'win32':
-                # native build or cross-compile to win32
-                plat_spec = PLAT_TO_VCVARS[plat_name]
-            else:
-                # cross compile from win32 -> some 64bit
-                plat_spec = (
-                    PLAT_TO_VCVARS[get_platform()] + '_' + PLAT_TO_VCVARS[plat_name]
-                )
-
-            vc_env = query_vcvarsall(VERSION, plat_spec)
-
-            self.__paths = vc_env['path'].split(os.pathsep)
-            os.environ['lib'] = vc_env['lib']
-            os.environ['include'] = vc_env['include']
-
-            if len(self.__paths) == 0:
-                raise DistutilsPlatformError(
-                    "Python was built with %s, "
-                    "and extensions need to be built with the same "
-                    "version of the compiler, but it isn't installed." % self.__product
-                )
-
-            self.cc = self.find_exe("cl.exe")
-            self.linker = self.find_exe("link.exe")
-            self.lib = self.find_exe("lib.exe")
-            self.rc = self.find_exe("rc.exe")  # resource compiler
-            self.mc = self.find_exe("mc.exe")  # message compiler
-            # self.set_path_env_var('lib')
-            # self.set_path_env_var('include')
-
-        # extend the MSVC path with the current path
-        try:
-            for p in os.environ['path'].split(';'):
-                self.__paths.append(p)
-        except KeyError:
-            pass
-        self.__paths = normalize_and_reduce_paths(self.__paths)
-        os.environ['path'] = ";".join(self.__paths)
-
-        self.preprocess_options = None
-        if self.__arch == "x86":
-            self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/DNDEBUG']
-            self.compile_options_debug = [
-                '/nologo',
-                '/Od',
-                '/MDd',
-                '/W3',
-                '/Z7',
-                '/D_DEBUG',
-            ]
-        else:
-            # Win64
-            self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/GS-', '/DNDEBUG']
-            self.compile_options_debug = [
-                '/nologo',
-                '/Od',
-                '/MDd',
-                '/W3',
-                '/GS-',
-                '/Z7',
-                '/D_DEBUG',
-            ]
-
-        self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
-        if self.__version >= 7:
-            self.ldflags_shared_debug = ['/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG']
-        self.ldflags_static = ['/nologo']
-
-        self.initialized = True
-
-    # -- Worker methods ------------------------------------------------
-
-    def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
-        # Copied from ccompiler.py, extended to return .res as 'object'-file
-        # for .rc input file
-        if output_dir is None:
-            output_dir = ''
-        obj_names = []
-        for src_name in source_filenames:
-            (base, ext) = os.path.splitext(src_name)
-            base = os.path.splitdrive(base)[1]  # Chop off the drive
-            base = base[os.path.isabs(base) :]  # If abs, chop off leading /
-            if ext not in self.src_extensions:
-                # Better to raise an exception instead of silently continuing
-                # and later complain about sources and targets having
-                # different lengths
-                raise CompileError("Don't know how to compile %s" % src_name)
-            if strip_dir:
-                base = os.path.basename(base)
-            if ext in self._rc_extensions:
-                obj_names.append(os.path.join(output_dir, base + self.res_extension))
-            elif ext in self._mc_extensions:
-                obj_names.append(os.path.join(output_dir, base + self.res_extension))
-            else:
-                obj_names.append(os.path.join(output_dir, base + self.obj_extension))
-        return obj_names
-
-    def compile(  # noqa: C901
-        self,
-        sources,
-        output_dir=None,
-        macros=None,
-        include_dirs=None,
-        debug=0,
-        extra_preargs=None,
-        extra_postargs=None,
-        depends=None,
-    ):
-
-        if not self.initialized:
-            self.initialize()
-        compile_info = self._setup_compile(
-            output_dir, macros, include_dirs, sources, depends, extra_postargs
-        )
-        macros, objects, extra_postargs, pp_opts, build = compile_info
-
-        compile_opts = extra_preargs or []
-        compile_opts.append('/c')
-        if debug:
-            compile_opts.extend(self.compile_options_debug)
-        else:
-            compile_opts.extend(self.compile_options)
-
-        for obj in objects:
-            try:
-                src, ext = build[obj]
-            except KeyError:
-                continue
-            if debug:
-                # pass the full pathname to MSVC in debug mode,
-                # this allows the debugger to find the source file
-                # without asking the user to browse for it
-                src = os.path.abspath(src)
-
-            if ext in self._c_extensions:
-                input_opt = "/Tc" + src
-            elif ext in self._cpp_extensions:
-                input_opt = "/Tp" + src
-            elif ext in self._rc_extensions:
-                # compile .RC to .RES file
-                input_opt = src
-                output_opt = "/fo" + obj
-                try:
-                    self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt])
-                except DistutilsExecError as msg:
-                    raise CompileError(msg)
-                continue
-            elif ext in self._mc_extensions:
-                # Compile .MC to .RC file to .RES file.
-                #   * '-h dir' specifies the directory for the
-                #     generated include file
-                #   * '-r dir' specifies the target directory of the
-                #     generated RC file and the binary message resource
-                #     it includes
-                #
-                # For now (since there are no options to change this),
-                # we use the source-directory for the include file and
-                # the build directory for the RC file and message
-                # resources. This works at least for win32all.
-                h_dir = os.path.dirname(src)
-                rc_dir = os.path.dirname(obj)
-                try:
-                    # first compile .MC to .RC and .H file
-                    self.spawn([self.mc] + ['-h', h_dir, '-r', rc_dir] + [src])
-                    base, _ = os.path.splitext(os.path.basename(src))
-                    rc_file = os.path.join(rc_dir, base + '.rc')
-                    # then compile .RC to .RES file
-                    self.spawn([self.rc] + ["/fo" + obj] + [rc_file])
-
-                except DistutilsExecError as msg:
-                    raise CompileError(msg)
-                continue
-            else:
-                # how to handle this file?
-                raise CompileError(
-                    "Don't know how to compile {} to {}".format(src, obj)
-                )
-
-            output_opt = "/Fo" + obj
-            try:
-                self.spawn(
-                    [self.cc]
-                    + compile_opts
-                    + pp_opts
-                    + [input_opt, output_opt]
-                    + extra_postargs
-                )
-            except DistutilsExecError as msg:
-                raise CompileError(msg)
-
-        return objects
-
-    def create_static_lib(
-        self, objects, output_libname, output_dir=None, debug=0, target_lang=None
-    ):
-
-        if not self.initialized:
-            self.initialize()
-        (objects, output_dir) = self._fix_object_args(objects, output_dir)
-        output_filename = self.library_filename(output_libname, output_dir=output_dir)
-
-        if self._need_link(objects, output_filename):
-            lib_args = objects + ['/OUT:' + output_filename]
-            if debug:
-                pass  # XXX what goes here?
-            try:
-                self.spawn([self.lib] + lib_args)
-            except DistutilsExecError as msg:
-                raise LibError(msg)
-        else:
-            log.debug("skipping %s (up-to-date)", output_filename)
-
-    def link(  # noqa: C901
-        self,
-        target_desc,
-        objects,
-        output_filename,
-        output_dir=None,
-        libraries=None,
-        library_dirs=None,
-        runtime_library_dirs=None,
-        export_symbols=None,
-        debug=0,
-        extra_preargs=None,
-        extra_postargs=None,
-        build_temp=None,
-        target_lang=None,
-    ):
-
-        if not self.initialized:
-            self.initialize()
-        (objects, output_dir) = self._fix_object_args(objects, output_dir)
-        fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
-        (libraries, library_dirs, runtime_library_dirs) = fixed_args
-
-        if runtime_library_dirs:
-            self.warn(
-                "I don't know what to do with 'runtime_library_dirs': "
-                + str(runtime_library_dirs)
-            )
-
-        lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
-        if output_dir is not None:
-            output_filename = os.path.join(output_dir, output_filename)
-
-        if self._need_link(objects, output_filename):
-            if target_desc == CCompiler.EXECUTABLE:
-                if debug:
-                    ldflags = self.ldflags_shared_debug[1:]
-                else:
-                    ldflags = self.ldflags_shared[1:]
-            else:
-                if debug:
-                    ldflags = self.ldflags_shared_debug
-                else:
-                    ldflags = self.ldflags_shared
-
-            export_opts = []
-            for sym in export_symbols or []:
-                export_opts.append("/EXPORT:" + sym)
-
-            ld_args = (
-                ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
-            )
-
-            # The MSVC linker generates .lib and .exp files, which cannot be
-            # suppressed by any linker switches. The .lib files may even be
-            # needed! Make sure they are generated in the temporary build
-            # directory. Since they have different names for debug and release
-            # builds, they can go into the same directory.
-            build_temp = os.path.dirname(objects[0])
-            if export_symbols is not None:
-                (dll_name, dll_ext) = os.path.splitext(
-                    os.path.basename(output_filename)
-                )
-                implib_file = os.path.join(build_temp, self.library_filename(dll_name))
-                ld_args.append('/IMPLIB:' + implib_file)
-
-            self.manifest_setup_ldargs(output_filename, build_temp, ld_args)
-
-            if extra_preargs:
-                ld_args[:0] = extra_preargs
-            if extra_postargs:
-                ld_args.extend(extra_postargs)
-
-            self.mkpath(os.path.dirname(output_filename))
-            try:
-                self.spawn([self.linker] + ld_args)
-            except DistutilsExecError as msg:
-                raise LinkError(msg)
-
-            # embed the manifest
-            # XXX - this is somewhat fragile - if mt.exe fails, distutils
-            # will still consider the DLL up-to-date, but it will not have a
-            # manifest.  Maybe we should link to a temp file?  OTOH, that
-            # implies a build environment error that shouldn't go undetected.
-            mfinfo = self.manifest_get_embed_info(target_desc, ld_args)
-            if mfinfo is not None:
-                mffilename, mfid = mfinfo
-                out_arg = '-outputresource:{};{}'.format(output_filename, mfid)
-                try:
-                    self.spawn(['mt.exe', '-nologo', '-manifest', mffilename, out_arg])
-                except DistutilsExecError as msg:
-                    raise LinkError(msg)
-        else:
-            log.debug("skipping %s (up-to-date)", output_filename)
-
-    def manifest_setup_ldargs(self, output_filename, build_temp, ld_args):
-        # If we need a manifest at all, an embedded manifest is recommended.
-        # See MSDN article titled
-        # "How to: Embed a Manifest Inside a C/C++ Application"
-        # (currently at http://msdn2.microsoft.com/en-us/library/ms235591(VS.80).aspx)
-        # Ask the linker to generate the manifest in the temp dir, so
-        # we can check it, and possibly embed it, later.
-        temp_manifest = os.path.join(
-            build_temp, os.path.basename(output_filename) + ".manifest"
-        )
-        ld_args.append('/MANIFESTFILE:' + temp_manifest)
-
-    def manifest_get_embed_info(self, target_desc, ld_args):
-        # If a manifest should be embedded, return a tuple of
-        # (manifest_filename, resource_id).  Returns None if no manifest
-        # should be embedded.  See http://bugs.python.org/issue7833 for why
-        # we want to avoid any manifest for extension modules if we can)
-        for arg in ld_args:
-            if arg.startswith("/MANIFESTFILE:"):
-                temp_manifest = arg.split(":", 1)[1]
-                break
-        else:
-            # no /MANIFESTFILE so nothing to do.
-            return None
-        if target_desc == CCompiler.EXECUTABLE:
-            # by default, executables always get the manifest with the
-            # CRT referenced.
-            mfid = 1
-        else:
-            # Extension modules try and avoid any manifest if possible.
-            mfid = 2
-            temp_manifest = self._remove_visual_c_ref(temp_manifest)
-        if temp_manifest is None:
-            return None
-        return temp_manifest, mfid
-
-    def _remove_visual_c_ref(self, manifest_file):
-        try:
-            # Remove references to the Visual C runtime, so they will
-            # fall through to the Visual C dependency of Python.exe.
-            # This way, when installed for a restricted user (e.g.
-            # runtimes are not in WinSxS folder, but in Python's own
-            # folder), the runtimes do not need to be in every folder
-            # with .pyd's.
-            # Returns either the filename of the modified manifest or
-            # None if no manifest should be embedded.
-            manifest_f = open(manifest_file)
-            try:
-                manifest_buf = manifest_f.read()
-            finally:
-                manifest_f.close()
-            pattern = re.compile(
-                r"""<assemblyIdentity.*?name=("|')Microsoft\."""
-                r"""VC\d{2}\.CRT("|').*?(/>|</assemblyIdentity>)""",
-                re.DOTALL,
-            )
-            manifest_buf = re.sub(pattern, "", manifest_buf)
-            pattern = r"<dependentAssembly>\s*</dependentAssembly>"
-            manifest_buf = re.sub(pattern, "", manifest_buf)
-            # Now see if any other assemblies are referenced - if not, we
-            # don't want a manifest embedded.
-            pattern = re.compile(
-                r"""<assemblyIdentity.*?name=(?:"|')(.+?)(?:"|')"""
-                r""".*?(?:/>|</assemblyIdentity>)""",
-                re.DOTALL,
-            )
-            if re.search(pattern, manifest_buf) is None:
-                return None
-
-            manifest_f = open(manifest_file, 'w')
-            try:
-                manifest_f.write(manifest_buf)
-                return manifest_file
-            finally:
-                manifest_f.close()
-        except OSError:
-            pass
-
-    # -- Miscellaneous methods -----------------------------------------
-    # These are all used by the 'gen_lib_options() function, in
-    # ccompiler.py.
-
-    def library_dir_option(self, dir):
-        return "/LIBPATH:" + dir
-
-    def runtime_library_dir_option(self, dir):
-        raise DistutilsPlatformError(
-            "don't know how to set runtime library search path for MSVC++"
-        )
-
-    def library_option(self, lib):
-        return self.library_filename(lib)
-
-    def find_library_file(self, dirs, lib, debug=0):
-        # Prefer a debugging library if found (and requested), but deal
-        # with it if we don't have one.
-        if debug:
-            try_names = [lib + "_d", lib]
-        else:
-            try_names = [lib]
-        for dir in dirs:
-            for name in try_names:
-                libfile = os.path.join(dir, self.library_filename(name))
-                if os.path.exists(libfile):
-                    return libfile
-        else:
-            # Oops, didn't find it in *any* of 'dirs'
-            return None
-
-    # Helper methods for using the MSVC registry settings
-
-    def find_exe(self, exe):
-        """Return path to an MSVC executable program.
-
-        Tries to find the program in several places: first, one of the
-        MSVC program search paths from the registry; next, the directories
-        in the PATH environment variable.  If any of those work, return an
-        absolute path that is known to exist.  If none of them work, just
-        return the original program name, 'exe'.
-        """
-        for p in self.__paths:
-            fn = os.path.join(os.path.abspath(p), exe)
-            if os.path.isfile(fn):
-                return fn
-
-        # didn't find it; try existing path
-        for p in os.environ['Path'].split(';'):
-            fn = os.path.join(os.path.abspath(p), exe)
-            if os.path.isfile(fn):
-                return fn
-
-        return exe
diff --git a/setuptools/_distutils/msvccompiler.py b/setuptools/_distutils/msvccompiler.py
deleted file mode 100644 (file)
index 51e6017..0000000
+++ /dev/null
@@ -1,686 +0,0 @@
-"""distutils.msvccompiler
-
-Contains MSVCCompiler, an implementation of the abstract CCompiler class
-for the Microsoft Visual Studio.
-"""
-
-# Written by Perry Stoll
-# hacked by Robin Becker and Thomas Heller to do a better job of
-#   finding DevStudio (through the registry)
-
-import sys
-import os
-from distutils.errors import (
-    DistutilsExecError,
-    DistutilsPlatformError,
-    CompileError,
-    LibError,
-    LinkError,
-)
-from distutils.ccompiler import CCompiler, gen_lib_options
-from distutils import log
-
-_can_read_reg = False
-try:
-    import winreg
-
-    _can_read_reg = True
-    hkey_mod = winreg
-
-    RegOpenKeyEx = winreg.OpenKeyEx
-    RegEnumKey = winreg.EnumKey
-    RegEnumValue = winreg.EnumValue
-    RegError = winreg.error
-
-except ImportError:
-    try:
-        import win32api
-        import win32con
-
-        _can_read_reg = True
-        hkey_mod = win32con
-
-        RegOpenKeyEx = win32api.RegOpenKeyEx
-        RegEnumKey = win32api.RegEnumKey
-        RegEnumValue = win32api.RegEnumValue
-        RegError = win32api.error
-    except ImportError:
-        log.info(
-            "Warning: Can't read registry to find the "
-            "necessary compiler setting\n"
-            "Make sure that Python modules winreg, "
-            "win32api or win32con are installed."
-        )
-        pass
-
-if _can_read_reg:
-    HKEYS = (
-        hkey_mod.HKEY_USERS,
-        hkey_mod.HKEY_CURRENT_USER,
-        hkey_mod.HKEY_LOCAL_MACHINE,
-        hkey_mod.HKEY_CLASSES_ROOT,
-    )
-
-
-def read_keys(base, key):
-    """Return list of registry keys."""
-    try:
-        handle = RegOpenKeyEx(base, key)
-    except RegError:
-        return None
-    L = []
-    i = 0
-    while True:
-        try:
-            k = RegEnumKey(handle, i)
-        except RegError:
-            break
-        L.append(k)
-        i += 1
-    return L
-
-
-def read_values(base, key):
-    """Return dict of registry keys and values.
-
-    All names are converted to lowercase.
-    """
-    try:
-        handle = RegOpenKeyEx(base, key)
-    except RegError:
-        return None
-    d = {}
-    i = 0
-    while True:
-        try:
-            name, value, type = RegEnumValue(handle, i)
-        except RegError:
-            break
-        name = name.lower()
-        d[convert_mbcs(name)] = convert_mbcs(value)
-        i += 1
-    return d
-
-
-def convert_mbcs(s):
-    dec = getattr(s, "decode", None)
-    if dec is not None:
-        try:
-            s = dec("mbcs")
-        except UnicodeError:
-            pass
-    return s
-
-
-class MacroExpander:
-    def __init__(self, version):
-        self.macros = {}
-        self.load_macros(version)
-
-    def set_macro(self, macro, path, key):
-        for base in HKEYS:
-            d = read_values(base, path)
-            if d:
-                self.macros["$(%s)" % macro] = d[key]
-                break
-
-    def load_macros(self, version):
-        vsbase = r"Software\Microsoft\VisualStudio\%0.1f" % version
-        self.set_macro("VCInstallDir", vsbase + r"\Setup\VC", "productdir")
-        self.set_macro("VSInstallDir", vsbase + r"\Setup\VS", "productdir")
-        net = r"Software\Microsoft\.NETFramework"
-        self.set_macro("FrameworkDir", net, "installroot")
-        try:
-            if version > 7.0:
-                self.set_macro("FrameworkSDKDir", net, "sdkinstallrootv1.1")
-            else:
-                self.set_macro("FrameworkSDKDir", net, "sdkinstallroot")
-        except KeyError:
-            raise DistutilsPlatformError(
-                """Python was built with Visual Studio 2003;
-extensions must be built with a compiler than can generate compatible binaries.
-Visual Studio 2003 was not found on this system. If you have Cygwin installed,
-you can try compiling with MingW32, by passing "-c mingw32" to setup.py."""
-            )
-
-        p = r"Software\Microsoft\NET Framework Setup\Product"
-        for base in HKEYS:
-            try:
-                h = RegOpenKeyEx(base, p)
-            except RegError:
-                continue
-            key = RegEnumKey(h, 0)
-            d = read_values(base, r"{}\{}".format(p, key))
-            self.macros["$(FrameworkVersion)"] = d["version"]
-
-    def sub(self, s):
-        for k, v in self.macros.items():
-            s = s.replace(k, v)
-        return s
-
-
-def get_build_version():
-    """Return the version of MSVC that was used to build Python.
-
-    For Python 2.3 and up, the version number is included in
-    sys.version.  For earlier versions, assume the compiler is MSVC 6.
-    """
-    prefix = "MSC v."
-    i = sys.version.find(prefix)
-    if i == -1:
-        return 6
-    i = i + len(prefix)
-    s, rest = sys.version[i:].split(" ", 1)
-    majorVersion = int(s[:-2]) - 6
-    if majorVersion >= 13:
-        # v13 was skipped and should be v14
-        majorVersion += 1
-    minorVersion = int(s[2:3]) / 10.0
-    # I don't think paths are affected by minor version in version 6
-    if majorVersion == 6:
-        minorVersion = 0
-    if majorVersion >= 6:
-        return majorVersion + minorVersion
-    # else we don't know what version of the compiler this is
-    return None
-
-
-def get_build_architecture():
-    """Return the processor architecture.
-
-    Possible results are "Intel" or "AMD64".
-    """
-
-    prefix = " bit ("
-    i = sys.version.find(prefix)
-    if i == -1:
-        return "Intel"
-    j = sys.version.find(")", i)
-    return sys.version[i + len(prefix) : j]
-
-
-def normalize_and_reduce_paths(paths):
-    """Return a list of normalized paths with duplicates removed.
-
-    The current order of paths is maintained.
-    """
-    # Paths are normalized so things like:  /a and /a/ aren't both preserved.
-    reduced_paths = []
-    for p in paths:
-        np = os.path.normpath(p)
-        # XXX(nnorwitz): O(n**2), if reduced_paths gets long perhaps use a set.
-        if np not in reduced_paths:
-            reduced_paths.append(np)
-    return reduced_paths
-
-
-class MSVCCompiler(CCompiler):
-    """Concrete class that implements an interface to Microsoft Visual C++,
-    as defined by the CCompiler abstract class."""
-
-    compiler_type = 'msvc'
-
-    # Just set this so CCompiler's constructor doesn't barf.  We currently
-    # don't use the 'set_executables()' bureaucracy provided by CCompiler,
-    # as it really isn't necessary for this sort of single-compiler class.
-    # Would be nice to have a consistent interface with UnixCCompiler,
-    # though, so it's worth thinking about.
-    executables = {}
-
-    # Private class data (need to distinguish C from C++ source for compiler)
-    _c_extensions = ['.c']
-    _cpp_extensions = ['.cc', '.cpp', '.cxx']
-    _rc_extensions = ['.rc']
-    _mc_extensions = ['.mc']
-
-    # Needed for the filename generation methods provided by the
-    # base class, CCompiler.
-    src_extensions = _c_extensions + _cpp_extensions + _rc_extensions + _mc_extensions
-    res_extension = '.res'
-    obj_extension = '.obj'
-    static_lib_extension = '.lib'
-    shared_lib_extension = '.dll'
-    static_lib_format = shared_lib_format = '%s%s'
-    exe_extension = '.exe'
-
-    def __init__(self, verbose=0, dry_run=0, force=0):
-        super().__init__(verbose, dry_run, force)
-        self.__version = get_build_version()
-        self.__arch = get_build_architecture()
-        if self.__arch == "Intel":
-            # x86
-            if self.__version >= 7:
-                self.__root = r"Software\Microsoft\VisualStudio"
-                self.__macros = MacroExpander(self.__version)
-            else:
-                self.__root = r"Software\Microsoft\Devstudio"
-            self.__product = "Visual Studio version %s" % self.__version
-        else:
-            # Win64. Assume this was built with the platform SDK
-            self.__product = "Microsoft SDK compiler %s" % (self.__version + 6)
-
-        self.initialized = False
-
-    def initialize(self):
-        self.__paths = []
-        if (
-            "DISTUTILS_USE_SDK" in os.environ
-            and "MSSdk" in os.environ
-            and self.find_exe("cl.exe")
-        ):
-            # Assume that the SDK set up everything alright; don't try to be
-            # smarter
-            self.cc = "cl.exe"
-            self.linker = "link.exe"
-            self.lib = "lib.exe"
-            self.rc = "rc.exe"
-            self.mc = "mc.exe"
-        else:
-            self.__paths = self.get_msvc_paths("path")
-
-            if len(self.__paths) == 0:
-                raise DistutilsPlatformError(
-                    "Python was built with %s, "
-                    "and extensions need to be built with the same "
-                    "version of the compiler, but it isn't installed." % self.__product
-                )
-
-            self.cc = self.find_exe("cl.exe")
-            self.linker = self.find_exe("link.exe")
-            self.lib = self.find_exe("lib.exe")
-            self.rc = self.find_exe("rc.exe")  # resource compiler
-            self.mc = self.find_exe("mc.exe")  # message compiler
-            self.set_path_env_var('lib')
-            self.set_path_env_var('include')
-
-        # extend the MSVC path with the current path
-        try:
-            for p in os.environ['path'].split(';'):
-                self.__paths.append(p)
-        except KeyError:
-            pass
-        self.__paths = normalize_and_reduce_paths(self.__paths)
-        os.environ['path'] = ";".join(self.__paths)
-
-        self.preprocess_options = None
-        if self.__arch == "Intel":
-            self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/GX', '/DNDEBUG']
-            self.compile_options_debug = [
-                '/nologo',
-                '/Od',
-                '/MDd',
-                '/W3',
-                '/GX',
-                '/Z7',
-                '/D_DEBUG',
-            ]
-        else:
-            # Win64
-            self.compile_options = ['/nologo', '/O2', '/MD', '/W3', '/GS-', '/DNDEBUG']
-            self.compile_options_debug = [
-                '/nologo',
-                '/Od',
-                '/MDd',
-                '/W3',
-                '/GS-',
-                '/Z7',
-                '/D_DEBUG',
-            ]
-
-        self.ldflags_shared = ['/DLL', '/nologo', '/INCREMENTAL:NO']
-        if self.__version >= 7:
-            self.ldflags_shared_debug = ['/DLL', '/nologo', '/INCREMENTAL:no', '/DEBUG']
-        else:
-            self.ldflags_shared_debug = [
-                '/DLL',
-                '/nologo',
-                '/INCREMENTAL:no',
-                '/pdb:None',
-                '/DEBUG',
-            ]
-        self.ldflags_static = ['/nologo']
-
-        self.initialized = True
-
-    # -- Worker methods ------------------------------------------------
-
-    def object_filenames(self, source_filenames, strip_dir=0, output_dir=''):
-        # Copied from ccompiler.py, extended to return .res as 'object'-file
-        # for .rc input file
-        if output_dir is None:
-            output_dir = ''
-        obj_names = []
-        for src_name in source_filenames:
-            (base, ext) = os.path.splitext(src_name)
-            base = os.path.splitdrive(base)[1]  # Chop off the drive
-            base = base[os.path.isabs(base) :]  # If abs, chop off leading /
-            if ext not in self.src_extensions:
-                # Better to raise an exception instead of silently continuing
-                # and later complain about sources and targets having
-                # different lengths
-                raise CompileError("Don't know how to compile %s" % src_name)
-            if strip_dir:
-                base = os.path.basename(base)
-            if ext in self._rc_extensions:
-                obj_names.append(os.path.join(output_dir, base + self.res_extension))
-            elif ext in self._mc_extensions:
-                obj_names.append(os.path.join(output_dir, base + self.res_extension))
-            else:
-                obj_names.append(os.path.join(output_dir, base + self.obj_extension))
-        return obj_names
-
-    def compile(  # noqa: C901
-        self,
-        sources,
-        output_dir=None,
-        macros=None,
-        include_dirs=None,
-        debug=0,
-        extra_preargs=None,
-        extra_postargs=None,
-        depends=None,
-    ):
-
-        if not self.initialized:
-            self.initialize()
-        compile_info = self._setup_compile(
-            output_dir, macros, include_dirs, sources, depends, extra_postargs
-        )
-        macros, objects, extra_postargs, pp_opts, build = compile_info
-
-        compile_opts = extra_preargs or []
-        compile_opts.append('/c')
-        if debug:
-            compile_opts.extend(self.compile_options_debug)
-        else:
-            compile_opts.extend(self.compile_options)
-
-        for obj in objects:
-            try:
-                src, ext = build[obj]
-            except KeyError:
-                continue
-            if debug:
-                # pass the full pathname to MSVC in debug mode,
-                # this allows the debugger to find the source file
-                # without asking the user to browse for it
-                src = os.path.abspath(src)
-
-            if ext in self._c_extensions:
-                input_opt = "/Tc" + src
-            elif ext in self._cpp_extensions:
-                input_opt = "/Tp" + src
-            elif ext in self._rc_extensions:
-                # compile .RC to .RES file
-                input_opt = src
-                output_opt = "/fo" + obj
-                try:
-                    self.spawn([self.rc] + pp_opts + [output_opt] + [input_opt])
-                except DistutilsExecError as msg:
-                    raise CompileError(msg)
-                continue
-            elif ext in self._mc_extensions:
-                # Compile .MC to .RC file to .RES file.
-                #   * '-h dir' specifies the directory for the
-                #     generated include file
-                #   * '-r dir' specifies the target directory of the
-                #     generated RC file and the binary message resource
-                #     it includes
-                #
-                # For now (since there are no options to change this),
-                # we use the source-directory for the include file and
-                # the build directory for the RC file and message
-                # resources. This works at least for win32all.
-                h_dir = os.path.dirname(src)
-                rc_dir = os.path.dirname(obj)
-                try:
-                    # first compile .MC to .RC and .H file
-                    self.spawn([self.mc] + ['-h', h_dir, '-r', rc_dir] + [src])
-                    base, _ = os.path.splitext(os.path.basename(src))
-                    rc_file = os.path.join(rc_dir, base + '.rc')
-                    # then compile .RC to .RES file
-                    self.spawn([self.rc] + ["/fo" + obj] + [rc_file])
-
-                except DistutilsExecError as msg:
-                    raise CompileError(msg)
-                continue
-            else:
-                # how to handle this file?
-                raise CompileError(
-                    "Don't know how to compile {} to {}".format(src, obj)
-                )
-
-            output_opt = "/Fo" + obj
-            try:
-                self.spawn(
-                    [self.cc]
-                    + compile_opts
-                    + pp_opts
-                    + [input_opt, output_opt]
-                    + extra_postargs
-                )
-            except DistutilsExecError as msg:
-                raise CompileError(msg)
-
-        return objects
-
-    def create_static_lib(
-        self, objects, output_libname, output_dir=None, debug=0, target_lang=None
-    ):
-
-        if not self.initialized:
-            self.initialize()
-        (objects, output_dir) = self._fix_object_args(objects, output_dir)
-        output_filename = self.library_filename(output_libname, output_dir=output_dir)
-
-        if self._need_link(objects, output_filename):
-            lib_args = objects + ['/OUT:' + output_filename]
-            if debug:
-                pass  # XXX what goes here?
-            try:
-                self.spawn([self.lib] + lib_args)
-            except DistutilsExecError as msg:
-                raise LibError(msg)
-        else:
-            log.debug("skipping %s (up-to-date)", output_filename)
-
-    def link(  # noqa: C901
-        self,
-        target_desc,
-        objects,
-        output_filename,
-        output_dir=None,
-        libraries=None,
-        library_dirs=None,
-        runtime_library_dirs=None,
-        export_symbols=None,
-        debug=0,
-        extra_preargs=None,
-        extra_postargs=None,
-        build_temp=None,
-        target_lang=None,
-    ):
-
-        if not self.initialized:
-            self.initialize()
-        (objects, output_dir) = self._fix_object_args(objects, output_dir)
-        fixed_args = self._fix_lib_args(libraries, library_dirs, runtime_library_dirs)
-        (libraries, library_dirs, runtime_library_dirs) = fixed_args
-
-        if runtime_library_dirs:
-            self.warn(
-                "I don't know what to do with 'runtime_library_dirs': "
-                + str(runtime_library_dirs)
-            )
-
-        lib_opts = gen_lib_options(self, library_dirs, runtime_library_dirs, libraries)
-        if output_dir is not None:
-            output_filename = os.path.join(output_dir, output_filename)
-
-        if self._need_link(objects, output_filename):
-            if target_desc == CCompiler.EXECUTABLE:
-                if debug:
-                    ldflags = self.ldflags_shared_debug[1:]
-                else:
-                    ldflags = self.ldflags_shared[1:]
-            else:
-                if debug:
-                    ldflags = self.ldflags_shared_debug
-                else:
-                    ldflags = self.ldflags_shared
-
-            export_opts = []
-            for sym in export_symbols or []:
-                export_opts.append("/EXPORT:" + sym)
-
-            ld_args = (
-                ldflags + lib_opts + export_opts + objects + ['/OUT:' + output_filename]
-            )
-
-            # The MSVC linker generates .lib and .exp files, which cannot be
-            # suppressed by any linker switches. The .lib files may even be
-            # needed! Make sure they are generated in the temporary build
-            # directory. Since they have different names for debug and release
-            # builds, they can go into the same directory.
-            if export_symbols is not None:
-                (dll_name, dll_ext) = os.path.splitext(
-                    os.path.basename(output_filename)
-                )
-                implib_file = os.path.join(
-                    os.path.dirname(objects[0]), self.library_filename(dll_name)
-                )
-                ld_args.append('/IMPLIB:' + implib_file)
-
-            if extra_preargs:
-                ld_args[:0] = extra_preargs
-            if extra_postargs:
-                ld_args.extend(extra_postargs)
-
-            self.mkpath(os.path.dirname(output_filename))
-            try:
-                self.spawn([self.linker] + ld_args)
-            except DistutilsExecError as msg:
-                raise LinkError(msg)
-
-        else:
-            log.debug("skipping %s (up-to-date)", output_filename)
-
-    # -- Miscellaneous methods -----------------------------------------
-    # These are all used by the 'gen_lib_options() function, in
-    # ccompiler.py.
-
-    def library_dir_option(self, dir):
-        return "/LIBPATH:" + dir
-
-    def runtime_library_dir_option(self, dir):
-        raise DistutilsPlatformError(
-            "don't know how to set runtime library search path for MSVC++"
-        )
-
-    def library_option(self, lib):
-        return self.library_filename(lib)
-
-    def find_library_file(self, dirs, lib, debug=0):
-        # Prefer a debugging library if found (and requested), but deal
-        # with it if we don't have one.
-        if debug:
-            try_names = [lib + "_d", lib]
-        else:
-            try_names = [lib]
-        for dir in dirs:
-            for name in try_names:
-                libfile = os.path.join(dir, self.library_filename(name))
-                if os.path.exists(libfile):
-                    return libfile
-        else:
-            # Oops, didn't find it in *any* of 'dirs'
-            return None
-
-    # Helper methods for using the MSVC registry settings
-
-    def find_exe(self, exe):
-        """Return path to an MSVC executable program.
-
-        Tries to find the program in several places: first, one of the
-        MSVC program search paths from the registry; next, the directories
-        in the PATH environment variable.  If any of those work, return an
-        absolute path that is known to exist.  If none of them work, just
-        return the original program name, 'exe'.
-        """
-        for p in self.__paths:
-            fn = os.path.join(os.path.abspath(p), exe)
-            if os.path.isfile(fn):
-                return fn
-
-        # didn't find it; try existing path
-        for p in os.environ['Path'].split(';'):
-            fn = os.path.join(os.path.abspath(p), exe)
-            if os.path.isfile(fn):
-                return fn
-
-        return exe
-
-    def get_msvc_paths(self, path, platform='x86'):
-        """Get a list of devstudio directories (include, lib or path).
-
-        Return a list of strings.  The list will be empty if unable to
-        access the registry or appropriate registry keys not found.
-        """
-        if not _can_read_reg:
-            return []
-
-        path = path + " dirs"
-        if self.__version >= 7:
-            key = r"{}\{:0.1f}\VC\VC_OBJECTS_PLATFORM_INFO\Win32\Directories".format(
-                self.__root,
-                self.__version,
-            )
-        else:
-            key = (
-                r"%s\6.0\Build System\Components\Platforms"
-                r"\Win32 (%s)\Directories" % (self.__root, platform)
-            )
-
-        for base in HKEYS:
-            d = read_values(base, key)
-            if d:
-                if self.__version >= 7:
-                    return self.__macros.sub(d[path]).split(";")
-                else:
-                    return d[path].split(";")
-        # MSVC 6 seems to create the registry entries we need only when
-        # the GUI is run.
-        if self.__version == 6:
-            for base in HKEYS:
-                if read_values(base, r"%s\6.0" % self.__root) is not None:
-                    self.warn(
-                        "It seems you have Visual Studio 6 installed, "
-                        "but the expected registry settings are not present.\n"
-                        "You must at least run the Visual Studio GUI once "
-                        "so that these entries are created."
-                    )
-                    break
-        return []
-
-    def set_path_env_var(self, name):
-        """Set environment variable 'name' to an MSVC path type value.
-
-        This is equivalent to a SET command prior to execution of spawned
-        commands.
-        """
-
-        if name == "lib":
-            p = self.get_msvc_paths("library")
-        else:
-            p = self.get_msvc_paths(name)
-        if p:
-            os.environ[name] = ';'.join(p)
-
-
-if get_build_version() >= 8.0:
-    log.debug("Importing new compiler from distutils.msvc9compiler")
-    OldMSVCCompiler = MSVCCompiler
-    from distutils.msvc9compiler import MSVCCompiler
-
-    # get_build_architecture not really relevant now we support cross-compile
-    from distutils.msvc9compiler import MacroExpander  # noqa: F811
index 5b8774e5eb1dd8c815327cedbab9f36207ad52a2..af330a06e7d605428139e0b4d990aa8c6621e653 100644 (file)
@@ -1,7 +1,4 @@
 """Tests for distutils.command.bdist."""
-import os
-import warnings
-
 from distutils.command.bdist import bdist
 from distutils.tests import support
 
@@ -12,18 +9,16 @@ class TestBuild(support.TempdirManager):
         # we can set the format
         dist = self.create_dist()[1]
         cmd = bdist(dist)
-        cmd.formats = ['msi']
+        cmd.formats = ['gztar']
         cmd.ensure_finalized()
-        assert cmd.formats == ['msi']
+        assert cmd.formats == ['gztar']
 
         # what formats does bdist offer?
         formats = [
             'bztar',
             'gztar',
-            'msi',
             'rpm',
             'tar',
-            'wininst',
             'xztar',
             'zip',
             'ztar',
@@ -41,17 +36,10 @@ class TestBuild(support.TempdirManager):
 
         names = [
             'bdist_dumb',
-            'bdist_wininst',
         ]  # bdist_rpm does not support --skip-build
-        if os.name == 'nt':
-            names.append('bdist_msi')
 
         for name in names:
-            with warnings.catch_warnings():
-                warnings.filterwarnings(
-                    'ignore', 'bdist_wininst command is deprecated', DeprecationWarning
-                )
-                subcmd = cmd.get_finalized_command(name)
+            subcmd = cmd.get_finalized_command(name)
             if getattr(subcmd, '_unsupported', False):
                 # command is not supported on this build
                 continue
diff --git a/setuptools/_distutils/tests/test_bdist_msi.py b/setuptools/_distutils/tests/test_bdist_msi.py
deleted file mode 100644 (file)
index f36b398..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-"""Tests for distutils.command.bdist_msi."""
-import pytest
-
-from distutils.tests import support
-
-from .py38compat import check_warnings
-
-
-pytest.importorskip('msilib')
-
-
-class TestBDistMSI(support.TempdirManager, support.LoggingSilencer):
-    def test_minimal(self):
-        # minimal test XXX need more tests
-        from distutils.command.bdist_msi import bdist_msi
-
-        project_dir, dist = self.create_dist()
-        with check_warnings(("", DeprecationWarning)):
-            cmd = bdist_msi(dist)
-        cmd.ensure_finalized()
diff --git a/setuptools/_distutils/tests/test_bdist_wininst.py b/setuptools/_distutils/tests/test_bdist_wininst.py
deleted file mode 100644 (file)
index c432d24..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-"""Tests for distutils.command.bdist_wininst."""
-import pytest
-
-from .py38compat import check_warnings
-
-from distutils.command.bdist_wininst import bdist_wininst
-from distutils.tests import support
-
-
-@pytest.mark.skipif("platform.machine() == 'ARM64'")
-@pytest.mark.skipif("bdist_wininst._unsupported")
-class TestBuildWinInst(support.TempdirManager, support.LoggingSilencer):
-    def test_get_exe_bytes(self):
-
-        # issue5731: command was broken on non-windows platforms
-        # this test makes sure it works now for every platform
-        # let's create a command
-        pkg_pth, dist = self.create_dist()
-        with check_warnings(("", DeprecationWarning)):
-            cmd = bdist_wininst(dist)
-        cmd.ensure_finalized()
-
-        # let's run the code that finds the right wininst*.exe file
-        # and make sure it finds it and returns its content
-        # no matter what platform we have
-        exe_file = cmd.get_exe_bytes()
-        assert len(exe_file) > 10
diff --git a/setuptools/_distutils/tests/test_msvc9compiler.py b/setuptools/_distutils/tests/test_msvc9compiler.py
deleted file mode 100644 (file)
index fe5693e..0000000
+++ /dev/null
@@ -1,183 +0,0 @@
-"""Tests for distutils.msvc9compiler."""
-import sys
-import os
-
-from distutils.errors import DistutilsPlatformError
-from distutils.tests import support
-import pytest
-
-# A manifest with the only assembly reference being the msvcrt assembly, so
-# should have the assembly completely stripped.  Note that although the
-# assembly has a <security> reference the assembly is removed - that is
-# currently a "feature", not a bug :)
-_MANIFEST_WITH_ONLY_MSVC_REFERENCE = """\
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
-          manifestVersion="1.0">
-  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
-    <security>
-      <requestedPrivileges>
-        <requestedExecutionLevel level="asInvoker" uiAccess="false">
-        </requestedExecutionLevel>
-      </requestedPrivileges>
-    </security>
-  </trustInfo>
-  <dependency>
-    <dependentAssembly>
-      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT"
-         version="9.0.21022.8" processorArchitecture="x86"
-         publicKeyToken="XXXX">
-      </assemblyIdentity>
-    </dependentAssembly>
-  </dependency>
-</assembly>
-"""
-
-# A manifest with references to assemblies other than msvcrt.  When processed,
-# this assembly should be returned with just the msvcrt part removed.
-_MANIFEST_WITH_MULTIPLE_REFERENCES = """\
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
-          manifestVersion="1.0">
-  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
-    <security>
-      <requestedPrivileges>
-        <requestedExecutionLevel level="asInvoker" uiAccess="false">
-        </requestedExecutionLevel>
-      </requestedPrivileges>
-    </security>
-  </trustInfo>
-  <dependency>
-    <dependentAssembly>
-      <assemblyIdentity type="win32" name="Microsoft.VC90.CRT"
-         version="9.0.21022.8" processorArchitecture="x86"
-         publicKeyToken="XXXX">
-      </assemblyIdentity>
-    </dependentAssembly>
-  </dependency>
-  <dependency>
-    <dependentAssembly>
-      <assemblyIdentity type="win32" name="Microsoft.VC90.MFC"
-        version="9.0.21022.8" processorArchitecture="x86"
-        publicKeyToken="XXXX"></assemblyIdentity>
-    </dependentAssembly>
-  </dependency>
-</assembly>
-"""
-
-_CLEANED_MANIFEST = """\
-<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<assembly xmlns="urn:schemas-microsoft-com:asm.v1"
-          manifestVersion="1.0">
-  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
-    <security>
-      <requestedPrivileges>
-        <requestedExecutionLevel level="asInvoker" uiAccess="false">
-        </requestedExecutionLevel>
-      </requestedPrivileges>
-    </security>
-  </trustInfo>
-  <dependency>
-
-  </dependency>
-  <dependency>
-    <dependentAssembly>
-      <assemblyIdentity type="win32" name="Microsoft.VC90.MFC"
-        version="9.0.21022.8" processorArchitecture="x86"
-        publicKeyToken="XXXX"></assemblyIdentity>
-    </dependentAssembly>
-  </dependency>
-</assembly>"""
-
-if sys.platform == "win32":
-    from distutils.msvccompiler import get_build_version
-
-    if get_build_version() >= 8.0:
-        SKIP_MESSAGE = None
-    else:
-        SKIP_MESSAGE = "These tests are only for MSVC8.0 or above"
-else:
-    SKIP_MESSAGE = "These tests are only for win32"
-
-
-@pytest.mark.skipif('SKIP_MESSAGE', reason=SKIP_MESSAGE)
-class Testmsvc9compiler(support.TempdirManager):
-    def test_no_compiler(self):
-        # makes sure query_vcvarsall raises
-        # a DistutilsPlatformError if the compiler
-        # is not found
-        from distutils.msvc9compiler import query_vcvarsall
-
-        def _find_vcvarsall(version):
-            return None
-
-        from distutils import msvc9compiler
-
-        old_find_vcvarsall = msvc9compiler.find_vcvarsall
-        msvc9compiler.find_vcvarsall = _find_vcvarsall
-        try:
-            with pytest.raises(DistutilsPlatformError):
-                query_vcvarsall('wont find this version')
-        finally:
-            msvc9compiler.find_vcvarsall = old_find_vcvarsall
-
-    def test_reg_class(self):
-        from distutils.msvc9compiler import Reg
-
-        with pytest.raises(KeyError):
-            Reg.get_value('xxx', 'xxx')
-
-        # looking for values that should exist on all
-        # windows registry versions.
-        path = r'Control Panel\Desktop'
-        v = Reg.get_value(path, 'dragfullwindows')
-        assert v in ('0', '1', '2')
-
-        import winreg
-
-        HKCU = winreg.HKEY_CURRENT_USER
-        keys = Reg.read_keys(HKCU, 'xxxx')
-        assert keys is None
-
-        keys = Reg.read_keys(HKCU, r'Control Panel')
-        assert 'Desktop' in keys
-
-    def test_remove_visual_c_ref(self):
-        from distutils.msvc9compiler import MSVCCompiler
-
-        tempdir = self.mkdtemp()
-        manifest = os.path.join(tempdir, 'manifest')
-        f = open(manifest, 'w')
-        try:
-            f.write(_MANIFEST_WITH_MULTIPLE_REFERENCES)
-        finally:
-            f.close()
-
-        compiler = MSVCCompiler()
-        compiler._remove_visual_c_ref(manifest)
-
-        # see what we got
-        f = open(manifest)
-        try:
-            # removing trailing spaces
-            content = '\n'.join([line.rstrip() for line in f.readlines()])
-        finally:
-            f.close()
-
-        # makes sure the manifest was properly cleaned
-        assert content == _CLEANED_MANIFEST
-
-    def test_remove_entire_manifest(self):
-        from distutils.msvc9compiler import MSVCCompiler
-
-        tempdir = self.mkdtemp()
-        manifest = os.path.join(tempdir, 'manifest')
-        f = open(manifest, 'w')
-        try:
-            f.write(_MANIFEST_WITH_ONLY_MSVC_REFERENCE)
-        finally:
-            f.close()
-
-        compiler = MSVCCompiler()
-        got = compiler._remove_visual_c_ref(manifest)
-        assert got is None
index 92da290ed19c21e4483ce6763ed34603fda9c563..15b489019cfd3dc941db8c17b2c5f21d521de994 100644 (file)
@@ -1,39 +1,39 @@
-@echo off\r
-\r
-REM Use old Windows SDK 6.1 so created .exe will be compatible with\r
-REM old Windows versions.\r
-REM Windows SDK 6.1 may be downloaded at:\r
-REM  http://www.microsoft.com/en-us/download/details.aspx?id=11310\r
-set PATH_OLD=%PATH%\r
-\r
-REM The SDK creates a false install of Visual Studio at one of these locations\r
-set PATH=C:\Program Files\Microsoft Visual Studio 9.0\VC\bin;%PATH%\r
-set PATH=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin;%PATH%\r
-\r
-REM set up the environment to compile to x86\r
-call VCVARS32\r
-if "%ERRORLEVEL%"=="0" (\r
-  cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /SUBSYSTEM:CONSOLE /out:setuptools/cli-32.exe\r
-  cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /SUBSYSTEM:WINDOWS /out:setuptools/gui-32.exe\r
-) else (\r
-  echo Windows SDK 6.1 not found to build Windows 32-bit version\r
-)\r
-\r
-REM buildout (and possibly other implementations) currently depend on\r
-REM the 32-bit launcher scripts without the -32 in the filename, so copy them\r
-REM there for now.\r
-copy setuptools/cli-32.exe setuptools/cli.exe\r
-copy setuptools/gui-32.exe setuptools/gui.exe\r
-\r
-REM now for 64-bit\r
-REM Use the x86_amd64 profile, which is the 32-bit cross compiler for amd64\r
-call VCVARSx86_amd64\r
-if "%ERRORLEVEL%"=="0" (\r
-  cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /SUBSYSTEM:CONSOLE /out:setuptools/cli-64.exe\r
-  cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /SUBSYSTEM:WINDOWS /out:setuptools/gui-64.exe\r
-) else (\r
-  echo Windows SDK 6.1 not found to build Windows 64-bit version\r
-)\r
-\r
-set PATH=%PATH_OLD%\r
-\r
+@echo off
+
+REM Use old Windows SDK 6.1 so created .exe will be compatible with
+REM old Windows versions.
+REM Windows SDK 6.1 may be downloaded at:
+REM  http://www.microsoft.com/en-us/download/details.aspx?id=11310
+set PATH_OLD=%PATH%
+
+REM The SDK creates a false install of Visual Studio at one of these locations
+set PATH=C:\Program Files\Microsoft Visual Studio 9.0\VC\bin;%PATH%
+set PATH=C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin;%PATH%
+
+REM set up the environment to compile to x86
+call VCVARS32
+if "%ERRORLEVEL%"=="0" (
+  cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /SUBSYSTEM:CONSOLE /out:setuptools/cli-32.exe
+  cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x86 /SUBSYSTEM:WINDOWS /out:setuptools/gui-32.exe
+) else (
+  echo Windows SDK 6.1 not found to build Windows 32-bit version
+)
+
+REM buildout (and possibly other implementations) currently depend on
+REM the 32-bit launcher scripts without the -32 in the filename, so copy them
+REM there for now.
+copy setuptools/cli-32.exe setuptools/cli.exe
+copy setuptools/gui-32.exe setuptools/gui.exe
+
+REM now for 64-bit
+REM Use the x86_amd64 profile, which is the 32-bit cross compiler for amd64
+call VCVARSx86_amd64
+if "%ERRORLEVEL%"=="0" (
+  cl /D "GUI=0" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /SUBSYSTEM:CONSOLE /out:setuptools/cli-64.exe
+  cl /D "GUI=1" /D "WIN32_LEAN_AND_MEAN" launcher.c /O2 /link /MACHINE:x64 /SUBSYSTEM:WINDOWS /out:setuptools/gui-64.exe
+) else (
+  echo Windows SDK 6.1 not found to build Windows 64-bit version
+)
+
+set PATH=%PATH_OLD%
+