[Python-checkins] gh-69443: Add test.support.Py_DEBUG constant (#93226)

vstinner webhook-mailer at python.org
Wed May 25 18:13:26 EDT 2022


https://github.com/python/cpython/commit/518595652759462b13904df767f69b8cc2c61143
commit: 518595652759462b13904df767f69b8cc2c61143
branch: main
author: Victor Stinner <vstinner at python.org>
committer: vstinner <vstinner at python.org>
date: 2022-05-26T00:12:54+02:00
summary:

gh-69443: Add test.support.Py_DEBUG constant (#93226)

files:
M Doc/library/test.rst
M Lib/test/support/__init__.py
M Lib/test/test_capi.py
M Lib/test/test_cmd_line.py
M Lib/test/test_embed.py
M Lib/test/test_hashlib.py
M Lib/test/test_io.py
M Lib/test/test_lltrace.py
M Lib/test/test_marshal.py
M Lib/test/test_regrtest.py
M Lib/test/test_ssl.py
M Lib/test/test_threading.py
M Lib/test/test_warnings/__init__.py

diff --git a/Doc/library/test.rst b/Doc/library/test.rst
index 707e966455ceb..548919cd59785 100644
--- a/Doc/library/test.rst
+++ b/Doc/library/test.rst
@@ -319,6 +319,15 @@ The :mod:`test.support` module defines the following constants:
    to make writes blocking.
 
 
+.. data:: Py_DEBUG
+
+   True if Python is built with the :c:macro:`Py_DEBUG` macro defined: if
+   Python is :ref:`built in debug mode <debug-build>`
+   (:option:`./configure --with-pydebug <--with-pydebug>`).
+
+   .. versionadded:: 3.12
+
+
 .. data:: SOCK_MAX_SIZE
 
    A constant that is likely larger than the underlying OS socket buffer size,
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index c284fc67b6402..e23ffee22d1cd 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -59,6 +59,7 @@
     "run_with_tz", "PGO", "missing_compiler_executable",
     "ALWAYS_EQ", "NEVER_EQ", "LARGEST", "SMALLEST",
     "LOOPBACK_TIMEOUT", "INTERNET_TIMEOUT", "SHORT_TIMEOUT", "LONG_TIMEOUT",
+    "Py_DEBUG",
     ]
 
 
@@ -2205,3 +2206,8 @@ def requires_venv_with_pip():
     except ImportError:
         ctypes = None
     return unittest.skipUnless(ctypes, 'venv: pip requires ctypes')
+
+
+# True if Python is built with the Py_DEBUG macro defined: if
+# Python is built in debug mode (./configure --with-pydebug).
+Py_DEBUG = hasattr(sys, 'gettotalrefcount')
diff --git a/Lib/test/test_capi.py b/Lib/test/test_capi.py
index 904ae9bc47ecf..49cd82108c92c 100644
--- a/Lib/test/test_capi.py
+++ b/Lib/test/test_capi.py
@@ -36,9 +36,6 @@
 
 import _testinternalcapi
 
-# Were we compiled --with-pydebug or with #define Py_DEBUG?
-Py_DEBUG = hasattr(sys, 'gettotalrefcount')
-
 
 def decode_stderr(err):
     return err.decode('utf-8', 'replace').replace('\r', '')
@@ -230,7 +227,7 @@ def test_c_type_with_ipow(self):
     def test_return_null_without_error(self):
         # Issue #23571: A function must not return NULL without setting an
         # error
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             code = textwrap.dedent("""
                 import _testcapi
                 from test import support
@@ -258,7 +255,7 @@ def test_return_null_without_error(self):
 
     def test_return_result_with_error(self):
         # Issue #23571: A function must not return a result with an error set
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             code = textwrap.dedent("""
                 import _testcapi
                 from test import support
@@ -516,7 +513,7 @@ def __del__(self):
         del subclass_instance
 
         # Test that setting __class__ modified the reference counts of the types
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             # gh-89373: In debug mode, _Py_Dealloc() keeps a strong reference
             # to the type while calling tp_dealloc()
             self.assertEqual(type_refcnt, B.refcnt_in_del)
@@ -586,7 +583,7 @@ def test_c_subclass_of_heap_ctype_with_del_modifying_dunder_class_only_decrefs_o
         del subclass_instance
 
         # Test that setting __class__ modified the reference counts of the types
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             # gh-89373: In debug mode, _Py_Dealloc() keeps a strong reference
             # to the type while calling tp_dealloc()
             self.assertEqual(type_refcnt, _testcapi.HeapCTypeSubclassWithFinalizer.refcnt_in_del)
@@ -1029,7 +1026,7 @@ class PyMemPymallocDebugTests(PyMemDebugTests):
     PYTHONMALLOC = 'pymalloc_debug'
 
 
- at unittest.skipUnless(Py_DEBUG, 'need Py_DEBUG')
+ at unittest.skipUnless(support.Py_DEBUG, 'need Py_DEBUG')
 class PyMemDefaultTests(PyMemDebugTests):
     # test default allocator of Python compiled in debug mode
     PYTHONMALLOC = ''
diff --git a/Lib/test/test_cmd_line.py b/Lib/test/test_cmd_line.py
index 5a9e14bbd3200..ed733d2f61666 100644
--- a/Lib/test/test_cmd_line.py
+++ b/Lib/test/test_cmd_line.py
@@ -18,9 +18,6 @@
 if not support.has_subprocess_support:
     raise unittest.SkipTest("test module requires subprocess")
 
-# Debug build?
-Py_DEBUG = hasattr(sys, "gettotalrefcount")
-
 
 # XXX (ncoghlan): Move to script_helper and make consistent with run_python
 def _kill_python_and_exit_code(p):
@@ -120,7 +117,7 @@ def run_python(*args):
         # "-X showrefcount" shows the refcount, but only in debug builds
         rc, out, err = run_python('-I', '-X', 'showrefcount', '-c', code)
         self.assertEqual(out.rstrip(), b"{'showrefcount': True}")
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             # bpo-46417: Tolerate negative reference count which can occur
             # because of bugs in C extensions. This test is only about checking
             # the showrefcount feature.
@@ -685,7 +682,7 @@ def test_xdev(self):
         code = ("import warnings; "
                 "print(' '.join('%s::%s' % (f[0], f[2].__name__) "
                                 "for f in warnings.filters))")
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             expected_filters = "default::Warning"
         else:
             expected_filters = ("default::Warning "
@@ -757,7 +754,7 @@ def test_warnings_filter_precedence(self):
         expected_filters = ("error::BytesWarning "
                             "once::UserWarning "
                             "always::UserWarning")
-        if not Py_DEBUG:
+        if not support.Py_DEBUG:
             expected_filters += (" "
                                  "default::DeprecationWarning "
                                  "ignore::DeprecationWarning "
@@ -795,10 +792,10 @@ def test_pythonmalloc(self):
         # Test the PYTHONMALLOC environment variable
         pymalloc = support.with_pymalloc()
         if pymalloc:
-            default_name = 'pymalloc_debug' if Py_DEBUG else 'pymalloc'
+            default_name = 'pymalloc_debug' if support.Py_DEBUG else 'pymalloc'
             default_name_debug = 'pymalloc_debug'
         else:
-            default_name = 'malloc_debug' if Py_DEBUG else 'malloc'
+            default_name = 'malloc_debug' if support.Py_DEBUG else 'malloc'
             default_name_debug = 'malloc_debug'
 
         tests = [
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 5ba6e3a43fdc6..f1ca6da147376 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -22,7 +22,6 @@
 
 MS_WINDOWS = (os.name == 'nt')
 MACOS = (sys.platform == 'darwin')
-Py_DEBUG = hasattr(sys, 'gettotalrefcount')
 PYMEM_ALLOCATOR_NOT_SET = 0
 PYMEM_ALLOCATOR_DEBUG = 2
 PYMEM_ALLOCATOR_MALLOC = 3
@@ -498,7 +497,7 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         'pathconfig_warnings': 1,
         '_init_main': 1,
         '_isolated_interpreter': 0,
-        'use_frozen_modules': not Py_DEBUG,
+        'use_frozen_modules': not support.Py_DEBUG,
         'safe_path': 0,
         '_is_python_build': IGNORE_CONFIG,
     }
@@ -1206,7 +1205,7 @@ def test_init_setpath_config(self):
              # The current getpath.c doesn't determine the stdlib dir
              # in this case.
             'stdlib_dir': '',
-            'use_frozen_modules': not Py_DEBUG,
+            'use_frozen_modules': not support.Py_DEBUG,
             # overridden by PyConfig
             'program_name': 'conf_program_name',
             'base_executable': 'conf_executable',
@@ -1445,12 +1444,12 @@ def test_init_pyvenv_cfg(self):
                 config['base_prefix'] = pyvenv_home
                 config['prefix'] = pyvenv_home
                 config['stdlib_dir'] = os.path.join(pyvenv_home, 'Lib')
-                config['use_frozen_modules'] = not Py_DEBUG
+                config['use_frozen_modules'] = not support.Py_DEBUG
             else:
                 # cannot reliably assume stdlib_dir here because it
                 # depends too much on our build. But it ought to be found
                 config['stdlib_dir'] = self.IGNORE_CONFIG
-                config['use_frozen_modules'] = not Py_DEBUG
+                config['use_frozen_modules'] = not support.Py_DEBUG
 
             env = self.copy_paths_by_env(config)
             self.check_all_configs("test_init_compat_config", config,
@@ -1680,7 +1679,7 @@ def test_frozenmain(self):
         """).lstrip()
         self.assertEqual(out, expected)
 
-    @unittest.skipUnless(hasattr(sys, 'gettotalrefcount'),
+    @unittest.skipUnless(support.Py_DEBUG,
                          '-X showrefcount requires a Python debug build')
     def test_no_memleak(self):
         # bpo-1635741: Python must release all memory at exit
diff --git a/Lib/test/test_hashlib.py b/Lib/test/test_hashlib.py
index 67becdd6d317f..bc9407dc9e424 100644
--- a/Lib/test/test_hashlib.py
+++ b/Lib/test/test_hashlib.py
@@ -26,8 +26,6 @@
 from test.support import warnings_helper
 from http.client import HTTPException
 
-# Were we compiled --with-pydebug or with #define Py_DEBUG?
-COMPILED_WITH_PYDEBUG = hasattr(sys, 'gettotalrefcount')
 
 # default builtin hash module
 default_builtin_hashes = {'md5', 'sha1', 'sha256', 'sha512', 'sha3', 'blake2'}
@@ -109,7 +107,7 @@ class HashLibTestCase(unittest.TestCase):
     shakes = {'shake_128', 'shake_256'}
 
     # Issue #14693: fallback modules are always compiled under POSIX
-    _warn_on_extension_import = os.name == 'posix' or COMPILED_WITH_PYDEBUG
+    _warn_on_extension_import = (os.name == 'posix' or support.Py_DEBUG)
 
     def _conditional_import_module(self, module_name):
         """Import a module and return a reference to it or None on failure."""
diff --git a/Lib/test/test_io.py b/Lib/test/test_io.py
index daccbae5b4a1d..129734b22328e 100644
--- a/Lib/test/test_io.py
+++ b/Lib/test/test_io.py
@@ -68,7 +68,7 @@ class EmptyStruct(ctypes.Structure):
 
 # Does io.IOBase finalizer log the exception if the close() method fails?
 # The exception is ignored silently by default in release build.
-IOBASE_EMITS_UNRAISABLE = (hasattr(sys, "gettotalrefcount") or sys.flags.dev_mode)
+IOBASE_EMITS_UNRAISABLE = (support.Py_DEBUG or sys.flags.dev_mode)
 
 
 def _default_chunk_size():
diff --git a/Lib/test/test_lltrace.py b/Lib/test/test_lltrace.py
index 63b65e4b2f821..5d175ce57b179 100644
--- a/Lib/test/test_lltrace.py
+++ b/Lib/test/test_lltrace.py
@@ -3,7 +3,8 @@
 import textwrap
 import unittest
 
-from test.support import os_helper, verbose
+from test import support
+from test.support import os_helper
 from test.support.script_helper import assert_python_ok
 
 def example():
@@ -14,9 +15,8 @@ def example():
     y = "an example"
     print(x, y)
 
-Py_DEBUG = hasattr(sys, 'gettotalrefcount')
 
- at unittest.skipUnless(Py_DEBUG, "lltrace requires Py_DEBUG")
+ at unittest.skipUnless(support.Py_DEBUG, "lltrace requires Py_DEBUG")
 class TestLLTrace(unittest.TestCase):
 
     def run_code(self, code):
@@ -28,7 +28,7 @@ def run_code(self, code):
         self.assertEqual(stderr, b"")
         self.assertEqual(status, 0)
         result = stdout.decode('utf-8')
-        if verbose:
+        if support.verbose:
             print("\n\n--- code ---")
             print(code)
             print("\n--- stdout ---")
diff --git a/Lib/test/test_marshal.py b/Lib/test/test_marshal.py
index aae86cc257d7e..882a819ca8090 100644
--- a/Lib/test/test_marshal.py
+++ b/Lib/test/test_marshal.py
@@ -256,7 +256,7 @@ def test_recursion_limit(self):
         # The max stack depth should match the value in Python/marshal.c.
         # BUG: https://bugs.python.org/issue33720
         # Windows always limits the maximum depth on release and debug builds
-        #if os.name == 'nt' and hasattr(sys, 'gettotalrefcount'):
+        #if os.name == 'nt' and support.Py_DEBUG:
         if os.name == 'nt':
             MAX_MARSHAL_STACK_DEPTH = 1000
         else:
diff --git a/Lib/test/test_regrtest.py b/Lib/test/test_regrtest.py
index 15e2f89ee20c1..4f632bb2f3954 100644
--- a/Lib/test/test_regrtest.py
+++ b/Lib/test/test_regrtest.py
@@ -25,7 +25,6 @@
 if not support.has_subprocess_support:
     raise unittest.SkipTest("test module requires subprocess")
 
-Py_DEBUG = hasattr(sys, 'gettotalrefcount')
 ROOT_DIR = os.path.join(os.path.dirname(__file__), '..', '..')
 ROOT_DIR = os.path.abspath(os.path.normpath(ROOT_DIR))
 LOG_PREFIX = r'[0-9]+:[0-9]+:[0-9]+ (?:load avg: [0-9]+\.[0-9]{2} )?'
@@ -665,7 +664,7 @@ def test_tools_buildbot_test(self):
             test_args.append('-arm32')   # 32-bit ARM build
         elif platform.architecture()[0] == '64bit':
             test_args.append('-x64')   # 64-bit build
-        if not Py_DEBUG:
+        if not support.Py_DEBUG:
             test_args.append('+d')     # Release build, use python.exe
         self.run_batch(script, *test_args, *self.tests)
 
@@ -682,7 +681,7 @@ def test_pcbuild_rt(self):
             rt_args.append('-arm32')   # 32-bit ARM build
         elif platform.architecture()[0] == '64bit':
             rt_args.append('-x64')   # 64-bit build
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             rt_args.append('-d')     # Debug build, use python_d.exe
         self.run_batch(script, *rt_args, *self.regrtest_args, *self.tests)
 
@@ -903,7 +902,7 @@ def check_leak(self, code, what):
             reflog = fp.read()
             self.assertIn(line2, reflog)
 
-    @unittest.skipUnless(Py_DEBUG, 'need a debug build')
+    @unittest.skipUnless(support.Py_DEBUG, 'need a debug build')
     def test_huntrleaks(self):
         # test --huntrleaks
         code = textwrap.dedent("""
@@ -917,7 +916,7 @@ def test_leak(self):
         """)
         self.check_leak(code, 'references')
 
-    @unittest.skipUnless(Py_DEBUG, 'need a debug build')
+    @unittest.skipUnless(support.Py_DEBUG, 'need a debug build')
     def test_huntrleaks_fd_leak(self):
         # test --huntrleaks for file descriptor leak
         code = textwrap.dedent("""
diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py
index fed76378726c9..6a66c167933de 100644
--- a/Lib/test/test_ssl.py
+++ b/Lib/test/test_ssl.py
@@ -38,8 +38,7 @@
 
 from ssl import TLSVersion, _TLSContentType, _TLSMessageType, _TLSAlertType
 
-Py_DEBUG = hasattr(sys, 'gettotalrefcount')
-Py_DEBUG_WIN32 = Py_DEBUG and sys.platform == 'win32'
+Py_DEBUG_WIN32 = support.Py_DEBUG and sys.platform == 'win32'
 
 PROTOCOLS = sorted(ssl._PROTOCOL_NAMES)
 HOST = socket_helper.HOST
@@ -1657,7 +1656,8 @@ def test_load_default_certs_env(self):
             self.assertEqual(ctx.cert_store_stats(), {"crl": 0, "x509": 1, "x509_ca": 0})
 
     @unittest.skipUnless(sys.platform == "win32", "Windows specific")
-    @unittest.skipIf(hasattr(sys, "gettotalrefcount"), "Debug build does not share environment between CRTs")
+    @unittest.skipIf(support.Py_DEBUG,
+                     "Debug build does not share environment between CRTs")
     def test_load_default_certs_env_windows(self):
         ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
         ctx.load_default_certs()
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 6cdc45f523dcb..dcd27697bb483 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -33,9 +33,6 @@
 # on platforms known to behave badly.
 platforms_to_skip = ('netbsd5', 'hp-ux11')
 
-# Is Python built with Py_DEBUG macro defined?
-Py_DEBUG = hasattr(sys, 'gettotalrefcount')
-
 
 def restore_default_excepthook(testcase):
     testcase.addCleanup(setattr, threading, 'excepthook', threading.excepthook)
diff --git a/Lib/test/test_warnings/__init__.py b/Lib/test/test_warnings/__init__.py
index 0f960b82bfaeb..b00ddd5df2f25 100644
--- a/Lib/test/test_warnings/__init__.py
+++ b/Lib/test/test_warnings/__init__.py
@@ -22,8 +22,6 @@
 c_warnings = import_helper.import_fresh_module('warnings',
                                                fresh=['_warnings'])
 
-Py_DEBUG = hasattr(sys, 'gettotalrefcount')
-
 @contextmanager
 def warnings_state(module):
     """Use a specific warnings implementation in warning_tests."""
@@ -1191,7 +1189,7 @@ def test_conflicting_envvar_and_command_line(self):
 
     def test_default_filter_configuration(self):
         pure_python_api = self.module is py_warnings
-        if Py_DEBUG:
+        if support.Py_DEBUG:
             expected_default_filters = []
         else:
             if pure_python_api:



More information about the Python-checkins mailing list