Skip to content

test_importlib.test_windows: vendored get_platform() misdetects clang-cl builds as win32, failing test_tagged_suffix #154200

Description

@SynaptSea

Bug description:

test_tagged_suffix in Lib/test/test_importlib/test_windows.py fails on Windows CPython built with clang-cl (build.bat "/p:PlatformToolset=ClangCL", documented in PCbuild/readme.txt; see the reproduction note below about VSCMD_ARG_TGT_ARCH). The root cause is the same sys.version-truncation misdetection that gh-145410 fixed for sysconfig.get_platform() in March 2026 (by moving the check into the _sysconfig.get_platform() C accelerator, GH-146145) — but this test computes its expected suffix with a vendored "Port of distutils.util.get_platform()" that still carries the pre-fix logic: it sniffs sys.version.lower() for 'amd64', misses on the truncated clang banner, and falls through to return sys.platform'win32'.

$ python -m unittest -v test.test_importlib.test_windows -k tagged
test_tagged_suffix (test.test_importlib.test_windows.Frozen_WindowsExtensionSuffixTests.test_tagged_suffix) ... FAIL
test_tagged_suffix (test.test_importlib.test_windows.Source_WindowsExtensionSuffixTests.test_tagged_suffix) ... FAIL

======================================================================
FAIL: test_tagged_suffix (test.test_importlib.test_windows.Frozen_WindowsExtensionSuffixTests.test_tagged_suffix)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "D:\Python\3.16t\Lib\test\test_importlib\test_windows.py", line 154, in test_tagged_suffix
    self.assertIn(expected_tag, suffixes)
    ~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: '.cp316t-win32.pyd' not found in ['.cp316t-win_amd64.pyd', '.pyd']

(the Source_ variant fails identically)

Reproduction note: the vendored function checks VSCMD_ARG_TGT_ARCH first, so the failure only manifests outside a VS developer prompt (or with a non-matching target arch); inside vcvars64 the env var masks it and the test passes. Run the repro from a plain shell.

The interpreter itself is right — the test's expectation is wrong:

>>> import sys, sysconfig
>>> sys.version
'3.16.0a0 free-threading build (heads/ft-opt-dirty:2f032556f42, Jul 16 2026, 11:20:12) [Clang 22.1.8 (https://github.com/llvm/llvm-project ca7933e47d3a3451d81e72ac174d'
>>> sysconfig.get_platform()   # fixed by gh-145410
'win-amd64'
>>> from test.test_importlib.test_windows import get_platform; get_platform()   # vendored copy, pre-fix logic
'win32'
>>> import importlib.machinery; importlib.machinery.EXTENSION_SUFFIXES
['.cp316t-win_amd64.pyd', '.pyd']

EXTENSION_SUFFIXES is built from PYD_PLATFORM_TAG in PC/pyconfig.h and is correct; only the test's vendored helper is stale.

Why the banner sniff misses on clang-cl builds: PC/pyconfig.h#L161 does put "] 64 bit (AMD64) with MSC v.NNNN CRT]" into the clang compiler banner — but Python/getversion.c#L18-L20 caps the compiler segment of sys.version at %.80s, and official LLVM Windows binaries have an 86-char __clang_version__ (version + URL + full 40-char commit hash — verified against the llvmorg-22.1.8 tag commit ca7933e4…). With the 7-char "[Clang " prefix the 80-char cut always lands inside the hash, so the tail carrying (AMD64) is truncated away — note the banner above ends 28 characters into the commit hash, inside a never-closed parenthesis, with no (AMD64) and no closing bracket. An MSVC banner ([MSC v.19NN 64 bit (AMD64)], ~27 chars) is never truncated, which is why this is clang-specific.

Prior art: the same assertion tripped on an early free-threaded Windows buildbot (gh-110359, 2023: '_d.cp313-win32.pyd' not found in ['_d.cp313t-win_amd64.pyd', '_d.pyd']). That report's win32 came from the builder's VS target-arch environment rather than from banner truncation — an MSVC compiler segment is far too short to truncate — but it is the same expected-tag computation going wrong. Only the abi-flag half was addressed there (gh-109740; GH-110422 for gh-110119); the vendored platform sniff was left untouched, and it is what now bites clang-cl builds. Free-threading isn't part of the mechanism either — only the abi_flags term of the expected tag depends on it, so a non-FT clang-cl build should fail identically with .cp316-win32.pyd vs .cp316-win_amd64.pyd (I've only run free-threaded builds myself).

Suggested fix (deferring to the maintainers): replace the get_platform() call at L146 with sysconfig.get_platform() and delete the vendored function (that call is its only consumer). This does not make the test circular: SYSCONFIG_PLATFORM in Modules/_sysconfig.c and PYD_PLATFORM_TAG in PC/pyconfig.h are independent definitions in separate files, so the test still cross-checks two separate code paths. I'm happy to submit a PR — the change is small and test-only.

Environment / build: built from 2f032556f42 = local branch ft-opt merged with CPython main @ f62050d (2026-07-16), per PCbuild with build.bat -p x64 --disable-gil --pgo --tail-call-interp "/p:PlatformToolset=ClangCL", LLVM 22.1.8 official Windows release, Windows 11 x64; also reproduced on an earlier (June 2026) clang-cl build. All cited code verified unchanged on main as of 2026-07-19; permalinks sha-pinned to 16d0c89. My branch carries only build-system tuning (PCbuild props/vcxproj plus a zlib-ng header) and build-regenerated files (hence the -dirty banner); Lib/test/test_importlib/test_windows.py, Python/getversion.c, and PC/pyconfig.h are unmodified from upstream.

clang-cl is PY_SUPPORT_TIER 0, but PCbuild documents the toolset and it is actively kept working (gh-77532; e.g. gh-146210 in 2026, gh-131278/gh-130090/gh-131035 in 2025) — and the failing logic is a test bug, not a platform gap.

The same 80-char banner truncation also breaks ctypes.util.find_msvcrt()'s "MSC v." sniff, causing a test_ctypes.test_errno failure; filed separately as gh-154199.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Windows

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    OS-windowstestsTests in the Lib/test dirtype-bugAn unexpected behavior, bug, or error

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions