]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-95299: Stop installing setuptools as a part of ensurepip and venv (#101039)
authorPradyun Gedam <pradyunsg@gmail.com>
Tue, 18 Apr 2023 04:43:34 +0000 (23:43 -0500)
committerGitHub <noreply@github.com>
Tue, 18 Apr 2023 04:43:34 +0000 (23:43 -0500)
Remove the bundled setuptools wheel from ensurepip, and stop installing setuptools in environments created by venv.

Co-Authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
Co-authored-by: C.A.M. Gerlach <CAM.Gerlach@Gerlach.CAM>
Co-authored-by: Oleg Iarygin <oleg@arhadthedev.net>
13 files changed:
.github/workflows/verify-ensurepip-wheels.yml
Doc/library/venv.rst
Doc/using/venv-create.inc
Doc/whatsnew/3.12.rst
Lib/ensurepip/__init__.py
Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl [deleted file]
Lib/test/test_ensurepip.py
Lib/test/test_venv.py
Lib/venv/__init__.py
Mac/BuildScript/scripts/postflight.ensurepip
Mac/Makefile.in
Misc/NEWS.d/next/Library/2023-01-14-17-54-56.gh-issue-95299.vUhpKz.rst [new file with mode: 0644]
Tools/build/verify_ensurepip_wheels.py

index d4a2cb6846c1cba65f31d4bf041acd1ad007c175..17d841f1f1c54ac4fc94c35ccd977d8e932a8485 100644 (file)
@@ -1,4 +1,4 @@
-name: Verify bundled pip and setuptools
+name: Verify bundled wheels
 
 on:
   workflow_dispatch:
@@ -29,5 +29,5 @@ jobs:
       - uses: actions/setup-python@v4
         with:
           python-version: '3'
-      - name: Compare checksums of bundled pip and setuptools to ones published on PyPI
+      - name: Compare checksum of bundled wheels to the ones published on PyPI
         run: ./Tools/build/verify_ensurepip_wheels.py
index 240ab139838db9f5c1b4cceee17dd1cb617787d5..52bf99e5bb0f678a6f96ab02085026710ac504ed 100644 (file)
@@ -284,11 +284,14 @@ creation according to their needs, the :class:`EnvBuilder` class.
 
     .. method:: upgrade_dependencies(context)
 
-       Upgrades the core venv dependency packages (currently ``pip`` and
-       ``setuptools``) in the environment. This is done by shelling out to the
+       Upgrades the core venv dependency packages (currently ``pip``)
+       in the environment. This is done by shelling out to the
        ``pip`` executable in the environment.
 
        .. versionadded:: 3.9
+       .. versionchanged:: 3.12
+
+          ``setuptools`` is no longer a core venv dependency.
 
     .. method:: post_setup(context)
 
index 43ee6b7807d57e1093602f1bb832b9f3e5532b8a..2fc90126482268910f6dd58ecd2a43ae95f9c51c 100644 (file)
@@ -61,12 +61,16 @@ The command, if run with ``-h``, will show the available options::
                             environment (pip is bootstrapped by default)
       --prompt PROMPT       Provides an alternative prompt prefix for this
                             environment.
-      --upgrade-deps        Upgrade core dependencies: pip setuptools to the
+      --upgrade-deps        Upgrade core dependencies (pip) to the
                             latest version in PyPI
 
     Once an environment has been created, you may wish to activate it, e.g. by
     sourcing an activate script in its bin directory.
 
+.. versionchanged:: 3.12
+
+   ``setuptools`` is no longer a core venv dependency.
+
 .. versionchanged:: 3.9
    Add ``--upgrade-deps`` option to upgrade pip + setuptools to the latest on PyPI
 
@@ -104,4 +108,3 @@ invoked to bootstrap ``pip`` into the virtual environment.
 Multiple paths can be given to ``venv``, in which case an identical virtual
 environment will be created, according to the given options, at each provided
 path.
-
index 2a371ebf55a11f46ea3d97c54e8defd94867ba3c..bd95bfeea80c71ada6af403fa245b94bf8f25f97 100644 (file)
@@ -731,6 +731,24 @@ Removed
   project can be installed: it still provides ``distutils``.
   (Contributed by Victor Stinner in :gh:`92584`.)
 
+* Remove the bundled setuptools wheel from :mod:`ensurepip`,
+  and stop installing setuptools in environments created by :mod:`venv`.
+
+  ``pip (>= 22.1)`` does not require setuptools to be installed in the
+  environment. ``setuptools``-based (and ``distutils``-based) packages
+  can still be used with ``pip install``, since pip will provide
+  ``setuptools`` in the build environment it uses for building a
+  package.
+
+  ``easy_install``, ``pkg_resources``, ``setuptools`` and ``distutils``
+  are no longer provided by default in environments created with
+  ``venv`` or bootstrapped with ``ensurepip``, since they are part of
+  the ``setuptools`` package. For projects relying on these at runtime,
+  the ``setuptools`` project should be declared as a dependency and
+  installed separately (typically, using pip).
+
+  (Contributed by Pradyun Gedam in :gh:`95299`.)
+
 * Removed many old deprecated :mod:`unittest` features:
 
   - A number of :class:`~unittest.TestCase` method aliases:
index 00e77749e25e77395457ef25f5d54e1c3a34f0fe..69b23de9e050253e2895f7d7c83c88e9d32385e3 100644 (file)
@@ -9,11 +9,9 @@ from importlib import resources
 
 
 __all__ = ["version", "bootstrap"]
-_PACKAGE_NAMES = ('setuptools', 'pip')
-_SETUPTOOLS_VERSION = "65.5.0"
+_PACKAGE_NAMES = ('pip',)
 _PIP_VERSION = "23.0.1"
 _PROJECTS = [
-    ("setuptools", _SETUPTOOLS_VERSION, "py3"),
     ("pip", _PIP_VERSION, "py3"),
 ]
 
@@ -153,17 +151,17 @@ def _bootstrap(*, root=None, upgrade=False, user=False,
 
     _disable_pip_configuration_settings()
 
-    # By default, installing pip and setuptools installs all of the
+    # By default, installing pip installs all of the
     # following scripts (X.Y == running Python version):
     #
-    #   pip, pipX, pipX.Y, easy_install, easy_install-X.Y
+    #   pip, pipX, pipX.Y
     #
     # pip 1.5+ allows ensurepip to request that some of those be left out
     if altinstall:
-        # omit pip, pipX and easy_install
+        # omit pip, pipX
         os.environ["ENSUREPIP_OPTIONS"] = "altinstall"
     elif not default_pip:
-        # omit pip and easy_install
+        # omit pip
         os.environ["ENSUREPIP_OPTIONS"] = "install"
 
     with tempfile.TemporaryDirectory() as tmpdir:
@@ -271,14 +269,14 @@ def _main(argv=None):
         action="store_true",
         default=False,
         help=("Make an alternate install, installing only the X.Y versioned "
-              "scripts (Default: pipX, pipX.Y, easy_install-X.Y)."),
+              "scripts (Default: pipX, pipX.Y)."),
     )
     parser.add_argument(
         "--default-pip",
         action="store_true",
         default=False,
         help=("Make a default pip install, installing the unqualified pip "
-              "and easy_install in addition to the versioned scripts."),
+              "in addition to the versioned scripts."),
     )
 
     args = parser.parse_args(argv)
