Skip to content

Commit 0111638

Browse files
committed
Reuse _sysconfig.config_vars() to get the Python version
* Move also py_version_short and py_version_nodot to _sysconfig. * Use _sysconfig.config_vars() on all platforms, no only Windows.
1 parent a4c2664 commit 0111638

File tree

3 files changed

+47
-35
lines changed

3 files changed

+47
-35
lines changed

Lib/sysconfig/__init__.py

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,6 @@ def joinuser(*args):
173173
_SCHEME_KEYS = ('stdlib', 'platstdlib', 'purelib', 'platlib', 'include',
174174
'scripts', 'data')
175175

176-
_PY_VERSION = _sysconfig.PY_VERSION
177-
_PY_VERSION_SHORT = f'{sys.version_info[0]}.{sys.version_info[1]}'
178-
_PY_VERSION_SHORT_NO_DOT = f'{sys.version_info[0]}{sys.version_info[1]}'
179176
_BASE_PREFIX = os.path.normpath(sys.base_prefix)
180177
_BASE_EXEC_PREFIX = os.path.normpath(sys.base_exec_prefix)
181178
# Mutex guarding initialization of _CONFIG_VARS.
@@ -324,7 +321,8 @@ def get_makefile_filename():
324321
return os.path.join(_PROJECT_BASE, "Makefile")
325322

326323
if hasattr(sys, 'abiflags'):
327-
config_dir_name = f'config-{_PY_VERSION_SHORT}{sys.abiflags}'
324+
py_version_short = f'{sys.version_info[0]}.{sys.version_info[1]}'
325+
config_dir_name = f'config-{py_version_short}{sys.abiflags}'
328326
else:
329327
config_dir_name = 'config'
330328

@@ -390,9 +388,6 @@ def _init_non_posix(vars):
390388
vars['BINLIBDEST'] = get_path('platstdlib')
391389
vars['INCLUDEPY'] = get_path('include')
392390

393-
# Add EXT_SUFFIX, SOABI, Py_DEBUG, and Py_GIL_DISABLED
394-
vars.update(_sysconfig.config_vars())
395-
396391
# NOTE: ABIFLAGS is only an emulated value. It is not present during build
397392
# on Windows. sys.abiflags is absent on Windows and vars['abiflags']
398393
# is already widely used to calculate paths, so it should remain an
@@ -410,7 +405,7 @@ def _init_non_posix(vars):
410405
vars['LIBRARY'] = os.path.basename(_safe_realpath(dllhandle))
411406
vars['LDLIBRARY'] = vars['LIBRARY']
412407
vars['EXE'] = '.exe'
413-
vars['VERSION'] = _PY_VERSION_SHORT_NO_DOT
408+
vars['VERSION'] = vars['py_version_nodot']
414409
vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable))
415410
# No standard path exists on Windows for this, but we'll check
416411
# whether someone is imitating a POSIX-like layout
@@ -505,6 +500,10 @@ def _init_config_vars():
505500
global _CONFIG_VARS
506501
_CONFIG_VARS = {}
507502

503+
# Add py_version, Py_DEBUG, and Py_GIL_DISABLED.
504+
# On Windows, add also EXT_SUFFIX and SOABI.
505+
_CONFIG_VARS.update(_sysconfig.config_vars())
506+
508507
prefix = os.path.normpath(sys.prefix)
509508
exec_prefix = os.path.normpath(sys.exec_prefix)
510509
base_prefix = _BASE_PREFIX
@@ -530,9 +529,6 @@ def _init_config_vars():
530529
# Distutils.
531530
_CONFIG_VARS['prefix'] = prefix
532531
_CONFIG_VARS['exec_prefix'] = exec_prefix
533-
_CONFIG_VARS['py_version'] = _PY_VERSION
534-
_CONFIG_VARS['py_version_short'] = _PY_VERSION_SHORT
535-
_CONFIG_VARS['py_version_nodot'] = _PY_VERSION_SHORT_NO_DOT
536532
_CONFIG_VARS['installed_base'] = base_prefix
537533
_CONFIG_VARS['base'] = prefix
538534
_CONFIG_VARS['installed_platbase'] = base_exec_prefix
@@ -739,11 +735,11 @@ def get_platform():
739735

740736

741737
def get_python_version():
742-
return _PY_VERSION_SHORT
738+
return get_config_var('py_version_short')
743739

744740

745741
def _get_python_version_abi():
746-
return _PY_VERSION_SHORT + get_config_var("abi_thread")
742+
return get_config_var('py_version_short') + get_config_var("abi_thread")
747743

748744

749745
def expand_makefile_vars(s, vars):

Lib/test/test_sysconfig.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,11 +743,19 @@ def test_sysconfig_config_vars_no_prefix_cache(self):
743743

