diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index f348c9a5bbb31c..e9fc4cca229a03 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -3525,17 +3525,12 @@ def check_immutable_type(testcase, type):
def built_with_c_assertions():
"""Check if Python was built with C assertions (assert())."""
-
- if MS_WINDOWS:
- # On Windows, rely on the Py_DEBUG macro to check for assertions
+ try:
+ import _testlimitedcapi
+ except ImportError:
return Py_DEBUG
-
- # Check if the NDEBUG macro is defined in C compiler flags
- PY_CFLAGS = (sysconfig.get_config_var('PY_CFLAGS') or '')
- if '-DNDEBUG' in PY_CFLAGS:
- return False
-
- return True
+ else:
+ return bool(_testlimitedcapi._py_getbuiltwithassert())
def inject_memory_error(start=0, stop=0):
diff --git a/Lib/test/test_capi/test_build.py b/Lib/test/test_capi/test_build.py
new file mode 100644
index 00000000000000..8319ad1ec77da8
--- /dev/null
+++ b/Lib/test/test_capi/test_build.py
@@ -0,0 +1,39 @@
+import sys
+import unittest
+from test.support import import_helper
+
+_testlimitedcapi = import_helper.import_module('_testlimitedcapi')
+
+
+class CAPITest(unittest.TestCase):
+ # Test Py_GetVersion()
+ def test_getversion(self):
+ self.assertEqual(_testlimitedcapi.py_getversion(), sys.version)
+
+ # Test Py_GetPlatform()
+ def test_getplatform(self):
+ self.assertEqual(_testlimitedcapi.py_getplatform(), sys.platform)
+
+ # Test Py_GetCopyright()
+ def test_getcopyright(self):
+ self.assertEqual(_testlimitedcapi.py_getcopyright(), sys.copyright)
+
+ # Test Py_GetCompiler()
+ def test_getcompiler(self):
+ compiler = _testlimitedcapi.py_getcompiler()
+ self.assertIsInstance(compiler, str)
+ self.assertNotEqual(compiler, '')
+
+ # Test Py_GetBuildInfo()
+ def test_getbuildinfo(self):
+ buildinfo = _testlimitedcapi.py_getbuildinfo()
+ self.assertIsInstance(buildinfo, str)
+ self.assertNotEqual(buildinfo, '')
+
+ # Test internal _Py_GetBuiltWithAssert()
+ def test__getbuiltwithassert(self):
+ self.assertIn(_testlimitedcapi._py_getbuiltwithassert(), (0, 1))
+
+
+if __name__ == "__main__":
+ unittest.main()
diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
index a8c7e883bd4dd8..b83e0c371db33d 100644
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -838,6 +838,10 @@ def test_linked_to_musl(self):
for v in linked:
self.assertIsInstance(v, int)
+ def test_built_with_c_assertions(self):
+ # Check that calling the function doesn't raise an exception
+ result = support.built_with_c_assertions()
+ self.assertIsInstance(result, bool)
# XXX -follows a list of untested API
# make_legacy_pyc
diff --git a/Modules/Setup.stdlib.in b/Modules/Setup.stdlib.in
index 0ca1d90ac4f30b..dd9f38e59f7a3f 100644
--- a/Modules/Setup.stdlib.in
+++ b/Modules/Setup.stdlib.in
@@ -174,7 +174,7 @@
@MODULE__TESTBUFFER_TRUE@_testbuffer _testbuffer.c
@MODULE__TESTINTERNALCAPI_TRUE@_testinternalcapi _testinternalcapi.c _testinternalcapi/test_lock.c _testinternalcapi/pytime.c _testinternalcapi/set.c _testinternalcapi/test_critical_sections.c _testinternalcapi/complex.c _testinternalcapi/interpreter.c _testinternalcapi/tokenizer.c _testinternalcapi/tuple.c _testinternalcapi/typecache.c
@MODULE__TESTCAPI_TRUE@_testcapi _testcapimodule.c _testcapi/vectorcall.c _testcapi/heaptype.c _testcapi/abstract.c _testcapi/unicode.c _testcapi/dict.c _testcapi/set.c _testcapi/list.c _testcapi/tuple.c _testcapi/getargs.c _testcapi/datetime.c _testcapi/docstring.c _testcapi/mem.c _testcapi/watchers.c _testcapi/long.c _testcapi/float.c _testcapi/complex.c _testcapi/numbers.c _testcapi/structmember.c _testcapi/exceptions.c _testcapi/code.c _testcapi/buffer.c _testcapi/pyatomic.c _testcapi/run.c _testcapi/file.c _testcapi/codec.c _testcapi/immortal.c _testcapi/gc.c _testcapi/hash.c _testcapi/time.c _testcapi/bytes.c _testcapi/object.c _testcapi/modsupport.c _testcapi/monitoring.c _testcapi/config.c _testcapi/import.c _testcapi/frame.c _testcapi/type.c _testcapi/function.c _testcapi/module.c _testcapi/weakref.c _testcapi/marshal.c
-@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/capsule.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/slice.c _testlimitedcapi/slots.c _testlimitedcapi/sys.c _testlimitedcapi/threadstate.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c _testlimitedcapi/weakref.c _testlimitedcapi/run.c _testlimitedcapi/type.c _testlimitedcapi/hash.c
+@MODULE__TESTLIMITEDCAPI_TRUE@_testlimitedcapi _testlimitedcapi.c _testlimitedcapi/abstract.c _testlimitedcapi/bytearray.c _testlimitedcapi/bytes.c _testlimitedcapi/capsule.c _testlimitedcapi/codec.c _testlimitedcapi/complex.c _testlimitedcapi/dict.c _testlimitedcapi/eval.c _testlimitedcapi/float.c _testlimitedcapi/heaptype_relative.c _testlimitedcapi/import.c _testlimitedcapi/list.c _testlimitedcapi/long.c _testlimitedcapi/object.c _testlimitedcapi/pyos.c _testlimitedcapi/set.c _testlimitedcapi/slice.c _testlimitedcapi/slots.c _testlimitedcapi/sys.c _testlimitedcapi/threadstate.c _testlimitedcapi/tuple.c _testlimitedcapi/unicode.c _testlimitedcapi/vectorcall_limited.c _testlimitedcapi/version.c _testlimitedcapi/file.c _testlimitedcapi/weakref.c _testlimitedcapi/run.c _testlimitedcapi/type.c _testlimitedcapi/hash.c _testlimitedcapi/build.c
@MODULE__TESTCLINIC_TRUE@_testclinic _testclinic.c
@MODULE__TESTCLINIC_LIMITED_TRUE@_testclinic_limited _testclinic_limited.c
diff --git a/Modules/_testlimitedcapi.c b/Modules/_testlimitedcapi.c
index 0d290eb5ef5b9e..1aee3bc9bf3c1d 100644
--- a/Modules/_testlimitedcapi.c
+++ b/Modules/_testlimitedcapi.c
@@ -97,6 +97,9 @@ module_exec(PyObject *mod)
if (_PyTestLimitedCAPI_Init_Hash(mod) < 0) {
return -1;
}
+ if (_PyTestLimitedCAPI_Init_Build(mod) < 0) {
+ return -1;
+ }
return 0;
}
diff --git a/Modules/_testlimitedcapi/build.c b/Modules/_testlimitedcapi/build.c
new file mode 100644
index 00000000000000..ae26fdc07fe908
--- /dev/null
+++ b/Modules/_testlimitedcapi/build.c
@@ -0,0 +1,78 @@
+#include "parts.h"
+#include "util.h"
+
+
+static PyObject*
+return_string(const char *str)
+{
+ assert(str != NULL);
+ return PyUnicode_FromString(str);
+}
+
+
+/* Test Py_GetVersion() */
+static PyObject*
+py_getversion(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+ return return_string(Py_GetVersion());
+}
+
+
+/* Test Py_GetPlatform() */
+static PyObject*
+py_getplatform(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+ return return_string(Py_GetPlatform());
+}
+
+
+/* Test Py_GetCopyright() */
+static PyObject*
+py_getcopyright(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+ return return_string(Py_GetCopyright());
+}
+
+
+/* Test Py_GetCompiler() */
+static PyObject*
+py_getcompiler(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+ return return_string(Py_GetCompiler());
+}
+
+
+/* Test Py_GetBuildInfo() */
+static PyObject*
+py_getbuildinfo(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+ return return_string(Py_GetBuildInfo());
+}
+
+
+/* Test _Py_GetBuiltWithAssert() */
+static PyObject*
+_py_getbuiltwithassert(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
+{
+ // Function only exported for _testlimitedcapi
+ PyAPI_FUNC(int) _Py_GetBuiltWithAssert(void);
+
+ return PyLong_FromLong(_Py_GetBuiltWithAssert());
+}
+
+
+static PyMethodDef test_methods[] = {
+ {"py_getversion", py_getversion, METH_NOARGS},
+ {"py_getplatform", py_getplatform, METH_NOARGS},
+ {"py_getcopyright", py_getcopyright, METH_NOARGS},
+ {"py_getcompiler", py_getcompiler, METH_NOARGS},
+ {"py_getbuildinfo", py_getbuildinfo, METH_NOARGS},
+ {"_py_getbuiltwithassert", _py_getbuiltwithassert, METH_NOARGS},
+ {NULL},
+};
+
+int
+_PyTestLimitedCAPI_Init_Build(PyObject *m)
+{
+ return PyModule_AddFunctions(m, test_methods);
+}
diff --git a/Modules/_testlimitedcapi/parts.h b/Modules/_testlimitedcapi/parts.h
index ab6f76f3d06699..1e9d140899cecf 100644
--- a/Modules/_testlimitedcapi/parts.h
+++ b/Modules/_testlimitedcapi/parts.h
@@ -53,5 +53,6 @@ int _PyTestLimitedCAPI_Init_Weakref(PyObject *module);
int _PyTestLimitedCAPI_Init_Run(PyObject *module);
int _PyTestLimitedCAPI_Init_Type(PyObject *module);
int _PyTestLimitedCAPI_Init_Hash(PyObject *module);
+int _PyTestLimitedCAPI_Init_Build(PyObject *module);
#endif // Py_TESTLIMITEDCAPI_PARTS_H
diff --git a/Modules/getbuildinfo.c b/Modules/getbuildinfo.c
index b68f0f5cc56a44..006043d7dc3ba6 100644
--- a/Modules/getbuildinfo.c
+++ b/Modules/getbuildinfo.c
@@ -77,3 +77,19 @@ _Py_gitidentifier(void)
gitid = GITBRANCH;
return gitid;
}
+
+
+// Check if Python was built with NDEBUG macro defined or not. Implement the
+// function in Modules/getbuildinfo.c so it's built with the same compiler
+// flags than the Python core C code.
+//
+// Export the function for '_testlimitedcapi' shared extension.
+PyAPI_FUNC(int)
+_Py_GetBuiltWithAssert(void)
+{
+#ifdef NDEBUG
+ return 0;
+#else
+ return 1;
+#endif
+}
diff --git a/PCbuild/_testlimitedcapi.vcxproj b/PCbuild/_testlimitedcapi.vcxproj
index 2995dbb469ed3d..1a40cd0d2271f5 100644
--- a/PCbuild/_testlimitedcapi.vcxproj
+++ b/PCbuild/_testlimitedcapi.vcxproj
@@ -123,6 +123,7 @@
+
diff --git a/PCbuild/_testlimitedcapi.vcxproj.filters b/PCbuild/_testlimitedcapi.vcxproj.filters
index 92f1c5dedbd62e..1b13da0ebca7ba 100644
--- a/PCbuild/_testlimitedcapi.vcxproj.filters
+++ b/PCbuild/_testlimitedcapi.vcxproj.filters
@@ -39,6 +39,7 @@
+