summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Snow <ericsnowcurrently@gmail.com>2022-11-08 16:58:11 (GMT)
committerGitHub <noreply@github.com>2022-11-08 16:58:11 (GMT)
commitd45cc80452b11d5ffc5c9721f74a3e3df8ecad8b (patch)
treea68aceaa899e2d1404b4f5d8d747bb7a3023ce7b
parent4d5fcca273b24a5566f1507758e5aae60cdf8a98 (diff)
downloadcpython-d45cc80452b11d5ffc5c9721f74a3e3df8ecad8b.zip
cpython-d45cc80452b11d5ffc5c9721f74a3e3df8ecad8b.tar.gz
cpython-d45cc80452b11d5ffc5c9721f74a3e3df8ecad8b.tar.bz2
gh-98627: Add the _testsinglephase Module (gh-99039)
This makes it more clear that a given test is definitely testing against a single-phase init (legacy) extension module. The new module is a companion to _testmultiphase. https://github.com/python/cpython/issues/98627
-rw-r--r--Lib/test/test_importlib/extension/test_case_sensitivity.py2
-rw-r--r--Lib/test/test_importlib/extension/test_loader.py117
-rw-r--r--Lib/test/test_importlib/util.py2
-rw-r--r--Modules/Setup1
-rw-r--r--Modules/Setup.stdlib.in1
-rw-r--r--Modules/_testsinglephase.c78
-rw-r--r--PCbuild/_testsinglephase.vcxproj115
-rw-r--r--PCbuild/_testsinglephase.vcxproj.filters23
-rw-r--r--PCbuild/pcbuild.proj2
-rw-r--r--PCbuild/pcbuild.sln32
-rw-r--r--PCbuild/readme.txt1
-rw-r--r--Tools/build/generate_stdlib_module_names.py1
-rw-r--r--Tools/msi/test/test_files.wxs2
13 files changed, 356 insertions, 21 deletions
diff --git a/Lib/test/test_importlib/extension/test_case_sensitivity.py b/Lib/test/test_importlib/extension/test_case_sensitivity.py
index 366e565..0bb74ff 100644
--- a/Lib/test/test_importlib/extension/test_case_sensitivity.py
+++ b/Lib/test/test_importlib/extension/test_case_sensitivity.py
@@ -8,7 +8,7 @@ importlib = util.import_importlib('importlib')
machinery = util.import_importlib('importlib.machinery')
-@unittest.skipIf(util.EXTENSIONS.filename is None, '_testcapi not available')
+@unittest.skipIf(util.EXTENSIONS.filename is None, f'{util.EXTENSIONS.name} not available')
@util.case_insensitive_tests
class ExtensionModuleCaseSensitivityTest(util.CASEOKTestBase):
diff --git a/Lib/test/test_importlib/extension/test_loader.py b/Lib/test/test_importlib/extension/test_loader.py
index 8570c6b..d69192b 100644
--- a/Lib/test/test_importlib/extension/test_loader.py
+++ b/Lib/test/test_importlib/extension/test_loader.py
@@ -13,9 +13,9 @@ import importlib
from test.support.script_helper import assert_python_failure
-class LoaderTests(abc.LoaderTests):
+class LoaderTests:
- """Test load_module() for extension modules."""
+ """Test ExtensionFileLoader."""
def setUp(self):
if not self.machinery.EXTENSION_SUFFIXES:
@@ -32,15 +32,6 @@ class LoaderTests(abc.LoaderTests):
warnings.simplefilter("ignore", DeprecationWarning)
return self.loader.load_module(fullname)
- def test_load_module_API(self):
- # Test the default argument for load_module().
- with warnings.catch_warnings():
- warnings.simplefilter("ignore", DeprecationWarning)
- self.loader.load_module()
- self.loader.load_module(None)
- with self.assertRaises(ImportError):
- self.load_module('XXX')
-
def test_equality(self):
other = self.machinery.ExtensionFileLoader(util.EXTENSIONS.name,
util.EXTENSIONS.file_path)
@@ -51,6 +42,15 @@ class LoaderTests(abc.LoaderTests):
util.EXTENSIONS.file_path)
self.assertNotEqual(self.loader, other)
+ def test_load_module_API(self):
+ # Test the default argument for load_module().
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ self.loader.load_module()
+ self.loader.load_module(None)
+ with self.assertRaises(ImportError):
+ self.load_module('XXX')
+
def test_module(self):
with util.uncache(util.EXTENSIONS.name):
module = self.load_module(util.EXTENSIONS.name)
@@ -68,12 +68,6 @@ class LoaderTests(abc.LoaderTests):
# No extension module in a package available for testing.
test_lacking_parent = None
- def test_module_reuse(self):
- with util.uncache(util.EXTENSIONS.name):
- module1 = self.load_module(util.EXTENSIONS.name)
- module2 = self.load_module(util.EXTENSIONS.name)
- self.assertIs(module1, module2)
-
# No easy way to trigger a failure after a successful import.
test_state_after_failure = None
@@ -83,6 +77,12 @@ class LoaderTests(abc.LoaderTests):
self.load_module(name)
self.assertEqual(cm.exception.name, name)
+ def test_module_reuse(self):
+ with util.uncache(util.EXTENSIONS.name):
+ module1 = self.load_module(util.EXTENSIONS.name)
+ module2 = self.load_module(util.EXTENSIONS.name)
+ self.assertIs(module1, module2)
+
def test_is_package(self):
self.assertFalse(self.loader.is_package(util.EXTENSIONS.name))
for suffix in self.machinery.EXTENSION_SUFFIXES:
@@ -90,10 +90,93 @@ class LoaderTests(abc.LoaderTests):
loader = self.machinery.ExtensionFileLoader('pkg', path)
self.assertTrue(loader.is_package('pkg'))
+
(Frozen_LoaderTests,
Source_LoaderTests
) = util.test_both(LoaderTests, machinery=machinery)
+
+class SinglePhaseExtensionModuleTests(abc.LoaderTests):
+ # Test loading extension modules without multi-phase initialization.
+
+ def setUp(self):
+ if not self.machinery.EXTENSION_SUFFIXES:
+ raise unittest.SkipTest("Requires dynamic loading support.")
+ self.name = '_testsinglephase'
+ if self.name in sys.builtin_module_names:
+ raise unittest.SkipTest(
+ f"{self.name} is a builtin module"
+ )
+ finder = self.machinery.FileFinder(None)
+ self.spec = importlib.util.find_spec(self.name)
+ assert self.spec
+ self.loader = self.machinery.ExtensionFileLoader(
+ self.name, self.spec.origin)
+
+ def load_module(self):
+ with warnings.catch_warnings():
+ warnings.simplefilter("ignore", DeprecationWarning)
+ return self.loader.load_module(self.name)
+
+ def load_module_by_name(self, fullname):
+ # Load a module from the test extension by name.
+ origin = self.spec.origin
+ loader = self.machinery.ExtensionFileLoader(fullname, origin)
+ spec = importlib.util.spec_from_loader(fullname, loader)
+ module = importlib.util.module_from_spec(spec)
+ loader.exec_module(module)
+ return module
+
+ def test_module(self):
+ # Test loading an extension module.
+ with util.uncache(self.name):
+ module = self.load_module()
+ for attr, value in [('__name__', self.name),
+ ('__file__', self.spec.origin),
+ ('__package__', '')]:
+ self.assertEqual(getattr(module, attr), value)
+ with self.assertRaises(AttributeError):
+ module.__path__
+ self.assertIs(module, sys.modules[self.name])
+ self.assertIsInstance(module.__loader__,
+ self.machinery.ExtensionFileLoader)
+
+ # No extension module as __init__ available for testing.
+ test_package = None
+
+ # No extension module in a package available for testing.
+ test_lacking_parent = None
+
+ # No easy way to trigger a failure after a successful import.
+ test_state_after_failure = None
+
+ def test_unloadable(self):
+ name = 'asdfjkl;'
+ with self.assertRaises(ImportError) as cm:
+ self.load_module_by_name(name)
+ self.assertEqual(cm.exception.name, name)
+
+ def test_unloadable_nonascii(self):
+ # Test behavior with nonexistent module with non-ASCII name.
+ name = 'fo\xf3'
+ with self.assertRaises(ImportError) as cm:
+ self.load_module_by_name(name)
+ self.assertEqual(cm.exception.name, name)
+
+ # It may make sense to add the equivalent to
+ # the following MultiPhaseExtensionModuleTests tests:
+ #
+ # * test_nonmodule
+ # * test_nonmodule_with_methods
+ # * test_bad_modules
+ # * test_nonascii
+
+
+(Frozen_SinglePhaseExtensionModuleTests,
+ Source_SinglePhaseExtensionModuleTests
+ ) = util.test_both(SinglePhaseExtensionModuleTests, machinery=machinery)
+
+
class MultiPhaseExtensionModuleTests(abc.LoaderTests):
# Test loading extension modules with multi-phase initialization (PEP 489).
diff --git a/Lib/test/test_importlib/util.py b/Lib/test/test_importlib/util.py
index 0b6dcc5..9032fd1 100644
--- a/Lib/test/test_importlib/util.py
+++ b/Lib/test/test_importlib/util.py
@@ -27,7 +27,7 @@ EXTENSIONS.path = None
EXTENSIONS.ext = None
EXTENSIONS.filename = None
EXTENSIONS.file_path = None
-EXTENSIONS.name = '_testcapi'
+EXTENSIONS.name = '_testsinglephase'
def _extension_details():
global EXTENSIONS
diff --git a/Modules/Setup b/Modules/Setup
index 8fe7951..e3a8297 100644
--- a/Modules/Setup
+++ b/Modules/Setup
@@ -291,6 +291,7 @@ PYTHONPATH=$(COREPYTHONPATH)
#_testcapi _testcapimodule.c
#_testimportmultiple _testimportmultiple.c
#_testmultiphase _testmultiphase.c
+#_testsinglephase _testsinglephase.c
# ---
# Uncommenting the following line tells makesetup that all following modules
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index ac8959e..74d2222 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -175,6 +175,7 @@
*shared*
@MODULE__TESTIMPORTMULTIPLE_TRUE@_testimportmultiple _testimportmultiple.c
@MODULE__TESTMULTIPHASE_TRUE@_testmultiphase _testmultiphase.c
+@MODULE__TESTMULTIPHASE_TRUE@_testsinglephase _testsinglephase.c
@MODULE__CTYPES_TEST_TRUE@_ctypes_test _ctypes/_ctypes_test.c
# Limited API template modules; must be built as shared modules.
diff --git a/Modules/_testsinglephase.c b/Modules/_testsinglephase.c
new file mode 100644
index 0000000..3bfe159
--- /dev/null
+++ b/Modules/_testsinglephase.c
@@ -0,0 +1,78 @@
+
+/* Testing module for single-phase initialization of extension modules
+ */
+#ifndef Py_BUILD_CORE_BUILTIN
+# define Py_BUILD_CORE_MODULE 1
+#endif
+
+#include "Python.h"
+#include "pycore_namespace.h" // _PyNamespace_New()
+
+
+/* Function of two integers returning integer */
+
+PyDoc_STRVAR(testexport_foo_doc,
+"foo(i,j)\n\
+\n\
+Return the sum of i and j.");
+
+static PyObject *
+testexport_foo(PyObject *self, PyObject *args)
+{
+ long i, j;
+ long res;
+ if (!PyArg_ParseTuple(args, "ll:foo", &i, &j))
+ return NULL;
+ res = i + j;
+ return PyLong_FromLong(res);
+}
+
+
+static PyMethodDef TestMethods[] = {
+ {"foo", testexport_foo, METH_VARARGS,
+ testexport_foo_doc},
+ {NULL, NULL} /* sentinel */
+};
+
+
+static struct PyModuleDef _testsinglephase = {
+ PyModuleDef_HEAD_INIT,
+ .m_name = "_testsinglephase",
+ .m_doc = PyDoc_STR("Test module _testsinglephase (main)"),
+ .m_size = -1, // no module state
+ .m_methods = TestMethods,
+};
+
+
+PyMODINIT_FUNC
+PyInit__testsinglephase(void)
+{
+ PyObject *module = PyModule_Create(&_testsinglephase);
+ if (module == NULL) {
+ return NULL;
+ }
+
+ /* Add an exception type */
+ PyObject *temp = PyErr_NewException("_testsinglephase.error", NULL, NULL);
+ if (temp == NULL) {
+ goto error;
+ }
+ if (PyModule_AddObject(module, "error", temp) != 0) {
+ Py_DECREF(temp);
+ goto error;
+ }
+
+ if (PyModule_AddIntConstant(module, "int_const", 1969) != 0) {
+ goto error;
+ }
+
+ if (PyModule_AddStringConstant(module, "str_const", "something different") != 0) {
+ goto error;
+ }
+
+ return module;
+
+error:
+ Py_DECREF(module);
+ return NULL;
+}
diff --git a/PCbuild/_testsinglephase.vcxproj b/PCbuild/_testsinglephase.vcxproj
new file mode 100644
index 0000000..fb4bcd9
--- /dev/null
+++ b/PCbuild/_testsinglephase.vcxproj
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug|ARM">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|ARM64">
+ <Configuration>Debug</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|x64">
+ <Configuration>Debug</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGInstrument|ARM">
+ <Configuration>PGInstrument</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGInstrument|ARM64">
+ <Configuration>PGInstrument</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGInstrument|Win32">
+ <Configuration>PGInstrument</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGInstrument|x64">
+ <Configuration>PGInstrument</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGUpdate|ARM">
+ <Configuration>PGUpdate</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGUpdate|ARM64">
+ <Configuration>PGUpdate</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGUpdate|Win32">
+ <Configuration>PGUpdate</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="PGUpdate|x64">
+ <Configuration>PGUpdate</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM">
+ <Configuration>Release</Configuration>
+ <Platform>ARM</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|ARM64">
+ <Configuration>Release</Configuration>
+ <Platform>ARM64</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|x64">
+ <Configuration>Release</Configuration>
+ <Platform>x64</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{2097F1C1-597C-4167-93E3-656A7D6339B2}</ProjectGuid>
+ <Keyword>Win32Proj</Keyword>
+ <RootNamespace>_testsinglephase</RootNamespace>
+ <SupportPGO>false</SupportPGO>
+ </PropertyGroup>
+ <Import Project="python.props" />
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Label="Configuration">
+ <ConfigurationType>DynamicLibrary</ConfigurationType>
+ <CharacterSet>NotSet</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <PropertyGroup>
+ <TargetExt>.pyd</TargetExt>
+ </PropertyGroup>
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="pyproject.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <ItemDefinitionGroup>
+ <ClCompile>
+ <PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ </ClCompile>
+ <Link>
+ <SubSystem>Console</SubSystem>
+ </Link>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="..\Modules\_testsinglephase.c" />
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="pythoncore.vcxproj">
+ <Project>{cf7ac3d1-e2df-41d2-bea6-1e2556cdea26}</Project>
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ </ProjectReference>
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project>
diff --git a/PCbuild/_testsinglephase.vcxproj.filters b/PCbuild/_testsinglephase.vcxproj.filters
new file mode 100644
index 0000000..2a0e0ef
--- /dev/null
+++ b/PCbuild/_testsinglephase.vcxproj.filters
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Resource Files">
+ <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+ <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="..\Modules\_testsinglephase.c">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ResourceCompile Include="..\PC\python_nt.rc">
+ <Filter>Resource Files</Filter>
+ </ResourceCompile>
+ </ItemGroup>
+</Project>
diff --git a/PCbuild/pcbuild.proj b/PCbuild/pcbuild.proj
index d9e4d98..e13a0d4 100644
--- a/PCbuild/pcbuild.proj
+++ b/PCbuild/pcbuild.proj
@@ -77,7 +77,7 @@
<ExtensionModules Include="@(ExternalModules->'%(Identity)')" Condition="$(IncludeExternals)" />
<Projects Include="@(ExtensionModules->'%(Identity).vcxproj')" Condition="$(IncludeExtensions)" />
<!-- Test modules -->
- <TestModules Include="_ctypes_test;_testbuffer;_testcapi;_testinternalcapi;_testembed;_testimportmultiple;_testmultiphase;_testconsole" />
+ <TestModules Include="_ctypes_test;_testbuffer;_testcapi;_testinternalcapi;_testembed;_testimportmultiple;_testmultiphase;_testsinglephase;_testconsole" />
<TestModules Include="xxlimited" Condition="'$(Configuration)' == 'Release'" />
<TestModules Include="xxlimited_35" Condition="'$(Configuration)' == 'Release'" />
<Projects Include="@(TestModules->'%(Identity).vcxproj')" Condition="$(IncludeTests)">
diff --git a/PCbuild/pcbuild.sln b/PCbuild/pcbuild.sln
index 9f374ab..d8fc00c 100644
--- a/PCbuild/pcbuild.sln
+++ b/PCbuild/pcbuild.sln
@@ -86,6 +86,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testembed", "_testembed.vc
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testmultiphase", "_testmultiphase.vcxproj", "{16BFE6F0-22EF-40B5-B831-7E937119EF10}"
EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testsinglephase", "_testsinglephase.vcxproj", "{2097F1C1-597C-4167-93E3-656A7D6339B2}"
+EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pyshellext", "pyshellext.vcxproj", "{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "_testconsole", "_testconsole.vcxproj", "{B244E787-C445-441C-BDF4-5A4F1A3A1E51}"
@@ -1168,6 +1170,36 @@ Global
{16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|Win32.Build.0 = Release|Win32
{16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|x64.ActiveCfg = Release|x64
{16BFE6F0-22EF-40B5-B831-7E937119EF10}.Release|x64.Build.0 = Release|x64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|ARM.ActiveCfg = Debug|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|ARM.Build.0 = Debug|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|ARM64.ActiveCfg = Debug|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|ARM64.Build.0 = Debug|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|Win32.ActiveCfg = Debug|Win32
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|Win32.Build.0 = Debug|Win32
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|x64.ActiveCfg = Debug|x64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Debug|x64.Build.0 = Debug|x64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGInstrument|ARM.ActiveCfg = PGInstrument|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGInstrument|ARM.Build.0 = PGInstrument|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGInstrument|ARM64.ActiveCfg = PGInstrument|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGInstrument|ARM64.Build.0 = PGInstrument|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGInstrument|Win32.ActiveCfg = Release|Win32
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGInstrument|x64.ActiveCfg = Release|x64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|ARM.ActiveCfg = PGUpdate|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|ARM.Build.0 = PGUpdate|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|ARM64.ActiveCfg = PGUpdate|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|ARM64.Build.0 = PGUpdate|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|Win32.ActiveCfg = Release|Win32
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|Win32.Build.0 = Release|Win32
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|x64.ActiveCfg = Release|x64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.PGUpdate|x64.Build.0 = Release|x64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|ARM.ActiveCfg = Release|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|ARM.Build.0 = Release|ARM
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|ARM64.ActiveCfg = Release|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|ARM64.Build.0 = Release|ARM64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|Win32.ActiveCfg = Release|Win32
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|Win32.Build.0 = Release|Win32
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|x64.ActiveCfg = Release|x64
+ {2097F1C1-597C-4167-93E3-656A7D6339B2}.Release|x64.Build.0 = Release|x64
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Debug|ARM.ActiveCfg = Debug|ARM
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Debug|ARM.Build.0 = Debug|ARM
{0F6EE4A4-C75F-4578-B4B3-2D64F4B9B782}.Debug|ARM64.ActiveCfg = Debug|ARM64
diff --git a/PCbuild/readme.txt b/PCbuild/readme.txt
index 5ba3e39..898d38e 100644
--- a/PCbuild/readme.txt
+++ b/PCbuild/readme.txt
@@ -147,6 +147,7 @@ _testcapi
_testconsole
_testimportmultiple
_testmultiphase
+_testsinglephase
_tkinter
pyexpat
select
diff --git a/Tools/build/generate_stdlib_module_names.py b/Tools/build/generate_stdlib_module_names.py
index 467a1f9..4534c3e 100644
--- a/Tools/build/generate_stdlib_module_names.py
+++ b/Tools/build/generate_stdlib_module_names.py
@@ -33,6 +33,7 @@ IGNORE = {
'_testimportmultiple',
'_testinternalcapi',
'_testmultiphase',
+ '_testsinglephase',
'_xxsubinterpreters',
'_xxtestfuzz',
'idlelib.idle_test',
diff --git a/Tools/msi/test/test_files.wxs b/Tools/msi/test/test_files.wxs
index 9127ce8..b5f68fa 100644
--- a/Tools/msi/test/test_files.wxs
+++ b/Tools/msi/test/test_files.wxs
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
- <?define exts=_testcapi;_ctypes_test;_testbuffer;_testimportmultiple;_testmultiphase;_testconsole;_testinternalcapi ?>
+ <?define exts=_testcapi;_ctypes_test;_testbuffer;_testimportmultiple;_testmultiphase;_testsinglephase;_testconsole;_testinternalcapi ?>
<Fragment>
<ComponentGroup Id="test_extensions">
<?foreach ext in $(var.exts)?>