744744
def test_py_version(self):
745745
config_vars = sysconfig.get_config_vars()
746-
py_version = config_vars['py_version']
747-
self.assertIsInstance(py_version, str)
746+
self.assertIsInstance(config_vars['py_version'], str)
748747
ver = sys.version_info
749748
version = f'{ver.major}.{ver.minor}.{ver.micro}'
750-
self.assertStartsWith(py_version, version)
749+
# py_version can be longer such as "3.15.0a7+" instead of "3.15.0"
750+
self.assertStartsWith(config_vars['py_version'], version)
751+
752+
self.assertIsInstance(config_vars['py_version_short'], str)
753+
self.assertEqual(config_vars['py_version_short'],
754+
f'{ver.major}.{ver.minor}')
755+
756+
self.assertIsInstance(config_vars['py_version_nodot'], str)
757+
self.assertEqual(config_vars['py_version_nodot'],
758+
f'{ver.major}{ver.minor}')
751759

752760

753761
class MakefileTests(unittest.TestCase):

Modules/_sysconfig.c

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,13 @@ module _sysconfig
1717

1818
#include "clinic/_sysconfig.c.h"
1919

20-
#ifdef MS_WINDOWS
20+
21+
#define py_version_short() \
22+
(Py_STRINGIFY(PY_MAJOR_VERSION) "." Py_STRINGIFY(PY_MINOR_VERSION))
23+
#define py_version_nodot() \
24+
(Py_STRINGIFY(PY_MAJOR_VERSION) Py_STRINGIFY(PY_MINOR_VERSION))
25+
26+
2127
static int
2228
add_string_value(PyObject *dict, const char *key, const char *str_value)
2329
{
@@ -29,7 +35,7 @@ add_string_value(PyObject *dict, const char *key, const char *str_value)
2935
Py_DECREF(value);
3036
return err;
3137
}
32-
#endif
38+
3339

3440
/*[clinic input]
3541
@permit_long_summary
@@ -47,14 +53,23 @@ _sysconfig_config_vars_impl(PyObject *module)
4753
return NULL;
4854
}
4955

56+
// Python version
57+
if (add_string_value(config, "py_version", PY_VERSION) < 0) {
58+
goto error;
59+
}
60+
if (add_string_value(config, "py_version_short", py_version_short()) < 0) {
61+
goto error;
62+
}
63+
if (add_string_value(config, "py_version_nodot", py_version_nodot()) < 0) {
64+
goto error;
65+
}
66+
5067
#ifdef MS_WINDOWS
5168
if (add_string_value(config, "EXT_SUFFIX", PYD_TAGGED_SUFFIX) < 0) {
52-
Py_DECREF(config);
53-
return NULL;
69+
goto error;
5470
}
5571
if (add_string_value(config, "SOABI", PYD_SOABI) < 0) {
56-
Py_DECREF(config);
57-
return NULL;
72+
goto error;
5873
}
5974
#endif
6075

@@ -64,8 +79,7 @@ _sysconfig_config_vars_impl(PyObject *module)
6479
PyObject *py_gil_disabled = _PyLong_GetZero();
6580
#endif
6681
if (PyDict_SetItemString(config, "Py_GIL_DISABLED", py_gil_disabled) < 0) {
67-
Py_DECREF(config);
68-
return NULL;
82+
goto error;
6983
}
7084

7185
#ifdef Py_DEBUG
@@ -74,11 +88,14 @@ _sysconfig_config_vars_impl(PyObject *module)
7488
PyObject *py_debug = _PyLong_GetZero();
7589
#endif
7690
if (PyDict_SetItemString(config, "Py_DEBUG", py_debug) < 0) {
77-
Py_DECREF(config);
78-
return NULL;
91+
goto error;
7992
}
8093

8194
return config;
95+
96+
error:
97+
Py_DECREF(config);
98+
return NULL;
8299
}
83100

84101
#ifdef MS_WINDOWS
@@ -117,14 +134,6 @@ _sysconfig_get_platform_impl(PyObject *module)
117134
#endif // MS_WINDOWS
118135

119136

120-
static int
121-
sysconfig_module_exec(PyObject *module)
122-
{
123-
return PyModule_Add(module, "PY_VERSION",
124-
PyUnicode_FromString(PY_VERSION));
125-
}
126-
127-
128137
PyDoc_STRVAR(sysconfig__doc__,
129138
"A helper for the sysconfig module.");
130139

@@ -135,7 +144,6 @@ static struct PyMethodDef sysconfig_methods[] = {
135144
};
136145

137146
static PyModuleDef_Slot sysconfig_slots[] = {
138-
{Py_mod_exec, sysconfig_module_exec},
139147
{Py_mod_multiple_interpreters, Py_MOD_PER_INTERPRETER_GIL_SUPPORTED},
140148
{Py_mod_gil, Py_MOD_GIL_NOT_USED},
141149
{0, NULL}

0 commit comments

Comments
 (0)