def _resolve_scheme(name): os_name, sep, key = name.partition('_') try: resolved = sysconfig.get_preferred_scheme(key) except Exception: resolved = fw.scheme(_pypy_hack(name)) return resolved
def _infer_prefix() -> str: """Try to find a prefix scheme for the current platform. This tries: * A special ``osx_framework_library`` for Python distributed by Apple's Command Line Tools, when not running in a virtual environment. * Implementation + OS, used by PyPy on Windows (``pypy_nt``). * Implementation without OS, used by PyPy on POSIX (``pypy``). * OS + "prefix", used by CPython on POSIX (``posix_prefix``). * Just the OS name, used by CPython on Windows (``nt``). If none of the above works, fall back to ``posix_prefix``. """ if _HAS_PREFERRED_SCHEME_API: return sysconfig.get_preferred_scheme("prefix") # type: ignore os_framework_global = is_osx_framework() and not running_under_virtualenv() if os_framework_global and "osx_framework_library" in _AVAILABLE_SCHEMES: return "osx_framework_library" implementation_suffixed = f"{sys.implementation.name}_{os.name}" if implementation_suffixed in _AVAILABLE_SCHEMES: return implementation_suffixed if sys.implementation.name in _AVAILABLE_SCHEMES: return sys.implementation.name suffixed = f"{os.name}_prefix" if suffixed in _AVAILABLE_SCHEMES: return suffixed if os.name in _AVAILABLE_SCHEMES: # On Windows, prefx is just called "nt". return os.name return "posix_prefix"
def select_scheme(self, name): os_name, sep, key = name.partition('_') try: resolved = sysconfig.get_preferred_scheme(key) except Exception: resolved = self._pypy_hack(name) return self._select_scheme(resolved)
def _infer_home() -> str: """Try to find a home for the current platform.""" if _HAS_PREFERRED_SCHEME_API: return sysconfig.get_preferred_scheme("home") # type: ignore suffixed = f"{os.name}_home" if suffixed in _AVAILABLE_SCHEMES: return suffixed return "posix_home"
def test_custom_venv_install_scheme_is_prefered(mocker): # The paths in this test are Fedora paths, but we set them for nt as well, so the test also works on Windows, # despite the actual values are nonsense there. # Values were simplified to be compatible with all the supported Python versions. default_scheme = { "stdlib": "{base}/lib/python{py_version_short}", "platstdlib": "{platbase}/lib/python{py_version_short}", "purelib": "{base}/local/lib/python{py_version_short}/site-packages", "platlib": "{platbase}/local/lib/python{py_version_short}/site-packages", "include": "{base}/include/python{py_version_short}", "platinclude": "{platbase}/include/python{py_version_short}", "scripts": "{base}/local/bin", "data": "{base}/local", } venv_scheme = {key: path.replace("local", "") for key, path in default_scheme.items()} sysconfig_install_schemes = { "posix_prefix": default_scheme, "nt": default_scheme, "pypy": default_scheme, "pypy_nt": default_scheme, "venv": venv_scheme, } if getattr(sysconfig, "get_preferred_scheme", None): sysconfig_install_schemes[sysconfig.get_preferred_scheme("prefix")] = default_scheme if sys.version_info[0] == 2: sysconfig_install_schemes = _stringify_schemes_dict(sysconfig_install_schemes) # On Python < 3.10, the distutils schemes are not derived from sysconfig schemes # So we mock them as well to assert the custom "venv" install scheme has priority distutils_scheme = { "purelib": "$base/local/lib/python$py_version_short/site-packages", "platlib": "$platbase/local/lib/python$py_version_short/site-packages", "headers": "$base/include/python$py_version_short/$dist_name", "scripts": "$base/local/bin", "data": "$base/local", } distutils_schemes = { "unix_prefix": distutils_scheme, "nt": distutils_scheme, } if sys.version_info[0] == 2: distutils_schemes = _stringify_schemes_dict(distutils_schemes) # We need to mock distutils first, so they don't see the mocked sysconfig, # if imported for the first time. # That can happen if the actual interpreter has the "venv" INSTALL_SCHEME # and hence this is the first time we are touching distutils in this process. # If distutils saw our mocked sysconfig INSTALL_SCHEMES, we would need # to define all install schemes. mocker.patch("distutils.command.install.INSTALL_SCHEMES", distutils_schemes) mocker.patch("sysconfig._INSTALL_SCHEMES", sysconfig_install_schemes) pyinfo = PythonInfo() pyver = f"{pyinfo.version_info.major}.{pyinfo.version_info.minor}" assert pyinfo.install_path("scripts") == "bin" assert pyinfo.install_path("purelib").replace(os.sep, "/") == f"lib/python{pyver}/site-packages"
def _infer_user() -> str: """Try to find a user scheme for the current platform.""" if _HAS_PREFERRED_SCHEME_API: return sysconfig.get_preferred_scheme("user") # type: ignore if is_osx_framework() and not running_under_virtualenv(): suffixed = "osx_framework_user" else: suffixed = f"{os.name}_user" if suffixed in _AVAILABLE_SCHEMES: return suffixed if "posix_user" not in _AVAILABLE_SCHEMES: # User scheme unavailable. raise UserInstallationInvalid() return "posix_user"