Skip to content

Commit

Permalink
Allow to decide whether to use distutils or sysconfig with sysconfig.…
Browse files Browse the repository at this point in the history
…_PIP_USE_SYSCONFIG

Fixes pypa#10647
  • Loading branch information
hroncok committed Nov 20, 2021
1 parent 4cdb516 commit 63b5051
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
9 changes: 9 additions & 0 deletions news/10647.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
Allow Python distributors to opt-out from or opt-in to the ``sysconfig``
installation scheme backend. By default, the installation scheme backend is
``sysconfig`` on Python 3.10 or later, but by setting the ``sysconfig._PIP_USE_SYSCONFIG``
the distributors can override this default: The boolean value of this private ``sysconfig``
attribute will take precedence over the default if set.
This can be used for compatibility considerations as well as for opting in for more leading-edge
technology if so desired.
Distributors who set ``sysconfig._PIP_USE_SYSCONFIG = False`` are strongly encouraged to ensure ``distutils`` is present,
e.g. it is not recommended to set this when ``distutils`` was removed from the standard library, as it will result in failures.
17 changes: 16 additions & 1 deletion src/pip/_internal/locations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,22 @@

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

_USE_SYSCONFIG = sys.version_info >= (3, 10)

def _should_use_sysconfig() -> bool:
"""
This function determines the value of _USE_SYSCONFIG.
By default, pip uses sysconfig on Python 3.10+.
But Python distributors can override this decision by setting:
sysconfig._PIP_USE_SYSCONFIG = True / False
Rationale in https://github.com/pypa/pip/issues/10647
"""
if hasattr(sysconfig, "_PIP_USE_SYSCONFIG"):
return bool(sysconfig._PIP_USE_SYSCONFIG) # type: ignore [attr-defined]
return sys.version_info >= (3, 10)


# This is a function for testability, but should be constant during any one run.
_USE_SYSCONFIG = _should_use_sysconfig()


def _looks_like_bpo_44860() -> bool:
Expand Down
21 changes: 20 additions & 1 deletion tests/unit/test_locations.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
import os
import shutil
import sys
import sysconfig
import tempfile
from typing import Any, Dict
from unittest.mock import Mock

import pytest

from pip._internal.locations import SCHEME_KEYS, get_scheme
from pip._internal.locations import SCHEME_KEYS, _should_use_sysconfig, get_scheme
from tests.lib.path import Path

if sys.platform == "win32":
Expand Down Expand Up @@ -82,6 +83,24 @@ def get_mock_getpwuid(self, uid: int) -> pwd.struct_passwd:
result.pw_name = self.username
return result

def test_default_should_use_sysconfig(
self, monkeypatch: pytest.MonkeyPatch
) -> None:
monkeypatch.delattr(sysconfig, "_PIP_USE_SYSCONFIG", raising=False)
if sys.version_info[:2] >= (3, 10):
assert _should_use_sysconfig() is True
else:
assert _should_use_sysconfig() is False

@pytest.mark.parametrize("vendor_value", [True, False, None, "", 0, 1])
def test_vendor_overriden_should_use_sysconfig(
self, monkeypatch: pytest.MonkeyPatch, vendor_value: Any
) -> None:
monkeypatch.setattr(
sysconfig, "_PIP_USE_SYSCONFIG", vendor_value, raising=False
)
assert _should_use_sysconfig() is bool(vendor_value)


class TestDistutilsScheme:
def test_root_modifies_appropriately(self) -> None:
Expand Down

0 comments on commit 63b5051

Please sign in to comment.