bpo-42856: Add --with-wheel-pkg-dir=PATH configure option (GH-24210)
Add --with-wheel-pkg-dir=PATH option to the ./configure script. If
specified, the ensurepip module looks for setuptools and pip wheel
packages in this directory: if both are present, these wheel packages
are used instead of ensurepip bundled wheel packages.
Some Linux distribution packaging policies recommend against bundling
dependencies. For example, Fedora installs wheel packages in the
/usr/share/python-wheels/ directory and don't install the
ensurepip._bundled package.
ensurepip: Remove unused runpy import.
diff --git a/Lib/test/test_ensurepip.py b/Lib/test/test_ensurepip.py
index 4786d28..bfca0cd 100644
--- a/Lib/test/test_ensurepip.py
+++ b/Lib/test/test_ensurepip.py
@@ -1,19 +1,68 @@
-import unittest
-import unittest.mock
-import test.support
+import contextlib
import os
import os.path
-import contextlib
import sys
+import tempfile
+import test.support
+import unittest
+import unittest.mock
import ensurepip
import ensurepip._uninstall
-class TestEnsurePipVersion(unittest.TestCase):
+class TestPackages(unittest.TestCase):
+ def touch(self, directory, filename):
+ fullname = os.path.join(directory, filename)
+ open(fullname, "wb").close()
- def test_returns_version(self):
- self.assertEqual(ensurepip._PIP_VERSION, ensurepip.version())
+ 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')
+
+ def test_get_packages_no_dir(self):
+ # Test _get_packages() without a wheel package directory
+ with (unittest.mock.patch.object(ensurepip, '_PACKAGES', None),
+ unittest.mock.patch.object(ensurepip, '_WHEEL_PKG_DIR', None)):
+ packages = ensurepip._get_packages()
+
+ # when bundled wheel packages are used, we get _PIP_VERSION
+ self.assertEqual(ensurepip._PIP_VERSION, ensurepip.version())
+
+ # 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")
+
+ with (unittest.mock.patch.object(ensurepip, '_PACKAGES', None),
+ 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'])
+
class EnsurepipMixin:
@@ -27,6 +76,8 @@ def setUp(self):
real_devnull = os.devnull
os_patch = unittest.mock.patch("ensurepip.os")
patched_os = os_patch.start()
+ # But expose os.listdir() used by _find_packages()
+ patched_os.listdir = os.listdir
self.addCleanup(os_patch.stop)
patched_os.devnull = real_devnull
patched_os.path = os.path
@@ -147,7 +198,7 @@ def test_pip_config_file_disabled(self):
self.assertEqual(self.os_environ["PIP_CONFIG_FILE"], os.devnull)
@contextlib.contextmanager
-def fake_pip(version=ensurepip._PIP_VERSION):
+def fake_pip(version=ensurepip.version()):
if version is None:
pip = None
else:
@@ -243,7 +294,7 @@ def test_pip_config_file_disabled(self):
# Basic testing of the main functions and their argument parsing
-EXPECTED_VERSION_OUTPUT = "pip " + ensurepip._PIP_VERSION
+EXPECTED_VERSION_OUTPUT = "pip " + ensurepip.version()
class TestBootstrappingMainFunction(EnsurepipMixin, unittest.TestCase):