Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-95299: Stop installing setuptools as a part of ensurepip and venv #101039

Merged
merged 21 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
001ee43
Use environment variables to pass data into test setup script
pradyunsg Jan 14, 2023
b8421a1
Update test_cppext to stop invoking setuptools-based script as a CLI
pradyunsg Jan 14, 2023
9d343f2
Stop installing setuptools as a part of ensurepip and venv
pradyunsg Sep 24, 2022
4a51332
Correct the name of step in GitHub Action
pradyunsg Jan 15, 2023
e0c53df
Drop most remaining references to `easy_install`
pradyunsg Feb 3, 2023
4c8e6be
fixup! Update test_cppext to stop invoking setuptools-based script as…
pradyunsg Feb 3, 2023
b489e52
fixup! Update test_cppext to stop invoking setuptools-based script as…
pradyunsg Feb 3, 2023
f308da4
Add a "What's New" entry for the setuptools removal
pradyunsg Feb 3, 2023
9579a3e
fixup! Add a "What's New" entry for the setuptools removal
pradyunsg Feb 3, 2023
0e2b55e
fixup! Add a "What's New" entry for the setuptools removal
pradyunsg Feb 3, 2023
0b8f384
Update Doc/whatsnew/3.12.rst
pradyunsg Feb 4, 2023
1262bee
Merge branch 'main' into remove-setuptools-ensurepip
arhadthedev Feb 23, 2023
bcda4cd
Merge branch 'main' into remove-setuptools-ensurepip
pradyunsg Feb 26, 2023
e19784d
Update "Creating virtual environments" section to drop reference
pradyunsg Apr 4, 2023
ea1bcea
Use the style suggested in review
pradyunsg Apr 4, 2023
5275f93
Use dirname on the absolute path
pradyunsg Apr 4, 2023
5c3ce99
Locate cppextdata with plain filesystem lookups
pradyunsg Apr 4, 2023
375b5c6
Merge branch 'main' into remove-setuptools-ensurepip
pradyunsg Apr 17, 2023
991d066
bundled pip -> bundled wheels
pradyunsg Apr 17, 2023
ebf6c3b
Unbreak `test_cppext`
pradyunsg Apr 17, 2023
b83cf9f
:art:
pradyunsg Apr 17, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/verify-ensurepip-wheels.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Verify bundled pip and setuptools
name: Verify bundled wheels

on:
workflow_dispatch:
Expand Down Expand Up @@ -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
7 changes: 5 additions & 2 deletions Doc/library/venv.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
7 changes: 5 additions & 2 deletions Doc/using/venv-create.inc
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.

18 changes: 18 additions & 0 deletions Doc/whatsnew/3.12.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
16 changes: 7 additions & 9 deletions Lib/ensurepip/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,9 @@


__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"),
]

Expand Down Expand Up @@ -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
pradyunsg marked this conversation as resolved.
Show resolved Hide resolved
#
# 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:
Expand Down Expand Up @@ -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)
Expand Down
Binary file not shown.
35 changes: 12 additions & 23 deletions Lib/test/test_ensurepip.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ def test_version(self):
# 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')
Expand All @@ -36,15 +35,12 @@ def test_get_packages_no_dir(self):

# 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")
Expand All @@ -53,15 +49,12 @@ def test_get_packages_with_dir(self):
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:
Expand Down Expand Up @@ -92,13 +85,13 @@ def test_basic_bootstrapping(self):
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/")
Expand All @@ -107,7 +100,7 @@ def test_bootstrapping_with_root(self):
[
"install", "--no-cache-dir", "--no-index", "--find-links",
unittest.mock.ANY, "--root", "/foo/bar/",
"setuptools", "pip",
"pip",
],
unittest.mock.ANY,
)
Expand All @@ -118,7 +111,7 @@ def test_bootstrapping_with_user(self):
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,
)
Expand All @@ -129,7 +122,7 @@ def test_bootstrapping_with_upgrade(self):
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,
)
Expand All @@ -140,7 +133,7 @@ def test_bootstrapping_with_verbosity_1(self):
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,
)
Expand All @@ -151,7 +144,7 @@ def test_bootstrapping_with_verbosity_2(self):
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,
)
Expand All @@ -162,7 +155,7 @@ def test_bootstrapping_with_verbosity_3(self):
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,
)
Expand Down Expand Up @@ -239,7 +232,6 @@ def test_uninstall(self):
self.run_pip.assert_called_once_with(
[
"uninstall", "-y", "--disable-pip-version-check", "pip",
"setuptools",
]
)

Expand All @@ -250,7 +242,6 @@ def test_uninstall_with_verbosity_1(self):
self.run_pip.assert_called_once_with(
[
"uninstall", "-y", "--disable-pip-version-check", "-v", "pip",
"setuptools",
]
)

Expand All @@ -261,7 +252,6 @@ def test_uninstall_with_verbosity_2(self):
self.run_pip.assert_called_once_with(
[
"uninstall", "-y", "--disable-pip-version-check", "-vv", "pip",
"setuptools",
]
)

Expand All @@ -272,7 +262,7 @@ def test_uninstall_with_verbosity_3(self):
self.run_pip.assert_called_once_with(
[
"uninstall", "-y", "--disable-pip-version-check", "-vvv",
"pip", "setuptools",
"pip"
]
)

Expand Down Expand Up @@ -312,13 +302,13 @@ def test_basic_bootstrapping(self):
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):
Expand All @@ -344,7 +334,6 @@ def test_basic_uninstall(self):
self.run_pip.assert_called_once_with(
[
"uninstall", "-y", "--disable-pip-version-check", "pip",
"setuptools",
]
)

Expand Down
2 changes: 0 additions & 2 deletions Lib/test/test_venv.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ def pip_cmd_checker(cmd, **kwargs):
'install',
'--upgrade',
'pip',
'setuptools'
]
)

Expand Down Expand Up @@ -745,7 +744,6 @@ def do_test_with_pip(self, system_site_packages):
# 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
Expand Down
4 changes: 2 additions & 2 deletions Lib/venv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import types


CORE_VENV_DEPS = ('pip', 'setuptools')
CORE_VENV_DEPS = ('pip',)
logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -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:
Expand Down
8 changes: 4 additions & 4 deletions Mac/BuildScript/scripts/postflight.ensurepip
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 0 additions & 1 deletion Mac/Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,6 @@ altinstallunixtools:
-if test "x$(ENSUREPIP)" != "xno" ; then \
cd "$(DESTDIR)$(FRAMEWORKUNIXTOOLSPREFIX)/bin" && \
for fn in \
easy_install-$(VERSION) \
pip$(VERSION) \
; \
do \
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Remove the bundled setuptools wheel from ``ensurepip``, and stop installing setuptools in environments created by ``venv``.
2 changes: 1 addition & 1 deletion Tools/build/verify_ensurepip_wheels.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
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")
Expand Down