Skip to content

Commit 3e640bc

Browse files
authored
Merge pull request #10358 from uranusjr/sysconfig-switch-python-310
Switch install scheme backend to sysconfig
2 parents 77e7431 + d1d9bc5 commit 3e640bc

File tree

7 files changed

+45
-15
lines changed

7 files changed

+45
-15
lines changed

news/10358.removal.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
On Python 3.10 or later, the installation scheme backend has been changed to use
2+
``sysconfig``. This is to anticipate the deprecation of ``distutils`` in Python
3+
3.10, and its scheduled removal in 3.12. For compatibility considerations, pip
4+
installations running on Python 3.9 or lower will continue to use ``distutils``.

setup.cfg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ follow_imports = skip
5555
addopts = --ignore src/pip/_vendor --ignore tests/tests_cache -r aR --color=yes
5656
markers =
5757
network: tests that need network
58+
incompatible_with_sysconfig
5859
incompatible_with_test_venv
5960
incompatible_with_venv
6061
no_auto_tempdir_manager

src/pip/_internal/locations/__init__.py

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545

4646
_PLATLIBDIR: str = getattr(sys, "platlibdir", "lib")
4747

48+
_USE_SYSCONFIG = sys.version_info >= (3, 10)
49+
4850

4951
def _looks_like_bpo_44860() -> bool:
5052
"""The resolution to bpo-44860 will change this incorrect platlib.
@@ -190,15 +192,18 @@ def get_scheme(
190192
isolated: bool = False,
191193
prefix: Optional[str] = None,
192194
) -> Scheme:
193-
old = _distutils.get_scheme(
195+
new = _sysconfig.get_scheme(
194196
dist_name,
195197
user=user,
196198
home=home,
197199
root=root,
198200
isolated=isolated,
199201
prefix=prefix,
200202
)
201-
new = _sysconfig.get_scheme(
203+
if _USE_SYSCONFIG:
204+
return new
205+
206+
old = _distutils.get_scheme(
202207
dist_name,
203208
user=user,
204209
home=home,
@@ -335,8 +340,11 @@ def get_scheme(
335340

336341

337342
def get_bin_prefix() -> str:
338-
old = _distutils.get_bin_prefix()
339343
new = _sysconfig.get_bin_prefix()
344+
if _USE_SYSCONFIG:
345+
return new
346+
347+
old = _distutils.get_bin_prefix()
340348
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="bin_prefix"):
341349
_log_context()
342350
return old
@@ -365,8 +373,11 @@ def _looks_like_deb_system_dist_packages(value: str) -> bool:
365373

366374
def get_purelib() -> str:
367375
"""Return the default pure-Python lib location."""
368-
old = _distutils.get_purelib()
369376
new = _sysconfig.get_purelib()
377+
if _USE_SYSCONFIG:
378+
return new
379+
380+
old = _distutils.get_purelib()
370381
if _looks_like_deb_system_dist_packages(old):
371382
return old
372383
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="purelib"):
@@ -376,19 +387,32 @@ def get_purelib() -> str:
376387

377388
def get_platlib() -> str:
378389
"""Return the default platform-shared lib location."""
379-
old = _distutils.get_platlib()
380390
new = _sysconfig.get_platlib()
391+
if _USE_SYSCONFIG:
392+
return new
393+
394+
old = _distutils.get_platlib()
381395
if _looks_like_deb_system_dist_packages(old):
382396
return old
383397
if _warn_if_mismatch(pathlib.Path(old), pathlib.Path(new), key="platlib"):
384398
_log_context()
385399
return old
386400

387401

402+
def _deduplicated(v1: str, v2: str) -> List[str]:
403+
"""Deduplicate values from a list."""
404+
if v1 == v2:
405+
return [v1]
406+
return [v1, v2]
407+
408+
388409
def get_prefixed_libs(prefix: str) -> List[str]:
389410
"""Return the lib locations under ``prefix``."""
390-
old_pure, old_plat = _distutils.get_prefixed_libs(prefix)
391411
new_pure, new_plat = _sysconfig.get_prefixed_libs(prefix)
412+
if _USE_SYSCONFIG:
413+
return _deduplicated(new_pure, new_plat)
414+
415+
old_pure, old_plat = _distutils.get_prefixed_libs(prefix)
392416

393417
warned = [
394418
_warn_if_mismatch(
@@ -405,6 +429,4 @@ def get_prefixed_libs(prefix: str) -> List[str]:
405429
if any(warned):
406430
_log_context(prefix=prefix)
407431

408-
if old_pure == old_plat:
409-
return [old_pure]
410-
return [old_pure, old_plat]
432+
return _deduplicated(old_pure, old_plat)

src/pip/_internal/operations/install/wheel.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -628,10 +628,7 @@ def pyc_output_path(path: str) -> str:
628628
with warnings.catch_warnings():
629629
warnings.filterwarnings("ignore")
630630
for path in pyc_source_file_paths():
631-
# Python 2's `compileall.compile_file` requires a str in
632-
# error cases, so we must convert to the native type.
633-
path_arg = ensure_str(path, encoding=sys.getfilesystemencoding())
634-
success = compileall.compile_file(path_arg, force=True, quiet=True)
631+
success = compileall.compile_file(path, force=True, quiet=True)
635632
if success:
636633
pyc_path = pyc_output_path(path)
637634
assert os.path.exists(pyc_path)

tests/conftest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from setuptools.wheel import Wheel
1616

1717
from pip._internal.cli.main import main as pip_entry_point
18+
from pip._internal.locations import _USE_SYSCONFIG
1819
from pip._internal.utils.temp_dir import global_tempdir_manager
1920
from tests.lib import DATA_DIR, SRC_DIR, PipTestEnvironment, TestData
2021
from tests.lib.certs import make_tls_cert, serialize_cert, serialize_key
@@ -77,6 +78,9 @@ def pytest_collection_modifyitems(config, items):
7778
):
7879
item.add_marker(pytest.mark.skip("Incompatible with venv"))
7980

81+
if item.get_closest_marker("incompatible_with_sysconfig") and _USE_SYSCONFIG:
82+
item.add_marker(pytest.mark.skip("Incompatible with sysconfig"))
83+
8084
module_path = os.path.relpath(
8185
item.module.__file__,
8286
os.path.commonprefix([__file__, item.module.__file__]),

tests/unit/test_locations.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ def test_root_modifies_appropriately(self, monkeypatch):
9696
expected = os.path.join(root, path[1:])
9797
assert os.path.abspath(root_scheme[key]) == expected
9898

99+
@pytest.mark.incompatible_with_sysconfig
99100
@pytest.mark.incompatible_with_venv
100101
def test_distutils_config_file_read(self, tmpdir, monkeypatch):
101102
# This deals with nt/posix path differences
@@ -116,10 +117,11 @@ def test_distutils_config_file_read(self, tmpdir, monkeypatch):
116117
scheme = _get_scheme_dict("example")
117118
assert scheme["scripts"] == install_scripts
118119

120+
@pytest.mark.incompatible_with_sysconfig
119121
@pytest.mark.incompatible_with_venv
120122
# when we request install-lib, we should install everything (.py &
121123
# .so) into that path; i.e. ensure platlib & purelib are set to
122-
# this path
124+
# this path. sysconfig does not support this.
123125
def test_install_lib_takes_precedence(self, tmpdir, monkeypatch):
124126
# This deals with nt/posix path differences
125127
install_lib = os.path.normcase(

tests/unit/test_wheel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,7 @@ def test_install_prefix(self, data, tmpdir):
422422
self.name,
423423
user=False,
424424
home=None,
425-
root=tmpdir,
425+
root=str(tmpdir), # Casting needed for CPython 3.10+. See GH-10358.
426426
isolated=False,
427427
prefix=prefix,
428428
)

0 commit comments

Comments
 (0)