diff --git a/Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl b/Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl
deleted file mode 100644 (file)
index 123a13e..0000000
Binary files a/Lib/ensurepip/_bundled/setuptools-65.5.0-py3-none-any.whl and /dev/null differ
index bfca0cd7fbe4834cad0a547549428a258cf04cff..69ab2a4feaa93895c1bde5944ee9938caaa632f0 100644 (file)
@@ -20,7 +20,6 @@ class TestPackages(unittest.TestCase):
         # Test version()
         with tempfile.TemporaryDirectory() as tmpdir:
             self.touch(tmpdir, "pip-1.2.3b1-py2.py3-none-any.whl")
-            self.touch(tmpdir, "setuptools-49.1.3-py3-none-any.whl")
             with (unittest.mock.patch.object(ensurepip, '_PACKAGES', None),
                   unittest.mock.patch.object(ensurepip, '_WHEEL_PKG_DIR', tmpdir)):
                 self.assertEqual(ensurepip.version(), '1.2.3b1')
@@ -36,15 +35,12 @@ class TestPackages(unittest.TestCase):
 
         # use bundled wheel packages
         self.assertIsNotNone(packages['pip'].wheel_name)
-        self.assertIsNotNone(packages['setuptools'].wheel_name)
 
     def test_get_packages_with_dir(self):
         # Test _get_packages() with a wheel package directory
-        setuptools_filename = "setuptools-49.1.3-py3-none-any.whl"
         pip_filename = "pip-20.2.2-py2.py3-none-any.whl"
 
         with tempfile.TemporaryDirectory() as tmpdir:
-            self.touch(tmpdir, setuptools_filename)
             self.touch(tmpdir, pip_filename)
             # not used, make sure that it's ignored
             self.touch(tmpdir, "wheel-0.34.2-py2.py3-none-any.whl")
@@ -53,15 +49,12 @@ class TestPackages(unittest.TestCase):
                   unittest.mock.patch.object(ensurepip, '_WHEEL_PKG_DIR', tmpdir)):
                 packages = ensurepip._get_packages()
 
-            self.assertEqual(packages['setuptools'].version, '49.1.3')
-            self.assertEqual(packages['setuptools'].wheel_path,
-                             os.path.join(tmpdir, setuptools_filename))
             self.assertEqual(packages['pip'].version, '20.2.2')
             self.assertEqual(packages['pip'].wheel_path,
                              os.path.join(tmpdir, pip_filename))
 
             # wheel package is ignored
-            self.assertEqual(sorted(packages), ['pip', 'setuptools'])
+            self.assertEqual(sorted(packages), ['pip'])
 
 
 class EnsurepipMixin:
@@ -92,13 +85,13 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
-                unittest.mock.ANY, "setuptools", "pip",
+                unittest.mock.ANY, "pip",
             ],
             unittest.mock.ANY,
         )
 
         additional_paths = self.run_pip.call_args[0][1]
-        self.assertEqual(len(additional_paths), 2)
+        self.assertEqual(len(additional_paths), 1)
 
     def test_bootstrapping_with_root(self):
         ensurepip.bootstrap(root="/foo/bar/")
@@ -107,7 +100,7 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase):
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
                 unittest.mock.ANY, "--root", "/foo/bar/",
-                "setuptools", "pip",
+                "pip",
             ],
             unittest.mock.ANY,
         )
@@ -118,7 +111,7 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
-                unittest.mock.ANY, "--user", "setuptools", "pip",
+                unittest.mock.ANY, "--user", "pip",
             ],
             unittest.mock.ANY,
         )
@@ -129,7 +122,7 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
-                unittest.mock.ANY, "--upgrade", "setuptools", "pip",
+                unittest.mock.ANY, "--upgrade", "pip",
             ],
             unittest.mock.ANY,
         )
@@ -140,7 +133,7 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
-                unittest.mock.ANY, "-v", "setuptools", "pip",
+                unittest.mock.ANY, "-v", "pip",
             ],
             unittest.mock.ANY,
         )
@@ -151,7 +144,7 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
-                unittest.mock.ANY, "-vv", "setuptools", "pip",
+                unittest.mock.ANY, "-vv", "pip",
             ],
             unittest.mock.ANY,
         )
@@ -162,7 +155,7 @@ class TestBootstrap(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
-                unittest.mock.ANY, "-vvv", "setuptools", "pip",
+                unittest.mock.ANY, "-vvv", "pip",
             ],
             unittest.mock.ANY,
         )
@@ -239,7 +232,6 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "uninstall", "-y", "--disable-pip-version-check", "pip",
-                "setuptools",
             ]
         )
 
@@ -250,7 +242,6 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "uninstall", "-y", "--disable-pip-version-check", "-v", "pip",
-                "setuptools",
             ]
         )
 
@@ -261,7 +252,6 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "uninstall", "-y", "--disable-pip-version-check", "-vv", "pip",
-                "setuptools",
             ]
         )
 
@@ -272,7 +262,7 @@ class TestUninstall(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "uninstall", "-y", "--disable-pip-version-check", "-vvv",
-                "pip", "setuptools",
+                "pip"
             ]
         )
 
@@ -312,13 +302,13 @@ class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "install", "--no-cache-dir", "--no-index", "--find-links",
-                unittest.mock.ANY, "setuptools", "pip",
+                unittest.mock.ANY, "pip",
             ],
             unittest.mock.ANY,
         )
 
         additional_paths = self.run_pip.call_args[0][1]
-        self.assertEqual(len(additional_paths), 2)
+        self.assertEqual(len(additional_paths), 1)
         self.assertEqual(exit_code, 0)
 
     def test_bootstrapping_error_code(self):
@@ -344,7 +334,6 @@ class TestUninstallationMainFunction(EnsurepipMixin, unittest.TestCase):
         self.run_pip.assert_called_once_with(
             [
                 "uninstall", "-y", "--disable-pip-version-check", "pip",
-                "setuptools",
             ]
         )
 
