From 518595652759462b13904df767f69b8cc2c61143 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 26 May 2022 00:12:54 +0200 Subject: [PATCH] gh-69443: Add test.support.Py_DEBUG constant (#93226) --- Doc/library/test.rst | 9 +++++++++ Lib/test/support/__init__.py | 6 ++++++ Lib/test/test_capi.py | 13 +++++-------- Lib/test/test_cmd_line.py | 13 +++++-------- Lib/test/test_embed.py | 11 +++++------ Lib/test/test_hashlib.py | 4 +--- Lib/test/test_io.py | 2 +- Lib/test/test_lltrace.py | 8 ++++---- Lib/test/test_marshal.py | 2 +- Lib/test/test_regrtest.py | 9 ++++----- Lib/test/test_ssl.py | 6 +++--- Lib/test/test_threading.py | 3 --- Lib/test/test_warnings/__init__.py | 4 +--- 13 files changed, 45 insertions(+), 45 deletions(-) diff --git a/Doc/library/test.rst b/Doc/library/test.rst index 707e966455c..548919cd597 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 ` + (: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 c284fc67b64..e23ffee22d1 100644 --- a/Lib/test/support/__init__.py +++ b/Lib/test/support/__init__.py @@ -59,6 +59,7 @@ __all__ = [ "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 904ae9bc47e..49cd82108c9 100644 --- a/Lib/test/test_capi.py +++ b/Lib/test/test_capi.py @@ -36,9 +36,6 @@ _testcapi = import_helper.import_module('_testcapi') 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 @@ class CAPITest(unittest.TestCase): 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 @@ class CAPITest(unittest.TestCase): 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 @@ class CAPITest(unittest.TestCase): 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 @@ class CAPITest(unittest.TestCase): 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' -@unittest.skipUnless(Py_DEBUG, 'need Py_DEBUG') +@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 5a9e14bbd32..ed733d2f616 100644 --- a/Lib/test/test_cmd_line.py +++ b/Lib/test/test_cmd_line.py @@ -18,9 +18,6 @@ from test.support.script_helper import ( 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 @@ class CmdLineTest(unittest.TestCase): # "-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 @@ class CmdLineTest(unittest.TestCase): 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 @@ class CmdLineTest(unittest.TestCase): 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 @@ class CmdLineTest(unittest.TestCase): # 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 5ba6e3a43fd..f1ca6da1473 100644 --- a/Lib/test/test_embed.py +++ b/Lib/test/test_embed.py @@ -22,7 +22,6 @@ if not support.has_subprocess_support: 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 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): # 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 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase): 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 @@ class MiscTests(EmbeddingTestsMixin, unittest.TestCase): """).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 67becdd6d31..bc9407dc9e4 100644 --- a/Lib/test/test_hashlib.py +++ b/Lib/test/test_hashlib.py @@ -26,8 +26,6 @@ from test.support import threading_helper 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 daccbae5b4a..129734b2232 100644 --- a/Lib/test/test_io.py +++ b/Lib/test/test_io.py @@ -68,7 +68,7 @@ else: # 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 63b65e4b2f8..5d175ce57b1 100644 --- a/Lib/test/test_lltrace.py +++ b/Lib/test/test_lltrace.py @@ -3,7 +3,8 @@ import sys 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') -@unittest.skipUnless(Py_DEBUG, "lltrace requires Py_DEBUG") +@unittest.skipUnless(support.Py_DEBUG, "lltrace requires Py_DEBUG") class TestLLTrace(unittest.TestCase): def run_code(self, code): @@ -28,7 +28,7 @@ class TestLLTrace(unittest.TestCase): 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 aae86cc257d..882a819ca80 100644 --- a/Lib/test/test_marshal.py +++ b/Lib/test/test_marshal.py @@ -256,7 +256,7 @@ class BugsTestCase(unittest.TestCase): # 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 15e2f89ee20..4f632bb2f39 100644 --- a/Lib/test/test_regrtest.py +++ b/Lib/test/test_regrtest.py @@ -25,7 +25,6 @@ from test.libregrtest import utils, setup 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 @@ class ProgramsTestCase(BaseTestCase): 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 @@ class ProgramsTestCase(BaseTestCase): 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 @@ class ArgsTestCase(BaseTestCase): 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 @@ class ArgsTestCase(BaseTestCase): """) 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 fed76378726..6a66c167933 100644 --- a/Lib/test/test_ssl.py +++ b/Lib/test/test_ssl.py @@ -38,8 +38,7 @@ import _ssl 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 @@ class ContextTests(unittest.TestCase): 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 6cdc45f523d..dcd27697bb4 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -33,9 +33,6 @@ threading_helper.requires_working_threading(module=True) # 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 0f960b82bfa..b00ddd5df2f 100644 --- a/Lib/test/test_warnings/__init__.py +++ b/Lib/test/test_warnings/__init__.py @@ -22,8 +22,6 @@ py_warnings = import_helper.import_fresh_module('warnings', 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 @@ class EnvironmentVariableTests(BaseTest): 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: