8000 bpo-43976: add vendor config by FFY00 · Pull Request #25718 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

bpo-43976: add vendor config #25718

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

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Prev Previous commit
Next Next commit
forgot to add this to the main commit
I fixed the main commit in another branch, but forgot I am no longer
rebasing here .-.

Signed-off-by: Filipe Laíns <lains@riseup.net>
  • Loading branch information
FFY00 committed Oct 20, 2021
commit dd1c61a3c53899c85389ea5a9c8bba20d2391f6c
77 changes: 61 additions & 16 deletions Lib/_sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def _fix_pcbuild(d):

# constants

_ALL_INSTALL_SCHEMES = {
_BASE_INSTALL_SCHEMES = {
'posix_prefix': {
'stdlib': '{installed_base}/{platlibdir}/python{py_version_short}',
'platstdlib': '{platbase}/{platlibdir}/python{py_version_short}',
Expand Down Expand Up @@ -64,7 +64,8 @@ def _fix_pcbuild(d):
'scripts': '{base}/Scripts',
'data': '{base}',
},
# userbase schemes
}
_USER_INSTALL_SCHEMES = {
# NOTE: When modifying "purelib" scheme, update site._get_path() too.
'nt_user': {
'stdlib': '{userbase}/Python{py_version_nodot_plat}',
Expand Down Expand Up @@ -95,8 +96,6 @@ def _fix_pcbuild(d):
},
}

_USER_BASE_SCHEME_NAMES = ('nt_user', 'posix_user', 'osx_framework_user')

_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
'scripts', 'data')

Expand All @@ -108,7 +107,6 @@ def _fix_pcbuild(d):
_EXEC_PREFIX = os.path.normpath(sys.exec_prefix)
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)


_CHEAP_SCHEME_CONFIG_VARS = {
'prefix': _PREFIX,
'exec_prefix': _EXEC_PREFIX,
Expand Down Expand Up @@ -167,6 +165,9 @@ def is_python_build(check_home=False):

def __getattr__(name):
match name:
case '_BUILD_TIME_VARS':
_sysconfigdata = __import__(_get_sysconfigdata_name(), globals(), locals(), ['build_time_vars'], 0)
value = _sysconfigdata.build_time_vars
case '_HAS_USER_BASE':
value = (_getuserbase() is not None)
case '_PROJECT_BASE':
Expand All @@ -183,10 +184,31 @@ def __getattr__(name):

if (os.name == 'nt' and
value.lower().endswith(('\\pcbuild\\win32', '\\pcbuild\\amd64'))):
value = _safe_realpath(os.path.join(value, os.path.pardir, os.path.pardir))
value = _safe_realpath(os.path.join(_PROJECT_BASE, os.path.pardir, os.path.pardir))

if os.name == 'nt':
value = _fix_pcbuild(value)
case '_SRCDIR':
if os.name == 'posix' and not _MODULE._PYTHON_BUILD:
# srcdir is not meaningful since the installation is
# spread about the filesystem. We choose the
# directory containing the Makefile since we know it
# exists.
value = os.path.dirname(get_makefile_filename())
else:
if 'srcdir' in _MODULE._BUILD_TIME_VARS:
value = _MODULE._BUILD_TIME_VARS['srcdir']
else:
value = _MODULE._PROJECT_BASE

if os.name == 'posix' and _MODULE._PYTHON_BUILD:
# If srcdir is a relative path (typically '.' or '..')
# then it should be interpreted relative to the directory
# containing Makefile.
base = os.path.dirname(get_makefile_filename())
value = os.path.join(base, value)

value = _safe_realpath(value)
case '_SYS_HOME':
value = getattr(sys, '_home', None)
if os.name == 'nt':
Expand All @@ -208,23 +230,22 @@ def __getattr__(name):
def _get_raw_scheme_paths(scheme):
# lazy loading of install schemes -- only run the code paths we need to

# check our schemes
if scheme in _ALL_INSTALL_SCHEMES:
if scheme in _USER_BASE_SCHEME_NAMES and not _MODULE._HAS_USER_BASE:
raise KeyError(repr(scheme))

# check base schemes
if scheme in _BASE_INSTALL_SCHEMES:
if scheme in ('posix_prefix', 'posix_home') and _MODULE._PYTHON_BUILD:
# On POSIX-y platforms, Python will:
# - Build from .h files in 'headers' (which is only added to the
# scheme when building CPython)
# - Install .h files to 'include'
scheme = _ALL_INSTALL_SCHEMES[scheme]
scheme = _BASE_INSTALL_SCHEMES[scheme]
scheme['headers'] = scheme['include']
scheme['include'] = '{srcdir}/Include'
scheme['platinclude'] = '{projectbase}/.'
return scheme
return _BASE_INSTALL_SCHEMES[scheme]

return _ALL_INSTALL_SCHEMES[scheme]
if scheme in _USER_INSTALL_SCHEMES and _MODULE._HAS_USER_BASE:
return _USER_INSTALL_SCHEMES[scheme]

# check vendor schemes
try:
Expand All @@ -236,6 +257,28 @@ def _get_raw_scheme_paths(scheme):
return vendor_schemes[scheme]


def _get_sysconfigdata_name():
multiarch = getattr(sys.implementation, '_multiarch', '')
return os.environ.get(
'_PYTHON_SYSCONFIGDATA_NAME',
f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}',
)


