https://github.com/python/cpython/commit/674befbd7be3bffee66772ff9fdef168feda47ef
commit: 674befbd7be3bffee66772ff9fdef168feda47ef
branch: main
author: Brandt Bucher <[email protected]>
committer: encukou <[email protected]>
date: 2025-01-31T11:50:54+01:00
summary:
GH-129386: Add `test.support.reset_code` (GH-129486)
files:
A Misc/NEWS.d/next/Tests/2025-01-30-13-09-27.gh-issue-129386.iNtbEi.rst
M Lib/test/support/__init__.py
M Lib/test/test_capi/test_opt.py
M Lib/test/test_dis.py
M Lib/test/test_embed.py
M Lib/test/test_opcache.py
diff --git a/Lib/test/support/__init__.py b/Lib/test/support/__init__.py
index 6436753f998a16..230bb240c89f77 100644
--- a/Lib/test/support/__init__.py
+++ b/Lib/test/support/__init__.py
@@ -66,6 +66,7 @@
"BrokenIter",
"in_systemd_nspawn_sync_suppressed",
"run_no_yield_async_fn", "run_yielding_async_fn", "async_yield",
+ "reset_code",
]
@@ -1286,6 +1287,12 @@ def requires_specialization_ft(test):
_opcode.ENABLE_SPECIALIZATION_FT, "requires specialization")(test)
+def reset_code(f: types.FunctionType) -> types.FunctionType:
+ """Clear all specializations, local instrumentation, and JIT code for the
given function."""
+ f.__code__ = f.__code__.replace()
+ return f
+
+
#=======================================================================
# Check for the presence of docstrings.
diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py
index d3aea37e094e61..02e534caec1162 100644
--- a/Lib/test/test_capi/test_opt.py
+++ b/Lib/test/test_capi/test_opt.py
@@ -9,7 +9,8 @@
import _opcode
from test.support import (script_helper, requires_specialization,
- import_helper, Py_GIL_DISABLED, requires_jit_enabled)
+ import_helper, Py_GIL_DISABLED, requires_jit_enabled,
+ reset_code)
_testinternalcapi = import_helper.import_module("_testinternalcapi")
@@ -19,11 +20,11 @@
@contextlib.contextmanager
def clear_executors(func):
# Clear executors in func before and after running a block
- func.__code__ = func.__code__.replace()
+ reset_code(func)
try:
yield
finally:
- func.__code__ = func.__code__.replace()
+ reset_code(func)
def get_first_executor(func):
diff --git a/Lib/test/test_dis.py b/Lib/test/test_dis.py
index bba2ac80aa6769..e99289cf66af67 100644
--- a/Lib/test/test_dis.py
+++ b/Lib/test/test_dis.py
@@ -15,7 +15,7 @@
import unittest
from test.support import (captured_stdout, requires_debug_ranges,
requires_specialization, cpython_only,
- os_helper, import_helper)
+ os_helper, import_helper, reset_code)
from test.support.bytecode_helper import BytecodeTestCase
@@ -1356,7 +1356,7 @@ def f():
self.code_quicken(f)
else:
# "copy" the code to un-quicken it:
- f.__code__ = f.__code__.replace()
+ reset_code(f)
for instruction in _unroll_caches_as_Instructions(dis.get_instructions(
f, show_caches=True, adaptive=adaptive
), show_caches=True):
diff --git a/Lib/test/test_embed.py b/Lib/test/test_embed.py
index 72221379a00051..cd65496cafb04d 100644
--- a/Lib/test/test_embed.py
+++ b/Lib/test/test_embed.py
@@ -391,6 +391,7 @@ def
test_specialized_static_code_gets_unspecialized_at_Py_FINALIZE(self):
import importlib._bootstrap
import opcode
import test.test_dis
+ import test.support
def is_specialized(f):
for instruction in dis.get_instructions(f, adaptive=True):
@@ -409,7 +410,7 @@ def is_specialized(f):
func = importlib._bootstrap._handle_fromlist
# "copy" the code to un-specialize it:
- func.__code__ = func.__code__.replace()
+ test.support.reset_code(func)
assert not is_specialized(func), "specialized instructions found"
diff --git a/Lib/test/test_opcache.py b/Lib/test/test_opcache.py
index 2defe74892786d..87de4c94ba26fb 100644
--- a/Lib/test/test_opcache.py
+++ b/Lib/test/test_opcache.py
@@ -6,7 +6,7 @@
import unittest
from test.support import (threading_helper, check_impl_detail,
requires_specialization, requires_specialization_ft,
- cpython_only, requires_jit_disabled)
+ cpython_only, requires_jit_disabled, reset_code)
from test.support.import_helper import import_module
# Skip this module on other interpreters, it is cpython specific:
@@ -579,9 +579,9 @@ def assert_races_do_not_crash(
# Reset:
if check_items:
for item in items:
- item.__code__ = item.__code__.replace()
+ reset_code(item)
else:
- read.__code__ = read.__code__.replace()
+ reset_code(read)
# Specialize:
for _ in range(_testinternalcapi.SPECIALIZATION_THRESHOLD):
read(items)
@@ -1552,6 +1552,7 @@ def test_store_attr_instance_value(self):
class C:
pass
+ @reset_code
def set_value(n):
c = C()
for i in range(n):
@@ -1577,6 +1578,7 @@ class C:
for i in range(_testinternalcapi.SHARED_KEYS_MAX_SIZE - 1):
setattr(c, f"_{i}", None)
+ @reset_code
def set_value(n):
for i in range(n):
c.x = i
diff --git
a/Misc/NEWS.d/next/Tests/2025-01-30-13-09-27.gh-issue-129386.iNtbEi.rst
b/Misc/NEWS.d/next/Tests/2025-01-30-13-09-27.gh-issue-129386.iNtbEi.rst
new file mode 100644
index 00000000000000..a03f596bc46c30
--- /dev/null
+++ b/Misc/NEWS.d/next/Tests/2025-01-30-13-09-27.gh-issue-129386.iNtbEi.rst
@@ -0,0 +1,2 @@
+Add ``test.support.reset_code``, which can be used to reset various
+bytecode-level optimizations and local instrumentation for a function.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: [email protected]