index 7cccbe84f4ebfa1c077a5e0f566c1315fbec9038..333b97688af5b6343f115347808adbb949a8a0a5 100644 (file)
@@ -227,7 +227,6 @@ class BasicTest(BaseTest):
                         'install',
                         '--upgrade',
                         'pip',
-                        'setuptools'
                     ]
                 )
 
@@ -745,7 +744,6 @@ class EnsurePipTest(BaseTest):
         # future pip versions, this test can likely be relaxed further.
         out = out.decode("latin-1") # Force to text, prevent decoding errors
         self.assertIn("Successfully uninstalled pip", out)
-        self.assertIn("Successfully uninstalled setuptools", out)
         # Check pip is now gone from the virtual environment. This only
         # applies in the system_site_packages=False case, because in the
         # other case, pip may still be available in the system site-packages
index 2f87c62ccba866e9e4c6459e1ca0a1ffed6f12d8..2173c9b13e5cf7fda7a17ea2becef0cba587a1a1 100644 (file)
@@ -13,7 +13,7 @@ import sysconfig
 import types
 
 
-CORE_VENV_DEPS = ('pip', 'setuptools')
+CORE_VENV_DEPS = ('pip',)
 logger = logging.getLogger(__name__)
 
 
@@ -523,7 +523,7 @@ def main(args=None):
                              'this environment.')
     parser.add_argument('--upgrade-deps', default=False, action='store_true',
                         dest='upgrade_deps',
-                        help=f'Upgrade core dependencies: {", ".join(CORE_VENV_DEPS)} '
+                        help=f'Upgrade core dependencies ({", ".join(CORE_VENV_DEPS)}) '
                              'to the latest version in PyPI')
     options = parser.parse_args(args)
     if options.upgrade and options.clear:
index 36d05945b6fd909789b301ed9318c42947829a90..ce3c6c1c2bf9e6667a1afe415ebaf35ffa126028 100755 (executable)
@@ -56,19 +56,19 @@ if [ -d /usr/local/bin ] ; then
 
         cd /usr/local/bin
 
-        # Create pipx.y and easy_install-x.y links if /usr/local/bin/pythonx.y
+        # Create pipx.y links if /usr/local/bin/pythonx.y
         #   is linked to this framework version
         install_links_if_our_fw "python${PYVER}" \
-                                    "pip${PYVER}" "easy_install-${PYVER}"
+                                    "pip${PYVER}"
 
         # Create pipx link if /usr/local/bin/pythonx is linked to this version
         install_links_if_our_fw "python${PYMAJOR}" \
                                     "pip${PYMAJOR}"
 
-        # Create pip and easy_install link if /usr/local/bin/python
+        # Create pip link if /usr/local/bin/python
         #   is linked to this version
         install_links_if_our_fw "python" \
-                                    "pip" "easy_install"
+                                    "pip"
     )
 fi
 exit 0
index f9691288414538343b6aedb33e8a9382449baf42..69ab4198988570d5fd074e2ba345f24fc9130332 100644 (file)
@@ -166,7 +166,6 @@ altinstallunixtools:
        -if test "x$(ENSUREPIP)" != "xno"  ; then \
                cd "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" && \
                for fn in \
-                               easy_install-$(VERSION) \
                                pip$(VERSION) \
                                ; \
                do \
diff --git a/Misc/NEWS.d/next/Library/2023-01-14-17-54-56.gh-issue-95299.vUhpKz.rst b/Misc/NEWS.d/next/Library/2023-01-14-17-54-56.gh-issue-95299.vUhpKz.rst
new file mode 100644 (file)
index 0000000..29c3084
--- /dev/null
@@ -0,0 +1 @@
+Remove the bundled setuptools wheel from ``ensurepip``, and stop installing setuptools in environments created by ``venv``.
index 044d1fd6b3cf2d58eab2507a8804920746618e17..09fd5d9e3103ac95a82732bcbdb406b100d7bee4 100755 (executable)
@@ -14,7 +14,7 @@ import re
 from pathlib import Path
 from urllib.request import urlopen
 
-PACKAGE_NAMES = ("pip", "setuptools")
+PACKAGE_NAMES = ("pip",)
 ENSURE_PIP_ROOT = Path(__file__).parent.parent.parent / "Lib/ensurepip"
 WHEEL_DIR = ENSURE_PIP_ROOT / "_bundled"
 ENSURE_PIP_INIT_PY_TEXT = (ENSURE_PIP_ROOT / "__init__.py").read_text(encoding="utf-8")