Skip to content
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

GH-127178: install a _sysconfig_vars_(...).json file in the stdlib directory #127302

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
37 changes: 28 additions & 9 deletions Lib/sysconfig/__main__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import json
import os
import sys
import types
from sysconfig import (
_ALWAYS_STR,
_PYTHON_BUILD,
Expand Down Expand Up @@ -157,6 +159,19 @@ def _print_config_dict(d, stream):
print ("}", file=stream)


def _get_pybuilddir():
pybuilddir = f'build/lib.{get_platform()}-{get_python_version()}'
if hasattr(sys, "gettotalrefcount"):
pybuilddir += '-pydebug'
return pybuilddir


def _get_json_data_name():
name = _get_sysconfigdata_name()
assert name.startswith('_sysconfigdata')
return name.replace('_sysconfigdata', '_sysconfig_vars') + '.json'


def _generate_posix_vars():
"""Generate the Python module containing build-time variables."""
vars = {}
Expand Down Expand Up @@ -185,6 +200,8 @@ def _generate_posix_vars():
if _PYTHON_BUILD:
vars['BLDSHARED'] = vars['LDSHARED']

name = _get_sysconfigdata_name()

# There's a chicken-and-egg situation on OS X with regards to the
# _sysconfigdata module after the changes introduced by #15298:
# get_config_vars() is called by get_platform() as part of the
Expand All @@ -196,16 +213,13 @@ def _generate_posix_vars():
# _sysconfigdata module manually and populate it with the build vars.
# This is more than sufficient for ensuring the subsequent call to
# get_platform() succeeds.
name = _get_sysconfigdata_name()
if 'darwin' in sys.platform:
import types
module = types.ModuleType(name)
module.build_time_vars = vars
sys.modules[name] = module
# GH-127178: Since we started generating a .json file, we also need this to
# be able to run sysconfig.get_config_vars().
module = types.ModuleType(name)
module.build_time_vars = vars
sys.modules[name] = module

pybuilddir = f'build/lib.{get_platform()}-{get_python_version()}'
if hasattr(sys, "gettotalrefcount"):
pybuilddir += '-pydebug'
pybuilddir = _get_pybuilddir()
os.makedirs(pybuilddir, exist_ok=True)
destfile = os.path.join(pybuilddir, name + '.py')

Expand All @@ -215,6 +229,11 @@ def _generate_posix_vars():
f.write('build_time_vars = ')
_print_config_dict(vars, stream=f)

# Write a JSON file with the output of sysconfig.get_config_vars
jsonfile = os.path.join(pybuilddir, _get_json_data_name())
with open(jsonfile, 'w') as f:
json.dump(get_config_vars(), f, indent=2)

# Create file used for sys.path fixup -- see Modules/getpath.c
with open('pybuilddir.txt', 'w', encoding='utf8') as f:
f.write(pybuilddir)
Expand Down
33 changes: 31 additions & 2 deletions Lib/test/test_sysconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from test.support import (
captured_stdout,
is_android,
is_apple_mobile,
is_wasi,
PythonSymlink,
Expand All @@ -25,8 +26,9 @@
from sysconfig import (get_paths, get_platform, get_config_vars,
get_path, get_path_names, _INSTALL_SCHEMES,
get_default_scheme, get_scheme_names, get_config_var,
_expand_vars, _get_preferred_schemes)
from sysconfig.__main__ import _main, _parse_makefile
_expand_vars, _get_preferred_schemes,
is_python_build, _PROJECT_BASE)
from sysconfig.__main__ import _main, _parse_makefile, _get_pybuilddir, _get_json_data_name
import _imp
import _osx_support
import _sysconfig
Expand All @@ -39,6 +41,7 @@ class TestSysConfig(unittest.TestCase):

def setUp(self):
super(TestSysConfig, self).setUp()
self.maxDiff = None
self.sys_path = sys.path[:]
# patching os.uname
if hasattr(os, 'uname'):
Expand Down Expand Up @@ -625,6 +628,32 @@ def test_makefile_overwrites_config_vars(self):
self.assertNotEqual(data['prefix'], data['base_prefix'])
self.assertNotEqual(data['exec_prefix'], data['base_exec_prefix'])

@unittest.skipIf(os.name != 'posix', '_sysconfig-vars JSON file is only available on POSIX')
@unittest.skipIf(is_wasi, "_sysconfig-vars JSON file currently isn't available on WASI")
@unittest.skipIf(is_android or is_apple_mobile, 'Android and iOS change the prefix')
def test_sysconfigdata_json(self):
if '_PYTHON_SYSCONFIGDATA_PATH' in os.environ:
data_dir = os.environ['_PYTHON_SYSCONFIGDATA_PATH']
elif is_python_build():
data_dir = os.path.join(_PROJECT_BASE, _get_pybuilddir())
else:
data_dir = sys._stdlib_dir

json_data_path = os.path.join(data_dir, _get_json_data_name())

with open(json_data_path) as f:
json_config_vars = json.load(f)

system_config_vars = get_config_vars()

# Ignore keys in the check
for key in ('projectbase', 'srcdir'):
json_config_vars.pop(key)
system_config_vars.pop(key)

self.assertEqual(system_config_vars, json_config_vars)


class MakefileTests(unittest.TestCase):

@unittest.skipIf(sys.platform.startswith('win'),
Expand Down
4 changes: 2 additions & 2 deletions Makefile.pre.in
Original file line number Diff line number Diff line change
Expand Up @@ -2645,8 +2645,8 @@ libinstall: all $(srcdir)/Modules/xxmodule.c
esac; \
done; \
done
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py \
$(DESTDIR)$(LIBDEST); \
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfigdata_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).py $(DESTDIR)$(LIBDEST); \
$(INSTALL_DATA) `cat pybuilddir.txt`/_sysconfig_vars_$(ABIFLAGS)_$(MACHDEP)_$(MULTIARCH).json $(DESTDIR)$(LIBDEST); \
$(INSTALL_DATA) $(srcdir)/LICENSE $(DESTDIR)$(LIBDEST)/LICENSE.txt
@ # If app store compliance has been configured, apply the patch to the
@ # installed library code. The patch has been previously validated against
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
A ``_sysconfig_vars_(...).json`` file is now shipped in the standard library
directory. It contains the output of :func:`sysconfig.get_config_vars` on
the default environment encoded as JSON data. This is an implementation
detail, and may change at any time.
Loading