def get_makefile_filename():
"""Return the path of the Makefile."""
if _MODULE._PYTHON_BUILD:
return os.path.join(_MODULE._SYS_HOME or _MODULE._PROJECT_BASE, "Makefile")
if hasattr(sys, 'abiflags'):
config_dir_name = f'config-{_PY_VERSION_SHORT}{sys.abiflags}'
else:
config_dir_name = 'config'
if hasattr(sys.implementation, '_multiarch'):
config_dir_name += f'-{sys.implementation._multiarch}'
stdlib = _get_paths(get_default_scheme())['stdlib']
return os.path.join(stdlib, config_dir_name, 'Makefile')


def _subst_vars(s, local_vars):
try:
return s.format(**local_vars)
Expand All @@ -256,9 +299,11 @@ def _expand_vars(scheme, vars):
if os.name in ('posix', 'nt'):
value = os.path.expanduser(value)

# this is an expensive and uncommon config var, let's only load it if we need to
# these are an expensive and uncommon config vars, let's only load them if we need to
if '{projectbase}' in value:
vars['projectbase'] = _MODULE._PROJECT_BASE
if '{srcdir}' in value:
vars['srcdir'] = _MODULE._SRCDIR

res[key] = os.path.normpath(_subst_vars(value, vars))
return res
Expand Down Expand Up @@ -296,8 +341,8 @@ def get_preferred_scheme(key):

scheme = _get_preferred_schemes()[key]

# check out schemes
if scheme in _ALL_INSTALL_SCHEMES:
# check our schemes
if scheme in _BASE_INSTALL_SCHEMES or scheme in _USER_INSTALL_SCHEMES:
return scheme

# check vendor schemes
Expand Down
51 changes: 17 additions & 34 deletions Lib/sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import os
import sys
from _sysconfig import (
_get_paths, _getuserbase, _safe_realpath,
get_default_scheme, get_preferred_scheme, is_python_build,
_HAS_USER_BASE, _ALL_INSTALL_SCHEMES, _USER_BASE_SCHEME_NAMES,
_PROJECT_BASE, _PYTHON_BUILD, _PY_VERSION_SHORT, _PY_VERSION_SHORT_NO_DOT,
_SCHEME_CONFIG_VARS, _SCHEME_KEYS, _SYS_HOME,
_get_paths, _getuserbase, _get_sysconfigdata_name, _safe_realpath,
get_default_scheme, get_preferred_scheme, get_makefile_filename,
is_python_build, _HAS_USER_BASE, _BASE_INSTALL_SCHEMES,
_USER_INSTALL_SCHEMES, _PROJECT_BASE, _PYTHON_BUILD, _PY_VERSION_SHORT,
_PY_VERSION_SHORT_NO_DOT, _SCHEME_CONFIG_VARS, _SCHEME_KEYS, _SYS_HOME,
)

__all__ = [
Expand All @@ -35,24 +35,28 @@
'MACOSX_DEPLOYMENT_TARGET',
}

_INSTALL_SCHEMES = {
key: value
for key, value in _ALL_INSTALL_SCHEMES.items()
if key not in _USER_BASE_SCHEME_NAMES
}
_INSTALL_SCHEMES = None


def _load_vendor_schemes():
def _reload_schemes():
global _INSTALL_SCHEMES

# our schemes
_INSTALL_SCHEMES = _BASE_INSTALL_SCHEMES.copy()
if _HAS_USER_BASE:
_INSTALL_SCHEMES |= _USER_INSTALL_SCHEMES

# vendor schemes
try:
import _vendor.config

_INSTALL_SCHEMES = _INSTALL_SCHEMES | _vendor.config.EXTRA_INSTALL_SCHEMES
# make sure we do not let the vendor install schemes override ours
_INSTALL_SCHEMES = _vendor.config.EXTRA_INSTALL_SCHEMES | _INSTALL_SCHEMES
except (ModuleNotFoundError, AttributeError):
pass


_load_vendor_schemes()
_reload_schemes()


