From 31b7eab6ee6264912f61abde5e9f5a515c777eb6 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 28 Mar 2025 00:19:33 +0800 Subject: [PATCH 01/43] Add `ABIFLAGS` to `sysconfig.get_config_vars()` on Windows --- Lib/sysconfig/__init__.py | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 18e6b8d25e5b56..42d9ffb919747b 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -414,6 +414,13 @@ def _init_non_posix(vars): vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) vars['TZPATH'] = '' + abiflags = vars['abi_thread'] + if vars['EXT_SUFFIX'].endswith('_d.'): + abiflags += 'd' + # Do not touch lower-cased `abiflags` here. + # sys.abiflags is absent on Windows. So vars['abiflags'] should be empty. + vars['ABIFLAGS'] = abiflags + # # public APIs # @@ -541,6 +548,9 @@ def _init_config_vars(): except AttributeError: _CONFIG_VARS['py_version_nodot_plat'] = '' + # e.g., 't' for free-threaded or '' for default build + _CONFIG_VARS['abi_thread'] = 't' if _CONFIG_VARS.get('Py_GIL_DISABLED') else '' + if os.name == 'nt': _init_non_posix(_CONFIG_VARS) _CONFIG_VARS['VPATH'] = sys._vpath @@ -550,9 +560,6 @@ def _init_config_vars(): # the init-function. _CONFIG_VARS['userbase'] = _getuserbase() - # e.g., 't' for free-threaded or '' for default build - _CONFIG_VARS['abi_thread'] = 't' if _CONFIG_VARS.get('Py_GIL_DISABLED') else '' - # Always convert srcdir to an absolute path srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE) if os.name == 'posix': From dc458977134f42475c646373e3115e7701a566a8 Mon Sep 17 00:00:00 2001 From: "blurb-it[bot]" <43283697+blurb-it[bot]@users.noreply.github.com> Date: Thu, 27 Mar 2025 16:23:01 +0000 Subject: [PATCH 02/43] =?UTF-8?q?=F0=9F=93=9C=F0=9F=A4=96=20Added=20by=20b?= =?UTF-8?q?lurb=5Fit.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../next/Windows/2025-03-27-16-22-58.gh-issue-127405.aASs2Z.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 Misc/NEWS.d/next/Windows/2025-03-27-16-22-58.gh-issue-127405.aASs2Z.rst diff --git a/Misc/NEWS.d/next/Windows/2025-03-27-16-22-58.gh-issue-127405.aASs2Z.rst b/Misc/NEWS.d/next/Windows/2025-03-27-16-22-58.gh-issue-127405.aASs2Z.rst new file mode 100644 index 00000000000000..a6d5985ff4c7b8 --- /dev/null +++ b/Misc/NEWS.d/next/Windows/2025-03-27-16-22-58.gh-issue-127405.aASs2Z.rst @@ -0,0 +1 @@ +Add ``ABIFLAGS`` to :func:`sysconfig.get_config_vars` on Windows. Patch by Xuehai Pan. From 9a4586a617cc738e7cf1f75ebd7a8451509b710d Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 28 Mar 2025 02:07:46 +0800 Subject: [PATCH 03/43] Add tests --- Lib/test/test_sysconfig.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 3738914cf17de8..e08b90611b385f 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -592,6 +592,10 @@ def test_osx_ext_suffix(self): suffix = sysconfig.get_config_var('EXT_SUFFIX') self.assertTrue(suffix.endswith('-darwin.so'), suffix) + def test_always_set_ABIFLAGS(self): + self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) + self.assertIsInstance(sysconfig.get_config_var('ABIFLAGS'), str) + @requires_subprocess() def test_makefile_overwrites_config_vars(self): script = textwrap.dedent(""" From 76c85bbee5fb42b3936fc683f4709747a0737b33 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 28 Mar 2025 16:01:45 +0800 Subject: [PATCH 04/43] Move `ABIFLAGS` definition to C code --- Lib/sysconfig/__init__.py | 12 +++++------- Misc/ACKS | 1 + Modules/_sysconfig.c | 24 ++++++++++++++++++++++++ 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 42d9ffb919747b..97db2f3cbb2f5a 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -401,7 +401,11 @@ def _init_non_posix(vars): vars['BINLIBDEST'] = get_path('platstdlib') vars['INCLUDEPY'] = get_path('include') - # Add EXT_SUFFIX, SOABI, and Py_GIL_DISABLED + # Add EXT_SUFFIX, SOABI, ABIFLAGS, and Py_GIL_DISABLED (defined in Modules/_sysconfig.c) + # NOTE: ABIFLAGS is only an emulated value. It is not present during build + # on Windows. sys.abiflags is absent on Windows and `vars['abiflags'] + # is already widely used to calculate paths. vars['abiflags'] should + # remain empty string. vars.update(_sysconfig.config_vars()) vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) @@ -414,12 +418,6 @@ def _init_non_posix(vars): vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) vars['TZPATH'] = '' - abiflags = vars['abi_thread'] - if vars['EXT_SUFFIX'].endswith('_d.'): - abiflags += 'd' - # Do not touch lower-cased `abiflags` here. - # sys.abiflags is absent on Windows. So vars['abiflags'] should be empty. - vars['ABIFLAGS'] = abiflags # # public APIs diff --git a/Misc/ACKS b/Misc/ACKS index b0b4ea0db44b64..e7a7bac5ca151e 100644 --- a/Misc/ACKS +++ b/Misc/ACKS @@ -1402,6 +1402,7 @@ Todd R. Palmer Juan David Ibáñez Palomar Nicola Palumbo Jan Palus +Xuehai Pan Yongzhi Pan Martin Panter Mathias Panzenböck diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c index c50c5cfabc2f1f..ebf2d24075abe4 100644 --- a/Modules/_sysconfig.c +++ b/Modules/_sysconfig.c @@ -55,6 +55,30 @@ _sysconfig_config_vars_impl(PyObject *module) Py_DECREF(config); return NULL; } + + // On Unix, the `ABIFLAGS` key is defined via a different logic. +# ifdef Py_GIL_DISABLED +# define _SYSCONFIG_ABI_THREAD "t" +# else +# define _SYSCONFIG_ABI_THREAD "" +# endif +# ifdef _DEBUG +# define _SYSCONFIG_ABI_DEBUG "d" +# else +# define _SYSCONFIG_ABI_DEBUG "" +# endif +# define _SYSCONFIG_ABIFLAGS (_SYSCONFIG_ABI_THREAD _SYSCONFIG_ABI_DEBUG) + + // Emulate `sys.abiflags` value on Unix for Windows. ABIFLAGS here is only + // an emulated value. It is not present during build on Windows. + if (add_string_value(config, "ABIFLAGS", SYSCONFIG_ABIFLAGS) < 0) { + Py_DECREF(config); + return NULL; + } + +# undef _SYSCONFIG_ABI_THREAD +# undef _SYSCONFIG_ABI_DEBUG +# undef _SYSCONFIG_ABIFLAGS #endif #ifdef Py_GIL_DISABLED From b98419b410d2a7f2a7a93f4351657f074e88a5d1 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 28 Mar 2025 16:24:14 +0800 Subject: [PATCH 05/43] Revert now unrelated changes --- Lib/sysconfig/__init__.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 97db2f3cbb2f5a..479883d117c39f 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -401,12 +401,12 @@ def _init_non_posix(vars): vars['BINLIBDEST'] = get_path('platstdlib') vars['INCLUDEPY'] = get_path('include') - # Add EXT_SUFFIX, SOABI, ABIFLAGS, and Py_GIL_DISABLED (defined in Modules/_sysconfig.c) + # Add EXT_SUFFIX, SOABI, ABIFLAGS, and Py_GIL_DISABLED # NOTE: ABIFLAGS is only an emulated value. It is not present during build # on Windows. sys.abiflags is absent on Windows and `vars['abiflags'] # is already widely used to calculate paths. vars['abiflags'] should # remain empty string. - vars.update(_sysconfig.config_vars()) + vars.update(_sysconfig.config_vars()) # defined in Modules/_sysconfig.c vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) if hasattr(sys, 'dllhandle'): @@ -418,7 +418,6 @@ def _init_non_posix(vars): vars['BINDIR'] = os.path.dirname(_safe_realpath(sys.executable)) vars['TZPATH'] = '' - # # public APIs # @@ -546,9 +545,6 @@ def _init_config_vars(): except AttributeError: _CONFIG_VARS['py_version_nodot_plat'] = '' - # e.g., 't' for free-threaded or '' for default build - _CONFIG_VARS['abi_thread'] = 't' if _CONFIG_VARS.get('Py_GIL_DISABLED') else '' - if os.name == 'nt': _init_non_posix(_CONFIG_VARS) _CONFIG_VARS['VPATH'] = sys._vpath @@ -558,6 +554,9 @@ def _init_config_vars(): # the init-function. _CONFIG_VARS['userbase'] = _getuserbase() + # e.g., 't' for free-threaded or '' for default build + _CONFIG_VARS['abi_thread'] = 't' if _CONFIG_VARS.get('Py_GIL_DISABLED') else '' + # Always convert srcdir to an absolute path srcdir = _CONFIG_VARS.get('srcdir', _PROJECT_BASE) if os.name == 'posix': From 4729f76217cc78a8ebd8c5364a10da53f22b984c Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 28 Mar 2025 16:30:22 +0800 Subject: [PATCH 06/43] Fix variable name --- Modules/_sysconfig.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c index ebf2d24075abe4..dd18bad08acfba 100644 --- a/Modules/_sysconfig.c +++ b/Modules/_sysconfig.c @@ -71,7 +71,7 @@ _sysconfig_config_vars_impl(PyObject *module) // Emulate `sys.abiflags` value on Unix for Windows. ABIFLAGS here is only // an emulated value. It is not present during build on Windows. - if (add_string_value(config, "ABIFLAGS", SYSCONFIG_ABIFLAGS) < 0) { + if (add_string_value(config, "ABIFLAGS", _SYSCONFIG_ABIFLAGS) < 0) { Py_DECREF(config); return NULL; } From 04cbb1c2a860137190a6bcf64e2d46ce5252b8fc Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 00:59:39 +0800 Subject: [PATCH 07/43] Refactor string concatination --- Modules/_sysconfig.c | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c index dd18bad08acfba..7fc3e86cfb67f0 100644 --- a/Modules/_sysconfig.c +++ b/Modules/_sysconfig.c @@ -57,28 +57,21 @@ _sysconfig_config_vars_impl(PyObject *module) } // On Unix, the `ABIFLAGS` key is defined via a different logic. + // + // Emulate `sys.abiflags` value on Unix for Windows. ABIFLAGS here is only + // an emulated value. It is not present during build on Windows. + if (add_string_value(config, "ABIFLAGS", # ifdef Py_GIL_DISABLED -# define _SYSCONFIG_ABI_THREAD "t" -# else -# define _SYSCONFIG_ABI_THREAD "" + "t" # endif # ifdef _DEBUG -# define _SYSCONFIG_ABI_DEBUG "d" -# else -# define _SYSCONFIG_ABI_DEBUG "" + "d" # endif -# define _SYSCONFIG_ABIFLAGS (_SYSCONFIG_ABI_THREAD _SYSCONFIG_ABI_DEBUG) - - // Emulate `sys.abiflags` value on Unix for Windows. ABIFLAGS here is only - // an emulated value. It is not present during build on Windows. - if (add_string_value(config, "ABIFLAGS", _SYSCONFIG_ABIFLAGS) < 0) { + "") + < 0) { Py_DECREF(config); return NULL; } - -# undef _SYSCONFIG_ABI_THREAD -# undef _SYSCONFIG_ABI_DEBUG -# undef _SYSCONFIG_ABIFLAGS #endif #ifdef Py_GIL_DISABLED From a6045ea23b599eead4e0c22b89bcf70995111ddf Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 02:33:26 +0800 Subject: [PATCH 08/43] Set `Py_DEBUG` flag in sysconfig --- Lib/sysconfig/__init__.py | 2 +- Modules/_sysconfig.c | 19 ++++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 479883d117c39f..ca03c33af7bbfb 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -401,7 +401,7 @@ def _init_non_posix(vars): vars['BINLIBDEST'] = get_path('platstdlib') vars['INCLUDEPY'] = get_path('include') - # Add EXT_SUFFIX, SOABI, ABIFLAGS, and Py_GIL_DISABLED + # Add EXT_SUFFIX, SOABI, ABIFLAGS, Py_DEBUG, and Py_GIL_DISABLED # NOTE: ABIFLAGS is only an emulated value. It is not present during build # on Windows. sys.abiflags is absent on Windows and `vars['abiflags'] # is already widely used to calculate paths. vars['abiflags'] should diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c index 7fc3e86cfb67f0..ccdce2bc9ac614 100644 --- a/Modules/_sysconfig.c +++ b/Modules/_sysconfig.c @@ -64,8 +64,15 @@ _sysconfig_config_vars_impl(PyObject *module) # ifdef Py_GIL_DISABLED "t" # endif -# ifdef _DEBUG +# ifdef Py_DEBUG +# ifndef _DEBUG +# error "_DEBUG not defined while Py_DEBUG is defined on Windows" +# endif "d" +# else +# ifdef _DEBUG +# error "_DEBUG defined while Py_DEBUG is not defined on Windows" +# endif # endif "") < 0) { @@ -84,6 +91,16 @@ _sysconfig_config_vars_impl(PyObject *module) return NULL; } +#ifdef Py_DEBUG + PyObject *py_debug = _PyLong_GetOne(); +#else + PyObject *py_debug = _PyLong_GetZero(); +#endif + if (PyDict_SetItemString(config, "Py_DEBUG", py_debug) < 0) { + Py_DECREF(config); + return NULL; + } + return config; } From 584e0b056677cae93a1531a8f46e203707fd5cc2 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 02:35:15 +0800 Subject: [PATCH 09/43] Update comments from code review --- Lib/sysconfig/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index ca03c33af7bbfb..759b8da1337e0c 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -403,9 +403,9 @@ def _init_non_posix(vars): # Add EXT_SUFFIX, SOABI, ABIFLAGS, Py_DEBUG, and Py_GIL_DISABLED # NOTE: ABIFLAGS is only an emulated value. It is not present during build - # on Windows. sys.abiflags is absent on Windows and `vars['abiflags'] - # is already widely used to calculate paths. vars['abiflags'] should - # remain empty string. + # on Windows. sys.abiflags is absent on Windows and vars['abiflags'] + # is already widely used to calculate paths, so it should remain an + # empty string. vars.update(_sysconfig.config_vars()) # defined in Modules/_sysconfig.c vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) From 93257bec96a9c07945d4d05a1ea8535d87bc97a2 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 02:54:06 +0800 Subject: [PATCH 10/43] Prefer `Py_DEBUG` over `_DEBUG` --- Include/internal/pycore_importdl.h | 2 +- Modules/_sysconfig.c | 7 ------- PC/launcher.c | 2 +- PC/pyconfig.h.in | 17 +++++++++-------- PC/python_uwp.cpp | 4 ++-- PC/python_ver_rc.h | 2 +- PCbuild/pyproject.props | 2 +- Python/dynload_win.c | 6 +++--- 8 files changed, 18 insertions(+), 24 deletions(-) diff --git a/Include/internal/pycore_importdl.h b/Include/internal/pycore_importdl.h index 525a16f6b97274..3ba9229cc21378 100644 --- a/Include/internal/pycore_importdl.h +++ b/Include/internal/pycore_importdl.h @@ -107,7 +107,7 @@ extern int _PyImport_RunModInitFunc( #include typedef FARPROC dl_funcptr; -#ifdef _DEBUG +#ifdef Py_DEBUG # define PYD_DEBUG_SUFFIX "_d" #else # define PYD_DEBUG_SUFFIX "" diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c index ccdce2bc9ac614..728cb4b252f2e3 100644 --- a/Modules/_sysconfig.c +++ b/Modules/_sysconfig.c @@ -65,14 +65,7 @@ _sysconfig_config_vars_impl(PyObject *module) "t" # endif # ifdef Py_DEBUG -# ifndef _DEBUG -# error "_DEBUG not defined while Py_DEBUG is defined on Windows" -# endif "d" -# else -# ifdef _DEBUG -# error "_DEBUG defined while Py_DEBUG is not defined on Windows" -# endif # endif "") < 0) { diff --git a/PC/launcher.c b/PC/launcher.c index 47fafbc3bf6bad..40e6630b82e17a 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -140,7 +140,7 @@ static wchar_t * get_env(wchar_t * key) return buf; } -#if defined(_DEBUG) +#if defined(Py_DEBUG) /* Do not define EXECUTABLEPATH_VALUE in debug builds as it'll never point to the debug build. */ #if defined(_WINDOWS) diff --git a/PC/pyconfig.h.in b/PC/pyconfig.h.in index 9e70303868e5de..2fa73807c93bac 100644 --- a/PC/pyconfig.h.in +++ b/PC/pyconfig.h.in @@ -289,6 +289,11 @@ typedef int pid_t; # include #endif +// _DEBUG implies Py_DEBUG +#ifdef _DEBUG +# define Py_DEBUG +#endif + /* 64 bit ints are usually spelt __int64 unless compiler has overridden */ #ifndef PY_LONG_LONG # define PY_LONG_LONG __int64 @@ -319,21 +324,21 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ This is relevant when using build-system generator (e.g CMake) where the linking is explicitly handled */ # if defined(Py_GIL_DISABLED) -# if defined(_DEBUG) +# if defined(Py_DEBUG) # pragma comment(lib,"python314t_d.lib") # elif defined(Py_LIMITED_API) # pragma comment(lib,"python3t.lib") # else # pragma comment(lib,"python314t.lib") -# endif /* _DEBUG */ +# endif /* Py_DEBUG */ # else /* Py_GIL_DISABLED */ -# if defined(_DEBUG) +# if defined(Py_DEBUG) # pragma comment(lib,"python314_d.lib") # elif defined(Py_LIMITED_API) # pragma comment(lib,"python3.lib") # else # pragma comment(lib,"python314.lib") -# endif /* _DEBUG */ +# endif /* Py_DEBUG */ # endif /* Py_GIL_DISABLED */ # endif /* _MSC_VER && !Py_NO_LINK_LIB */ # endif /* Py_BUILD_CORE */ @@ -376,10 +381,6 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ # define ALIGNOF_MAX_ALIGN_T 8 #endif -#ifdef _DEBUG -# define Py_DEBUG -#endif - #ifdef MS_WIN32 diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp index b9c408a580c999..8cdb8d722cdb9a 100644 --- a/PC/python_uwp.cpp +++ b/PC/python_uwp.cpp @@ -19,13 +19,13 @@ #include #ifdef PYTHONW -#ifdef _DEBUG +#ifdef Py_DEBUG const wchar_t *PROGNAME = L"pythonw_d.exe"; #else const wchar_t *PROGNAME = L"pythonw.exe"; #endif #else -#ifdef _DEBUG +#ifdef Py_DEBUG const wchar_t *PROGNAME = L"python_d.exe"; #else const wchar_t *PROGNAME = L"python.exe"; diff --git a/PC/python_ver_rc.h b/PC/python_ver_rc.h index ee867fe41224c3..bb98144cd03f15 100644 --- a/PC/python_ver_rc.h +++ b/PC/python_ver_rc.h @@ -10,7 +10,7 @@ #define MS_WINDOWS #include "modsupport.h" #include "patchlevel.h" -#ifdef _DEBUG +#ifdef Py_DEBUG # define PYTHON_DEBUG_EXT "_d" #else # define PYTHON_DEBUG_EXT diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 4e414dc913b9d5..83a34cf18961df 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -42,7 +42,7 @@ <_DebugPreprocessorDefinition>NDEBUG; - <_DebugPreprocessorDefinition Condition="$(Configuration) == 'Debug'">_DEBUG; + <_DebugPreprocessorDefinition Condition="$(Configuration) == 'Debug'">_DEBUG;Py_DEBUG; <_PyStatsPreprocessorDefinition>PyStats; <_PyStatsPreprocessorDefinition Condition="$(PySTATS) != ''">Py_STATS; <_PlatformPreprocessorDefinition>_WIN32; diff --git a/Python/dynload_win.c b/Python/dynload_win.c index 6324063401e51f..de9b0a77817a63 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -108,7 +108,7 @@ static char *GetPythonImport (HINSTANCE hModule) char *pch; /* Don't claim that python3.dll is a Python DLL. */ -#ifdef _DEBUG +#ifdef Py_DEBUG if (strcmp(import_name, "python3_d.dll") == 0) { #else if (strcmp(import_name, "python3.dll") == 0) { @@ -120,7 +120,7 @@ static char *GetPythonImport (HINSTANCE hModule) /* Ensure python prefix is followed only by numbers to the end of the basename */ pch = import_name + 6; -#ifdef _DEBUG +#ifdef Py_DEBUG while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') { #else while (*pch && *pch != '.') { @@ -300,7 +300,7 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, char buffer[256]; PyOS_snprintf(buffer, sizeof(buffer), -#ifdef _DEBUG +#ifdef Py_DEBUG "python%d%d_d.dll", #else "python%d%d.dll", From 30c7b56442cb29aa2c02e7beab96e25e3c69345a Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 02:56:25 +0800 Subject: [PATCH 11/43] Add tests --- Lib/test/test_sysconfig.py | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index e08b90611b385f..f951af75b894ae 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -596,6 +596,20 @@ def test_always_set_ABIFLAGS(self): self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) self.assertIsInstance(sysconfig.get_config_var('ABIFLAGS'), str) + def test_always_set_Py_DEBUG(self): + self.assertIn('Py_DEBUG', sysconfig.get_config_vars()) + self.assertIn(sysconfig.get_config_var('Py_DEBUG'), (0, 1)) + + def test_ABIFLAGS(self): + if sysconfig.get_config_var('Py_DEBUG'): + self.assertIn('d', sysconfig.get_config_var('ABIFLAGS')) + else: + self.assertNotIn('d', sysconfig.get_config_var('ABIFLAGS')) + if sysconfig.get_config_var('Py_GIL_DISABLED'): + self.assertIn('t', sysconfig.get_config_var('ABIFLAGS')) + else: + self.assertNotIn('t', sysconfig.get_config_var('ABIFLAGS')) + @requires_subprocess() def test_makefile_overwrites_config_vars(self): script = textwrap.dedent(""" From 97942b29fcf7d184a88793a3589da8aeb11f69b9 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 03:13:34 +0800 Subject: [PATCH 12/43] Add tests --- Lib/test/test_sysconfig.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index f951af75b894ae..089d221149b0c2 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -595,20 +595,29 @@ def test_osx_ext_suffix(self): def test_always_set_ABIFLAGS(self): self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) self.assertIsInstance(sysconfig.get_config_var('ABIFLAGS'), str) + self.assertIn('abiflags', sysconfig.get_config_vars()) + self.assertIsInstance(sysconfig.get_config_var('abiflags'), str) def test_always_set_Py_DEBUG(self): self.assertIn('Py_DEBUG', sysconfig.get_config_vars()) self.assertIn(sysconfig.get_config_var('Py_DEBUG'), (0, 1)) + def test_always_set_Py_GIL_DISABLED(self): + self.assertIn('Py_GIL_DISABLED', sysconfig.get_config_vars()) + self.assertIn(sysconfig.get_config_var('Py_GIL_DISABLED'), (0, 1)) + def test_ABIFLAGS(self): + abiflags = sysconfig.get_config_var('abiflags') + ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') + self.assertIn(abiflags, ABIFLAGS) if sysconfig.get_config_var('Py_DEBUG'): - self.assertIn('d', sysconfig.get_config_var('ABIFLAGS')) + self.assertIn('d', ABIFLAGS) else: - self.assertNotIn('d', sysconfig.get_config_var('ABIFLAGS')) + self.assertNotIn('d', ABIFLAGS) if sysconfig.get_config_var('Py_GIL_DISABLED'): - self.assertIn('t', sysconfig.get_config_var('ABIFLAGS')) + self.assertIn('t', ABIFLAGS) else: - self.assertNotIn('t', sysconfig.get_config_var('ABIFLAGS')) + self.assertNotIn('t', ABIFLAGS) @requires_subprocess() def test_makefile_overwrites_config_vars(self): From f49067e5441925c330735c5aa8e6e5d137c0d251 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 03:35:59 +0800 Subject: [PATCH 13/43] Update tests --- Lib/test/test_sysconfig.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 089d221149b0c2..90eea625da2139 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -9,6 +9,7 @@ import textwrap from copy import copy +from test import support from test.support import ( captured_stdout, is_android, @@ -592,29 +593,38 @@ def test_osx_ext_suffix(self): suffix = sysconfig.get_config_var('EXT_SUFFIX') self.assertTrue(suffix.endswith('-darwin.so'), suffix) - def test_always_set_ABIFLAGS(self): + def test_always_set_abiflags(self): self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) self.assertIsInstance(sysconfig.get_config_var('ABIFLAGS'), str) self.assertIn('abiflags', sysconfig.get_config_vars()) self.assertIsInstance(sysconfig.get_config_var('abiflags'), str) - def test_always_set_Py_DEBUG(self): + def test_always_set_py_debug(self): self.assertIn('Py_DEBUG', sysconfig.get_config_vars()) - self.assertIn(sysconfig.get_config_var('Py_DEBUG'), (0, 1)) + Py_DEBUG = sysconfig.get_config_var('Py_DEBUG') + self.assertIn(Py_DEBUG, (0, 1)) + self.assertEqual(Py_DEBUG, support.Py_DEBUG) - def test_always_set_Py_GIL_DISABLED(self): + def test_always_set_py_gil_disabled(self): self.assertIn('Py_GIL_DISABLED', sysconfig.get_config_vars()) - self.assertIn(sysconfig.get_config_var('Py_GIL_DISABLED'), (0, 1)) + Py_GIL_DISABLED = sysconfig.get_config_var('Py_GIL_DISABLED') + self.assertIn(Py_GIL_DISABLED, (0, 1)) + self.assertEqual(Py_GIL_DISABLED, support.Py_GIL_DISABLED) - def test_ABIFLAGS(self): + def test_abiflags(self): abiflags = sysconfig.get_config_var('abiflags') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') + self.assertIn(abiflags, ABIFLAGS) - if sysconfig.get_config_var('Py_DEBUG'): + + if os.name == 'nt': + self.assertEqual(abiflags, '') + + if support.Py_DEBUG: self.assertIn('d', ABIFLAGS) else: self.assertNotIn('d', ABIFLAGS) - if sysconfig.get_config_var('Py_GIL_DISABLED'): + if support.Py_GIL_DISABLED: self.assertIn('t', ABIFLAGS) else: self.assertNotIn('t', ABIFLAGS) From 8fa952bab3b6352d34847b95068ad52e0f6ee2f2 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Sat, 29 Mar 2025 04:01:26 +0800 Subject: [PATCH 14/43] Update tests --- Lib/test/test_sys.py | 2 ++ Lib/test/test_sysconfig.py | 6 +++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index c64a80d83f154e..1cec36fc0df6bd 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -719,6 +719,8 @@ def test_attributes(self): self.assertIn(sys.float_repr_style, ('short', 'legacy')) if not sys.platform.startswith('win'): self.assertIsInstance(sys.abiflags, str) + else: + self.assertFalse(hasattr(sys, 'abiflags')) def test_thread_info(self): info = sys.thread_info diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 90eea625da2139..7679ae2a3e76de 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -615,13 +615,17 @@ def test_abiflags(self): abiflags = sysconfig.get_config_var('abiflags') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') + self.assertIsInstance(abiflags, str) + self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) + if ABIFLAGS: + self.assertTrue(ABIFLAGS.isalpha(), ABIFLAGS) if os.name == 'nt': self.assertEqual(abiflags, '') if support.Py_DEBUG: - self.assertIn('d', ABIFLAGS) + self.assertEndsWith(ABIFLAGS, 'd') else: self.assertNotIn('d', ABIFLAGS) if support.Py_GIL_DISABLED: From b667dd9364105ee2c6bdb82f490c4cc6a483f3d9 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 00:32:22 +0800 Subject: [PATCH 15/43] Remove unnecessary comments --- Lib/sysconfig/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 759b8da1337e0c..e780b577c84870 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -406,7 +406,7 @@ def _init_non_posix(vars): # on Windows. sys.abiflags is absent on Windows and vars['abiflags'] # is already widely used to calculate paths, so it should remain an # empty string. - vars.update(_sysconfig.config_vars()) # defined in Modules/_sysconfig.c + vars.update(_sysconfig.config_vars()) vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) if hasattr(sys, 'dllhandle'): From 5df954061715c500310023a04a5fdb3360334d2a Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 02:33:54 +0800 Subject: [PATCH 16/43] Update What's New --- Doc/whatsnew/3.14.rst | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Doc/whatsnew/3.14.rst b/Doc/whatsnew/3.14.rst index ac5b53ef94bfb1..fada56fa6e063a 100644 --- a/Doc/whatsnew/3.14.rst +++ b/Doc/whatsnew/3.14.rst @@ -936,6 +936,14 @@ sys.monitoring * Two new events are added: :monitoring-event:`BRANCH_LEFT` and :monitoring-event:`BRANCH_RIGHT`. The ``BRANCH`` event is deprecated. + +sysconfig +--------- + +* Add ``ABIFLAGS`` key to :func:`sysconfig.get_config_vars` on Windows. + (Contributed by Xuehai Pan in :gh:`131799`.) + + threading --------- @@ -943,6 +951,7 @@ threading to :attr:`threading.Thread.name`. (Contributed by Victor Stinner in :gh:`59705`.) + tkinter ------- From 4f22ff3875aa1d53ba0a74d1dd290dcaae3bfb1a Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 22:44:18 +0800 Subject: [PATCH 17/43] Revert `PCbuild/pyproject.props` --- PCbuild/pyproject.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PCbuild/pyproject.props b/PCbuild/pyproject.props index 83a34cf18961df..4e414dc913b9d5 100644 --- a/PCbuild/pyproject.props +++ b/PCbuild/pyproject.props @@ -42,7 +42,7 @@ <_DebugPreprocessorDefinition>NDEBUG; - <_DebugPreprocessorDefinition Condition="$(Configuration) == 'Debug'">_DEBUG;Py_DEBUG; + <_DebugPreprocessorDefinition Condition="$(Configuration) == 'Debug'">_DEBUG; <_PyStatsPreprocessorDefinition>PyStats; <_PyStatsPreprocessorDefinition Condition="$(PySTATS) != ''">Py_STATS; <_PlatformPreprocessorDefinition>_WIN32; From a4646c541cd18eb5aa0468d99153a928b48c750b Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 23:04:45 +0800 Subject: [PATCH 18/43] Revert `_DEBUG` -> `Py_DEBUG` --- PC/launcher.c | 2 +- PC/pyconfig.h.in | 17 ++++++++--------- PC/python_uwp.cpp | 4 ++-- PC/python_ver_rc.h | 2 +- Python/dynload_win.c | 6 +++--- 5 files changed, 15 insertions(+), 16 deletions(-) diff --git a/PC/launcher.c b/PC/launcher.c index 40e6630b82e17a..47fafbc3bf6bad 100644 --- a/PC/launcher.c +++ b/PC/launcher.c @@ -140,7 +140,7 @@ static wchar_t * get_env(wchar_t * key) return buf; } -#if defined(Py_DEBUG) +#if defined(_DEBUG) /* Do not define EXECUTABLEPATH_VALUE in debug builds as it'll never point to the debug build. */ #if defined(_WINDOWS) diff --git a/PC/pyconfig.h.in b/PC/pyconfig.h.in index f29a62eb45b0bb..9e70303868e5de 100644 --- a/PC/pyconfig.h.in +++ b/PC/pyconfig.h.in @@ -102,11 +102,6 @@ WIN32 is still required for the locale module. /* #define Py_GIL_DISABLED 1 */ #endif -// _DEBUG implies Py_DEBUG -#ifdef _DEBUG -#define Py_DEBUG -#endif - /* Compiler specific defines */ /* ------------------------------------------------------------------------*/ @@ -324,21 +319,21 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ This is relevant when using build-system generator (e.g CMake) where the linking is explicitly handled */ # if defined(Py_GIL_DISABLED) -# if defined(Py_DEBUG) +# if defined(_DEBUG) # pragma comment(lib,"python314t_d.lib") # elif defined(Py_LIMITED_API) # pragma comment(lib,"python3t.lib") # else # pragma comment(lib,"python314t.lib") -# endif /* Py_DEBUG */ +# endif /* _DEBUG */ # else /* Py_GIL_DISABLED */ -# if defined(Py_DEBUG) +# if defined(_DEBUG) # pragma comment(lib,"python314_d.lib") # elif defined(Py_LIMITED_API) # pragma comment(lib,"python3.lib") # else # pragma comment(lib,"python314.lib") -# endif /* Py_DEBUG */ +# endif /* _DEBUG */ # endif /* Py_GIL_DISABLED */ # endif /* _MSC_VER && !Py_NO_LINK_LIB */ # endif /* Py_BUILD_CORE */ @@ -381,6 +376,10 @@ Py_NO_ENABLE_SHARED to find out. Also support MS_NO_COREDLL for b/w compat */ # define ALIGNOF_MAX_ALIGN_T 8 #endif +#ifdef _DEBUG +# define Py_DEBUG +#endif + #ifdef MS_WIN32 diff --git a/PC/python_uwp.cpp b/PC/python_uwp.cpp index 8cdb8d722cdb9a..b9c408a580c999 100644 --- a/PC/python_uwp.cpp +++ b/PC/python_uwp.cpp @@ -19,13 +19,13 @@ #include #ifdef PYTHONW -#ifdef Py_DEBUG +#ifdef _DEBUG const wchar_t *PROGNAME = L"pythonw_d.exe"; #else const wchar_t *PROGNAME = L"pythonw.exe"; #endif #else -#ifdef Py_DEBUG +#ifdef _DEBUG const wchar_t *PROGNAME = L"python_d.exe"; #else const wchar_t *PROGNAME = L"python.exe"; diff --git a/PC/python_ver_rc.h b/PC/python_ver_rc.h index bb98144cd03f15..ee867fe41224c3 100644 --- a/PC/python_ver_rc.h +++ b/PC/python_ver_rc.h @@ -10,7 +10,7 @@ #define MS_WINDOWS #include "modsupport.h" #include "patchlevel.h" -#ifdef Py_DEBUG +#ifdef _DEBUG # define PYTHON_DEBUG_EXT "_d" #else # define PYTHON_DEBUG_EXT diff --git a/Python/dynload_win.c b/Python/dynload_win.c index de9b0a77817a63..6324063401e51f 100644 --- a/Python/dynload_win.c +++ b/Python/dynload_win.c @@ -108,7 +108,7 @@ static char *GetPythonImport (HINSTANCE hModule) char *pch; /* Don't claim that python3.dll is a Python DLL. */ -#ifdef Py_DEBUG +#ifdef _DEBUG if (strcmp(import_name, "python3_d.dll") == 0) { #else if (strcmp(import_name, "python3.dll") == 0) { @@ -120,7 +120,7 @@ static char *GetPythonImport (HINSTANCE hModule) /* Ensure python prefix is followed only by numbers to the end of the basename */ pch = import_name + 6; -#ifdef Py_DEBUG +#ifdef _DEBUG while (*pch && pch[0] != '_' && pch[1] != 'd' && pch[2] != '.') { #else while (*pch && *pch != '.') { @@ -300,7 +300,7 @@ dl_funcptr _PyImport_FindSharedFuncptrWindows(const char *prefix, char buffer[256]; PyOS_snprintf(buffer, sizeof(buffer), -#ifdef Py_DEBUG +#ifdef _DEBUG "python%d%d_d.dll", #else "python%d%d.dll", From 7b21d7d90bc7163ab9548a8d801a8f0a2d3a7212 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 23:07:18 +0800 Subject: [PATCH 19/43] Revert `_DEBUG` -> `Py_DEBUG` --- Include/internal/pycore_importdl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Include/internal/pycore_importdl.h b/Include/internal/pycore_importdl.h index 3ba9229cc21378..525a16f6b97274 100644 --- a/Include/internal/pycore_importdl.h +++ b/Include/internal/pycore_importdl.h @@ -107,7 +107,7 @@ extern int _PyImport_RunModInitFunc( #include typedef FARPROC dl_funcptr; -#ifdef Py_DEBUG +#ifdef _DEBUG # define PYD_DEBUG_SUFFIX "_d" #else # define PYD_DEBUG_SUFFIX "" From 1ee82303c7416a0b0909b71a1a43de47b5c7d002 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 23:09:11 +0800 Subject: [PATCH 20/43] Add underscore prefix to `d` on Windows --- Lib/sysconfig/__init__.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index e780b577c84870..9f411e377d06a3 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -408,6 +408,9 @@ def _init_non_posix(vars): # empty string. vars.update(_sysconfig.config_vars()) + # Add an underscore to the `d` flag. E.g, `td` -> `t_d`, `d` -> `_d`. + vars['Py_DEBUG'] = vars['Py_DEBUG'].replace('d', '_d') + vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) if hasattr(sys, 'dllhandle'): dllhandle = _winapi.GetModuleFileName(sys.dllhandle) From 084deac14b8808e522fca18e55c01f02002be509 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 23:40:33 +0800 Subject: [PATCH 21/43] Fix key name --- Lib/sysconfig/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 9f411e377d06a3..34e29be9f61621 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -409,7 +409,7 @@ def _init_non_posix(vars): vars.update(_sysconfig.config_vars()) # Add an underscore to the `d` flag. E.g, `td` -> `t_d`, `d` -> `_d`. - vars['Py_DEBUG'] = vars['Py_DEBUG'].replace('d', '_d') + vars['ABIFLAGS'] = vars['ABIFLAGS'].replace('d', '_d') vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) if hasattr(sys, 'dllhandle'): From af50632b02abcb1de18e91177fddaf6b570ce0c1 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Mon, 31 Mar 2025 23:46:49 +0800 Subject: [PATCH 22/43] Add comments for test for `d` flag in `ABIFLAGS` --- Lib/test/test_sysconfig.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 7679ae2a3e76de..7f3807712aad8d 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -625,6 +625,9 @@ def test_abiflags(self): self.assertEqual(abiflags, '') if support.Py_DEBUG: + # The 'd' flag should always be the last one. + # On Windows, the debug flag is used differently with a underscore prefix. + # For example, `python{X}.{Y}td` on Unix and ```python{X}.{Y}t_d.exe` on Windows. self.assertEndsWith(ABIFLAGS, 'd') else: self.assertNotIn('d', ABIFLAGS) From b397f406f3407a5f2cf6d0ea604a5d9fb07d6a16 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 1 Apr 2025 00:06:17 +0800 Subject: [PATCH 23/43] Fix failing test --- Lib/test/test_sysconfig.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 7f3807712aad8d..0909b6e8a02303 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -619,7 +619,8 @@ def test_abiflags(self): self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) if ABIFLAGS: - self.assertTrue(ABIFLAGS.isalpha(), ABIFLAGS) + self.assertLessEqual(ABIFLAGS.count('_'), 1) # example value on Windows: 't_d' + self.assertTrue(ABIFLAGS.replace('_', '').isalpha(), ABIFLAGS) if os.name == 'nt': self.assertEqual(abiflags, '') From 1a82cd1b979103178cd3a384d3e763b60c9b27a9 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 1 Apr 2025 00:08:15 +0800 Subject: [PATCH 24/43] Update tests --- Lib/test/test_sysconfig.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 0909b6e8a02303..fcb8c954659a03 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -618,17 +618,21 @@ def test_abiflags(self): self.assertIsInstance(abiflags, str) self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) - if ABIFLAGS: - self.assertLessEqual(ABIFLAGS.count('_'), 1) # example value on Windows: 't_d' - self.assertTrue(ABIFLAGS.replace('_', '').isalpha(), ABIFLAGS) if os.name == 'nt': self.assertEqual(abiflags, '') + # Example values: '', 't', 't_d', '_d' + self.assertLessEqual(ABIFLAGS.count('_'), 1) + else: + # Example values: '', 't', 'td', 'd' + self.assertNotIn('_', ABIFLAGS) + if ABIFLAGS: + self.assertTrue(ABIFLAGS.replace('_', '').isalpha(), ABIFLAGS) if support.Py_DEBUG: # The 'd' flag should always be the last one. # On Windows, the debug flag is used differently with a underscore prefix. - # For example, `python{X}.{Y}td` on Unix and ```python{X}.{Y}t_d.exe` on Windows. + # For example, `python{X}.{Y}td` on Unix and `python{X}.{Y}t_d.exe` on Windows. self.assertEndsWith(ABIFLAGS, 'd') else: self.assertNotIn('d', ABIFLAGS) From 518137beb3fe864fe86514dd810ab22c809526bc Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 4 Apr 2025 03:21:03 +0800 Subject: [PATCH 25/43] Add a test for `sysconfig.get_config_var('ABIFLAGS')` on Windows --- Lib/test/test_winapi.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Lib/test/test_winapi.py b/Lib/test/test_winapi.py index e64208330ad2f9..9fc1cf97b43406 100644 --- a/Lib/test/test_winapi.py +++ b/Lib/test/test_winapi.py @@ -3,6 +3,8 @@ import os import pathlib import re +import sys +import sysconfig import unittest from test.support import import_helper, os_helper @@ -156,3 +158,14 @@ def test_namedpipe(self): pipe2.write(b'testdata') pipe2.flush() self.assertEqual((b'testdata', 8), _winapi.PeekNamedPipe(pipe, 8)[:2]) + + def test_get_module_file_name(self): + dll_file_path = _winapi.GetModuleFileName(sys.dllhandle) + dll_file_name = os.path.basename(dll_file_path) + self.assertEqual( + dll_file_name, + "python{vi.major}{vi.minor}{abiflags}.dll".format( + vi=sys.version_info, + abiflags=sysconfig.get_config_var('ABIFLAGS'), + ), + ) From 486e2a880c043f17a6b9f38c93f3286d36b41ad8 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 4 Apr 2025 03:22:33 +0800 Subject: [PATCH 26/43] Rename test function --- Lib/test/test_winapi.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_winapi.py b/Lib/test/test_winapi.py index 9fc1cf97b43406..a69740cb696e72 100644 --- a/Lib/test/test_winapi.py +++ b/Lib/test/test_winapi.py @@ -127,6 +127,17 @@ def test_getshortpathname(self): # Should contain "PROGRA~" but we can't predict the number self.assertIsNotNone(re.match(r".\:\\PROGRA~\d", actual.upper()), actual) + def test_getmodulefilename(self): + dll_file_path = _winapi.GetModuleFileName(sys.dllhandle) + dll_file_name = os.path.basename(dll_file_path) + self.assertEqual( + dll_file_name, + "python{vi.major}{vi.minor}{abiflags}.dll".format( + vi=sys.version_info, + abiflags=sysconfig.get_config_var('ABIFLAGS'), + ), + ) + def test_namedpipe(self): pipe_name = rf"\\.\pipe\LOCAL\{os_helper.TESTFN}" @@ -158,14 +169,3 @@ def test_namedpipe(self): pipe2.write(b'testdata') pipe2.flush() self.assertEqual((b'testdata', 8), _winapi.PeekNamedPipe(pipe, 8)[:2]) - - def test_get_module_file_name(self): - dll_file_path = _winapi.GetModuleFileName(sys.dllhandle) - dll_file_name = os.path.basename(dll_file_path) - self.assertEqual( - dll_file_name, - "python{vi.major}{vi.minor}{abiflags}.dll".format( - vi=sys.version_info, - abiflags=sysconfig.get_config_var('ABIFLAGS'), - ), - ) From 3bccf1db8566a7960ca10bac0ebc7e52c80de7e8 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 4 Apr 2025 03:45:01 +0800 Subject: [PATCH 27/43] Move test location --- Lib/test/test_sysconfig.py | 11 +++++------ Lib/test/test_winapi.py | 11 ----------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 255a94e35814cf..12222f7f37165e 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -456,20 +456,19 @@ def test_library(self): library = sysconfig.get_config_var('LIBRARY') ldlibrary = sysconfig.get_config_var('LDLIBRARY') major, minor = sys.version_info[:2] - if sys.platform == 'win32': - self.assertTrue(library.startswith(f'python{major}{minor}')) - self.assertTrue(library.endswith('.dll')) + abiflags = sysconfig.get_config_var('ABIFLAGS') + if sys.platform.startswith('win'): + self.assertEqual(library, f'python{major}{minor}{abiflags}.dll') self.assertEqual(library, ldlibrary) elif is_apple_mobile: framework = sysconfig.get_config_var('PYTHONFRAMEWORK') self.assertEqual(ldlibrary, f"{framework}.framework/{framework}") else: - self.assertTrue(library.startswith(f'libpython{major}.{minor}')) - self.assertTrue(library.endswith('.a')) + self.assertEqual(library, f'libpython{major}.{minor}{abiflags}.a') if sys.platform == 'darwin' and sys._framework: self.skipTest('gh-110824: skip LDLIBRARY test for framework build') else: - self.assertTrue(ldlibrary.startswith(f'libpython{major}.{minor}')) + self.assertStartsWith(ldlibrary, f'libpython{major}.{minor}{abiflags}') @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX") @requires_subprocess() diff --git a/Lib/test/test_winapi.py b/Lib/test/test_winapi.py index a69740cb696e72..ba56277ad6a3f4 100644 --- a/Lib/test/test_winapi.py +++ b/Lib/test/test_winapi.py @@ -127,17 +127,6 @@ def test_getshortpathname(self): # Should contain "PROGRA~" but we can't predict the number self.assertIsNotNone(re.match(r".\:\\PROGRA~\d", actual.upper()), actual) - def test_getmodulefilename(self): - dll_file_path = _winapi.GetModuleFileName(sys.dllhandle) - dll_file_name = os.path.basename(dll_file_path) - self.assertEqual( - dll_file_name, - "python{vi.major}{vi.minor}{abiflags}.dll".format( - vi=sys.version_info, - abiflags=sysconfig.get_config_var('ABIFLAGS'), - ), - ) - def test_namedpipe(self): pipe_name = rf"\\.\pipe\LOCAL\{os_helper.TESTFN}" From 780f3408a93f9a603f3fb8034128ee968eb11ed2 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 4 Apr 2025 03:46:35 +0800 Subject: [PATCH 28/43] Move test location --- Lib/test/test_winapi.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/Lib/test/test_winapi.py b/Lib/test/test_winapi.py index ba56277ad6a3f4..e64208330ad2f9 100644 --- a/Lib/test/test_winapi.py +++ b/Lib/test/test_winapi.py @@ -3,8 +3,6 @@ import os import pathlib import re -import sys -import sysconfig import unittest from test.support import import_helper, os_helper From 98c26f9cdee724833acd136a632ff2e4e789dcf1 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 4 Apr 2025 04:04:56 +0800 Subject: [PATCH 29/43] Add a note for `test_abiflags` --- Lib/test/test_sysconfig.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 12222f7f37165e..3c0ec3fef32a20 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -611,6 +611,8 @@ def test_always_set_py_gil_disabled(self): self.assertEqual(Py_GIL_DISABLED, support.Py_GIL_DISABLED) def test_abiflags(self): + # XXX: If this test fails on some platforms, maintainers should add/update + # the definition of the ABIFLAGS variable and make this test pass. abiflags = sysconfig.get_config_var('abiflags') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') @@ -621,7 +623,7 @@ def test_abiflags(self): if os.name == 'nt': self.assertEqual(abiflags, '') # Example values: '', 't', 't_d', '_d' - self.assertLessEqual(ABIFLAGS.count('_'), 1) + self.assertTrue(ABIFLAGS.count('_d') == 1 or '_' not in ABIFLAGS, ABIFLAGS) else: # Example values: '', 't', 'td', 'd' self.assertNotIn('_', ABIFLAGS) From e236bc75fbfb13725553f228a62f10b0bf8a75ae Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 4 Apr 2025 04:35:54 +0800 Subject: [PATCH 30/43] Move definition of ABIFLAGS from C to Python --- Lib/sysconfig/__init__.py | 14 +++++++++----- Modules/_sysconfig.c | 17 ----------------- 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/Lib/sysconfig/__init__.py b/Lib/sysconfig/__init__.py index 34e29be9f61621..dad715eb087387 100644 --- a/Lib/sysconfig/__init__.py +++ b/Lib/sysconfig/__init__.py @@ -401,15 +401,19 @@ def _init_non_posix(vars): vars['BINLIBDEST'] = get_path('platstdlib') vars['INCLUDEPY'] = get_path('include') - # Add EXT_SUFFIX, SOABI, ABIFLAGS, Py_DEBUG, and Py_GIL_DISABLED + # Add EXT_SUFFIX, SOABI, Py_DEBUG, and Py_GIL_DISABLED + vars.update(_sysconfig.config_vars()) + # NOTE: ABIFLAGS is only an emulated value. It is not present during build # on Windows. sys.abiflags is absent on Windows and vars['abiflags'] # is already widely used to calculate paths, so it should remain an # empty string. - vars.update(_sysconfig.config_vars()) - - # Add an underscore to the `d` flag. E.g, `td` -> `t_d`, `d` -> `_d`. - vars['ABIFLAGS'] = vars['ABIFLAGS'].replace('d', '_d') + vars['ABIFLAGS'] = ''.join( + ( + 't' if vars['Py_GIL_DISABLED'] else '', + '_d' if vars['Py_DEBUG'] else '', + ), + ) vars['LIBDIR'] = _safe_realpath(os.path.join(get_config_var('installed_base'), 'libs')) if hasattr(sys, 'dllhandle'): diff --git a/Modules/_sysconfig.c b/Modules/_sysconfig.c index 728cb4b252f2e3..e2d141b5910b6d 100644 --- a/Modules/_sysconfig.c +++ b/Modules/_sysconfig.c @@ -55,23 +55,6 @@ _sysconfig_config_vars_impl(PyObject *module) Py_DECREF(config); return NULL; } - - // On Unix, the `ABIFLAGS` key is defined via a different logic. - // - // Emulate `sys.abiflags` value on Unix for Windows. ABIFLAGS here is only - // an emulated value. It is not present during build on Windows. - if (add_string_value(config, "ABIFLAGS", -# ifdef Py_GIL_DISABLED - "t" -# endif -# ifdef Py_DEBUG - "d" -# endif - "") - < 0) { - Py_DECREF(config); - return NULL; - } #endif #ifdef Py_GIL_DISABLED From 299cec6b3025b336bb5406a91a39e1459634c512 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 05:57:29 +0800 Subject: [PATCH 31/43] Update tests --- Lib/test/test_sysconfig.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 3c0ec3fef32a20..c460b56a00e35e 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -611,7 +611,7 @@ def test_always_set_py_gil_disabled(self): self.assertEqual(Py_GIL_DISABLED, support.Py_GIL_DISABLED) def test_abiflags(self): - # XXX: If this test fails on some platforms, maintainers should add/update + # If this test fails on some platforms, maintainers should add/update # the definition of the ABIFLAGS variable and make this test pass. abiflags = sysconfig.get_config_var('abiflags') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') @@ -620,10 +620,17 @@ def test_abiflags(self): self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) + # Check all flags are alphabetic if os.name == 'nt': self.assertEqual(abiflags, '') # Example values: '', 't', 't_d', '_d' - self.assertTrue(ABIFLAGS.count('_d') == 1 or '_' not in ABIFLAGS, ABIFLAGS) + # '_' can only exist if 'd' is present + if '_' in ABIFLAGS: + # '_' is followed by 'd' + self.assertTrue(ABIFLAGS.count('_d') == 1, ABIFLAGS) + self.assertTrue(ABIFLAGS.count('_') == 1, ABIFLAGS) + else: + self.assertNotIn('d', ABIFLAGS) else: # Example values: '', 't', 'td', 'd' self.assertNotIn('_', ABIFLAGS) From 21d2e738f8b4e7a19ce00bb9d706e14344547ad5 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 06:42:07 +0800 Subject: [PATCH 32/43] Split 't' flag to another test --- Lib/test/test_sysconfig.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index c460b56a00e35e..b8ba71b5cc4d5a 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -644,9 +644,16 @@ def test_abiflags(self): self.assertEndsWith(ABIFLAGS, 'd') else: self.assertNotIn('d', ABIFLAGS) + + def test_abi_thread(self): + abi_thread = sysconfig.get_config_var('abi_thread') + ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') + self.assertIsInstance(abi_thread, str) if support.Py_GIL_DISABLED: + self.assertEqual(abi_thread, 't') self.assertIn('t', ABIFLAGS) else: + self.assertEqual(abi_thread, '') self.assertNotIn('t', ABIFLAGS) @requires_subprocess() From d265a596ecc456f749383f6a3fbd65866c905588 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 12:00:04 +0800 Subject: [PATCH 33/43] Update tests --- Lib/test/test_sysconfig.py | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index b8ba71b5cc4d5a..ab46606ac2ec4c 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -611,8 +611,8 @@ def test_always_set_py_gil_disabled(self): self.assertEqual(Py_GIL_DISABLED, support.Py_GIL_DISABLED) def test_abiflags(self): - # If this test fails on some platforms, maintainers should add/update - # the definition of the ABIFLAGS variable and make this test pass. + # If this test fails on some platforms, maintainers should update the + # test to make it pass, rather than changing the definition of ABIFLAGS. abiflags = sysconfig.get_config_var('abiflags') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') @@ -621,21 +621,23 @@ def test_abiflags(self): self.assertIn(abiflags, ABIFLAGS) # Check all flags are alphabetic + valid_abiflags = ('', 't', 'd', 'td') + for flags in valid_abiflags: + self.assertTrue(len(flags) == len(set(flags)), flags) + if flags: + self.assertIn(flags.isalpha(), flags) if os.name == 'nt': self.assertEqual(abiflags, '') # Example values: '', 't', 't_d', '_d' # '_' can only exist if 'd' is present - if '_' in ABIFLAGS: - # '_' is followed by 'd' - self.assertTrue(ABIFLAGS.count('_d') == 1, ABIFLAGS) - self.assertTrue(ABIFLAGS.count('_') == 1, ABIFLAGS) - else: - self.assertNotIn('d', ABIFLAGS) + # '_' can only followed by 'd' + self.assertIn( + ABIFLAGS, + tuple(flag.replace('d', '_d') for flag in valid_abiflags), + ) else: # Example values: '', 't', 'td', 'd' - self.assertNotIn('_', ABIFLAGS) - if ABIFLAGS: - self.assertTrue(ABIFLAGS.replace('_', '').isalpha(), ABIFLAGS) + self.assertIn(ABIFLAGS, valid_abiflags) if support.Py_DEBUG: # The 'd' flag should always be the last one. From f3b857016cc396711514867d8af3e55eea7ca937 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 12:02:18 +0800 Subject: [PATCH 34/43] Update tests --- Lib/test/test_sysconfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index ab46606ac2ec4c..f79d5594fe7d7b 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -633,7 +633,7 @@ def test_abiflags(self): # '_' can only followed by 'd' self.assertIn( ABIFLAGS, - tuple(flag.replace('d', '_d') for flag in valid_abiflags), + tuple(flags.replace('d', '_d') for flags in valid_abiflags), ) else: # Example values: '', 't', 'td', 'd' From fe4ea953b0717a9cea856fd32c4a954670b79422 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 12:05:54 +0800 Subject: [PATCH 35/43] Update tests --- Lib/test/test_sysconfig.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index f79d5594fe7d7b..8b3d94bed93cd2 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -620,15 +620,14 @@ def test_abiflags(self): self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) - # Check all flags are alphabetic valid_abiflags = ('', 't', 'd', 'td') - for flags in valid_abiflags: + for flags in valid_abiflags: # senity check self.assertTrue(len(flags) == len(set(flags)), flags) if flags: self.assertIn(flags.isalpha(), flags) if os.name == 'nt': self.assertEqual(abiflags, '') - # Example values: '', 't', 't_d', '_d' + # Example values: '', '_d', 't', 't_d' # '_' can only exist if 'd' is present # '_' can only followed by 'd' self.assertIn( @@ -636,9 +635,11 @@ def test_abiflags(self): tuple(flags.replace('d', '_d') for flags in valid_abiflags), ) else: - # Example values: '', 't', 'td', 'd' + # Example values: '', 'd', 't', 'td' self.assertIn(ABIFLAGS, valid_abiflags) + def test_abi_debug(self): + ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') if support.Py_DEBUG: # The 'd' flag should always be the last one. # On Windows, the debug flag is used differently with a underscore prefix. From 64f096121edf54d8827ee701c3f0ec9630810f1a Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 23:24:41 +0800 Subject: [PATCH 36/43] Simplify tests --- Lib/test/test_sysconfig.py | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 8b3d94bed93cd2..e37b8dfcdf5944 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -592,12 +592,6 @@ def test_osx_ext_suffix(self): suffix = sysconfig.get_config_var('EXT_SUFFIX') self.assertTrue(suffix.endswith('-darwin.so'), suffix) - def test_always_set_abiflags(self): - self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) - self.assertIsInstance(sysconfig.get_config_var('ABIFLAGS'), str) - self.assertIn('abiflags', sysconfig.get_config_vars()) - self.assertIsInstance(sysconfig.get_config_var('abiflags'), str) - def test_always_set_py_debug(self): self.assertIn('Py_DEBUG', sysconfig.get_config_vars()) Py_DEBUG = sysconfig.get_config_var('Py_DEBUG') @@ -613,29 +607,23 @@ def test_always_set_py_gil_disabled(self): def test_abiflags(self): # If this test fails on some platforms, maintainers should update the # test to make it pass, rather than changing the definition of ABIFLAGS. + self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) + self.assertIn('abiflags', sysconfig.get_config_vars()) abiflags = sysconfig.get_config_var('abiflags') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') - self.assertIsInstance(abiflags, str) self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) valid_abiflags = ('', 't', 'd', 'td') - for flags in valid_abiflags: # senity check - self.assertTrue(len(flags) == len(set(flags)), flags) - if flags: - self.assertIn(flags.isalpha(), flags) if os.name == 'nt': self.assertEqual(abiflags, '') - # Example values: '', '_d', 't', 't_d' - # '_' can only exist if 'd' is present - # '_' can only followed by 'd' + # '_' can only exist if 'd' is present and can only followed by 'd' self.assertIn( ABIFLAGS, tuple(flags.replace('d', '_d') for flags in valid_abiflags), ) else: - # Example values: '', 'd', 't', 'td' self.assertIn(ABIFLAGS, valid_abiflags) def test_abi_debug(self): From 8b164547cccdde14e1ff784b0852abc3f27b8453 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 23:30:35 +0800 Subject: [PATCH 37/43] Simplify tests --- Lib/test/test_sysconfig.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index e37b8dfcdf5944..1843b35722a274 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -615,16 +615,15 @@ def test_abiflags(self): self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) - valid_abiflags = ('', 't', 'd', 'td') + if not sys.platform.startswith('win'): + valid_abiflags = ('', 't', 'd', 'td') + else: + # '_' can only exist if 'd' is present and can only followed by 'd' + valid_abiflags = ('', 't', '_d', 't_d') + if os.name == 'nt': self.assertEqual(abiflags, '') - # '_' can only exist if 'd' is present and can only followed by 'd' - self.assertIn( - ABIFLAGS, - tuple(flags.replace('d', '_d') for flags in valid_abiflags), - ) - else: - self.assertIn(ABIFLAGS, valid_abiflags) + self.assertIn(ABIFLAGS, valid_abiflags) def test_abi_debug(self): ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') From 1c807f0c92848d4da56f8d96d1e7578cb309a41a Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Tue, 8 Apr 2025 23:34:27 +0800 Subject: [PATCH 38/43] Update test comments --- Lib/test/test_sysconfig.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 1843b35722a274..bae1548caaccbc 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -607,8 +607,8 @@ def test_always_set_py_gil_disabled(self): def test_abiflags(self): # If this test fails on some platforms, maintainers should update the # test to make it pass, rather than changing the definition of ABIFLAGS. - self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) self.assertIn('abiflags', sysconfig.get_config_vars()) + self.assertIn('ABIFLAGS', sysconfig.get_config_vars()) abiflags = sysconfig.get_config_var('abiflags') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') self.assertIsInstance(abiflags, str) @@ -618,7 +618,9 @@ def test_abiflags(self): if not sys.platform.startswith('win'): valid_abiflags = ('', 't', 'd', 'td') else: - # '_' can only exist if 'd' is present and can only followed by 'd' + # '_' can only exist if 'd' is present and can only followed by 'd'. + # That is `ABIFLAGS.replace('d', '_d')` above. + # See test_abi_debug() for more details. valid_abiflags = ('', 't', '_d', 't_d') if os.name == 'nt': From 932386c6a3c554d6fd7cea778e6c53b80bca4118 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Thu, 10 Apr 2025 01:26:37 +0800 Subject: [PATCH 39/43] Simplify test comment --- Lib/test/test_sysconfig.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index bae1548caaccbc..bc52d01634e506 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -618,9 +618,7 @@ def test_abiflags(self): if not sys.platform.startswith('win'): valid_abiflags = ('', 't', 'd', 'td') else: - # '_' can only exist if 'd' is present and can only followed by 'd'. - # That is `ABIFLAGS.replace('d', '_d')` above. - # See test_abi_debug() for more details. + # These are mapped with `f.replace('d', '_d')` above. See test_abi_debug(). valid_abiflags = ('', 't', '_d', 't_d') if os.name == 'nt': From 23b6e6c77b3146362e4c7562d29ad7b04e70bb85 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Thu, 10 Apr 2025 01:50:45 +0800 Subject: [PATCH 40/43] Apply suggestions from code review --- Lib/test/test_sysconfig.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index bc52d01634e506..fdb28eddcd2491 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -614,15 +614,15 @@ def test_abiflags(self): self.assertIsInstance(abiflags, str) self.assertIsInstance(ABIFLAGS, str) self.assertIn(abiflags, ABIFLAGS) + if os.name == 'nt': + self.assertEqual(abiflags, '') if not sys.platform.startswith('win'): valid_abiflags = ('', 't', 'd', 'td') else: - # These are mapped with `f.replace('d', '_d')` above. See test_abi_debug(). + # Windows uses '_d' rather than 'd'; see also test_abi_debug below valid_abiflags = ('', 't', '_d', 't_d') - if os.name == 'nt': - self.assertEqual(abiflags, '') self.assertIn(ABIFLAGS, valid_abiflags) def test_abi_debug(self): From 75b6c51a74f678052ad3be567da578a162f884bc Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 11 Apr 2025 19:18:35 +0800 Subject: [PATCH 41/43] Make 'd' flag test more platform specific --- Lib/test/test_sysconfig.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index fdb28eddcd2491..2b3c80e1eb38c5 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -628,13 +628,16 @@ def test_abiflags(self): def test_abi_debug(self): ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') if support.Py_DEBUG: - # The 'd' flag should always be the last one. - # On Windows, the debug flag is used differently with a underscore prefix. - # For example, `python{X}.{Y}td` on Unix and `python{X}.{Y}t_d.exe` on Windows. - self.assertEndsWith(ABIFLAGS, 'd') + self.assertIn('d', ABIFLAGS) else: self.assertNotIn('d', ABIFLAGS) + # The 'd' flag should always be the last one on Windows. + # On Windows, the debug flag is used differently with a underscore prefix. + # For example, `python{X}.{Y}td` on Unix and `python{X}.{Y}t_d.exe` on Windows. + if support.Py_DEBUG and sys.platform.endswith('win'): + self.assertEndsWith(ABIFLAGS, '_d') + def test_abi_thread(self): abi_thread = sysconfig.get_config_var('abi_thread') ABIFLAGS = sysconfig.get_config_var('ABIFLAGS') From d55b3e6717553e7caf2c01a2664a5e2e93c80a4e Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 11 Apr 2025 19:21:26 +0800 Subject: [PATCH 42/43] Revert non-Windows test changes --- Lib/test/test_sysconfig.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 2b3c80e1eb38c5..2424f1fb310b5f 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -464,11 +464,12 @@ def test_library(self): framework = sysconfig.get_config_var('PYTHONFRAMEWORK') self.assertEqual(ldlibrary, f"{framework}.framework/{framework}") else: - self.assertEqual(library, f'libpython{major}.{minor}{abiflags}.a') + self.assertStartsWith(library, f'libpython{major}.{minor}') + self.assertEndsWith(library, '.a') if sys.platform == 'darwin' and sys._framework: self.skipTest('gh-110824: skip LDLIBRARY test for framework build') else: - self.assertStartsWith(ldlibrary, f'libpython{major}.{minor}{abiflags}') + self.assertStartsWith(ldlibrary, f'libpython{major}.{minor}') @unittest.skipUnless(sys.platform == "darwin", "test only relevant on MacOSX") @requires_subprocess() From a0840707ba6672ab629553b80ea540048ad64574 Mon Sep 17 00:00:00 2001 From: Xuehai Pan Date: Fri, 11 Apr 2025 19:41:36 +0800 Subject: [PATCH 43/43] Fix Windows platform detection --- Lib/test/test_sysconfig.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_sysconfig.py b/Lib/test/test_sysconfig.py index 2424f1fb310b5f..53e55383bf9c72 100644 --- a/Lib/test/test_sysconfig.py +++ b/Lib/test/test_sysconfig.py @@ -636,7 +636,7 @@ def test_abi_debug(self): # The 'd' flag should always be the last one on Windows. # On Windows, the debug flag is used differently with a underscore prefix. # For example, `python{X}.{Y}td` on Unix and `python{X}.{Y}t_d.exe` on Windows. - if support.Py_DEBUG and sys.platform.endswith('win'): + if support.Py_DEBUG and sys.platform.startswith('win'): self.assertEndsWith(ABIFLAGS, '_d') def test_abi_thread(self):