_CONFIG_VARS = None
Expand Down Expand Up @@ -192,27 +196,6 @@ def _parse_makefile(filename, vars=None, keep_unresolved=True):
return vars


def get_makefile_filename():
"""Return the path of the Makefile."""
if _PYTHON_BUILD:
return os.path.join(_SYS_HOME or _PROJECT_BASE, "Makefile")
if hasattr(sys, 'abiflags'):
config_dir_name = f'config-{_PY_VERSION_SHORT}{sys.abiflags}'
else:
config_dir_name = 'config'
if hasattr(sys.implementation, '_multiarch'):
config_dir_name += f'-{sys.implementation._multiarch}'
return os.path.join(get_path('stdlib'), config_dir_name, 'Makefile')


def _get_sysconfigdata_name():
multiarch = getattr(sys.implementation, '_multiarch', '')
return os.environ.get(
'_PYTHON_SYSCONFIGDATA_NAME',
f'_sysconfigdata_{sys.abiflags}_{sys.platform}_{multiarch}',
)


def _generate_posix_vars():
"""Generate the Python module containing build-time variables."""
import pprint
Expand Down
2 changes: 2 additions & 0 deletions Lib/test/support/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2108,10 +2108,12 @@ def with_test_vendor_config():
import _vendor

_vendor.config = test.vendor_config
sysconfig._reload_schemes()

yield

if old_config:
_vendor.config = old_config
else:
delattr(_vendor, 'config')
sysconfig._reload_schemes()
3 changes: 1 addition & 2 deletions Lib/test/test_site.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,8 @@ def test_getsitepackages(self):

@with_test_vendor_config()
def test_getsitepackages_vendor(self):
# force re-load of vendor schemes with the patched sys.modules
# force re-load of vendor schemes
site._VENDOR_SCHEMES = None
_sysconfig._load_vendor_schemes()

site.PREFIXES = ['xoxo']
dirs = site.getsitepackages()
Expand Down
21 changes: 8 additions & 13 deletions Lib/test/test_sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
import sysconfig
from _sysconfig import _get_preferred_schemes_default, _expand_vars
from sysconfig import (get_paths, get_platform, get_config_vars,
get_path, get_path_names, _INSTALL_SCHEMES,
get_path, get_path_names, _INSTALL_SCHEMES, _SCHEME_KEYS,
get_default_scheme, get_scheme_names, get_config_var,
get_preferred_scheme, _main)
import _osx_support
Expand Down Expand Up @@ -112,7 +112,7 @@ def test_get_paths(self):
def test_get_path(self):
config_vars = get_config_vars()
for scheme in _INSTALL_SCHEMES:
for name in _INSTALL_SCHEMES[scheme]:
for name in _SCHEME_KEYS:
expected = _INSTALL_SCHEMES[scheme][name].format(**config_vars)
self.assertEqual(
os.path.normpath(get_path(name, scheme)),
Expand All @@ -124,9 +124,7 @@ def test_get_default_scheme(self):

@with_test_vendor_config()
def test_get_preferred_schemes_vendor(self):
# force re-load of vendor schemes with the patched sys.modules
_sysconfig._get_preferred_schemes = None
_sysconfig._load_vendor_schemes()

self.assertEqual(get_preferred_scheme('prefix'), 'some_vendor')

Expand Down Expand Up @@ -280,20 +278,17 @@ def test_get_config_h_filename(self):
self.assertTrue(os.path.isfile(config_h), config_h)

def test_get_scheme_names(self):
wanted = ['nt', 'posix_home', 'posix_prefix']
wanted = {'nt', 'posix_home', 'posix_prefix'}
if HAS_USER_BASE:
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
self.assertEqual(get_scheme_names(), tuple(sorted(wanted)))
wanted |= {'nt_user', 'osx_framework_user', 'posix_user'}
self.assertEqual(set(get_scheme_names()), wanted)

@with_test_vendor_config()
def test_get_scheme_names_vendor(self):
# force re-load of vendor schemes with the patched sys.modules
_sysconfig._load_vendor_schemes()

wanted = ['nt', 'posix_home', 'posix_prefix', 'some_vendor']
wanted = {'nt', 'posix_home', 'posix_prefix', 'some_vendor'}
52A4 if HAS_USER_BASE:
wanted.extend(['nt_user', 'osx_framework_user', 'posix_user'])
self.assertEqual(sysconfig.get_scheme_names(), tuple(sorted(wanted)))
wanted |= {'nt_user', 'osx_framework_user', 'posix_user'}
self.assertEqual(set(sysconfig.get_scheme_names()), wanted)

@skip_unless_symlink
def test_symlink(self): # Issue 7880
Expand Down
0