import warnings
from inspect import isabstract
from typing import Any
+import linecache
from test import support
from test.support import os_helper
ps = copyreg.dispatch_table.copy()
pic = sys.path_importer_cache.copy()
zdc: dict[str, Any] | None
+ # Linecache holds a cache with the source of interactive code snippets
+ # (e.g. code typed in the REPL). This cache is not cleared by
+ # linecache.clearcache(). We need to save and restore it to avoid false
+ # positives.
+ linecache_data = linecache.cache.copy(), linecache._interactive_cache.copy() # type: ignore[attr-defined]
try:
import zipimport
except ImportError:
xml_filename = 'refleak-xml.tmp'
result = None
- dash_R_cleanup(fs, ps, pic, zdc, abcs)
+ dash_R_cleanup(fs, ps, pic, zdc, abcs, linecache_data)
for i in rep_range:
support.gc_collect()
refleak_helper._hunting_for_refleaks = current
save_support_xml(xml_filename)
- dash_R_cleanup(fs, ps, pic, zdc, abcs)
+ dash_R_cleanup(fs, ps, pic, zdc, abcs, linecache_data)
support.gc_collect()
# Read memory statistics immediately after the garbage collection.
return (failed, result)
-def dash_R_cleanup(fs, ps, pic, zdc, abcs):
+def dash_R_cleanup(fs, ps, pic, zdc, abcs, linecache_data):
import copyreg
import collections.abc
copyreg.dispatch_table.update(ps)
sys.path_importer_cache.clear()
sys.path_importer_cache.update(pic)
+ lcache, linteractive = linecache_data
+ linecache._interactive_cache.clear()
+ linecache._interactive_cache.update(linteractive)
+ linecache.cache.clear()
+ linecache.cache.update(lcache)
try:
import zipimport
except ImportError:
self.assertMultilineMatches(bt,
r'''^.*
Traceback \(most recent call first\):
- <built-in method _idfunc of module object .*>
- File ".*gdb_sample.py", line 11, in baz
- _idfunc\(42\)
- File ".*gdb_sample.py", line 8, in bar
+ <built-in method id of module object .*>
+ File ".*gdb_sample.py", line 10, in baz
+ id\(42\)
+ File ".*gdb_sample.py", line 7, in bar
baz\(a, b, c\)
- File ".*gdb_sample.py", line 5, in foo
+ File ".*gdb_sample.py", line 4, in foo
bar\(a=a, b=b, c=c\)
- File ".*gdb_sample.py", line 13, in <module>
+ File ".*gdb_sample.py", line 12, in <module>
foo\(1, 2, 3\)
''')
cmds_after_breakpoint=['py-bt-full'])
self.assertMultilineMatches(bt,
r'''^.*
-#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 8, in bar \(a=1, b=2, c=3\)
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 7, in bar \(a=1, b=2, c=3\)
baz\(a, b, c\)
-#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 5, in foo \(a=1, b=2, c=3\)
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 4, in foo \(a=1, b=2, c=3\)
bar\(a=a, b=b, c=c\)
-#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 13, in <module> \(\)
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file .*gdb_sample.py, line 12, in <module> \(\)
foo\(1, 2, 3\)
''')
'Verify that "py-bt" indicates threads that are waiting for the GIL'
cmd = '''
from threading import Thread
-from _typing import _idfunc
class TestThread(Thread):
# These threads would run forever, but we'll interrupt things with the
t[i].start()
# Trigger a breakpoint on the main thread
-_idfunc(42)
+id(42)
'''
# Verify with "py-bt":
# unless we add LD_PRELOAD=PATH-TO-libpthread.so.1 as a workaround
def test_gc(self):
'Verify that "py-bt" indicates if a thread is garbage-collecting'
- cmd = ('from gc import collect; from _typing import _idfunc\n'
- '_idfunc(42)\n'
+ cmd = ('from gc import collect\n'
+ 'id(42)\n'
'def foo():\n'
' collect()\n'
'def bar():\n'
"Python was compiled with optimizations")
def test_wrapper_call(self):
cmd = textwrap.dedent('''
- from typing import _idfunc
class MyList(list):
def __init__(self):
super(*[]).__init__() # wrapper_call()
- _idfunc("first break point")
+ id("first break point")
l = MyList()
''')
cmds_after_breakpoint = ['break wrapper_call', 'continue']
bt = self.get_stack_trace(script=SAMPLE_SCRIPT,
cmds_after_breakpoint=['py-list'])
- self.assertListing(' 6 \n'
- ' 7 def bar(a, b, c):\n'
- ' 8 baz(a, b, c)\n'
- ' 9 \n'
- ' 10 def baz(*args):\n'
- ' >11 _idfunc(42)\n'
- ' 12 \n'
- ' 13 foo(1, 2, 3)\n',
+ self.assertListing(' 5 \n'
+ ' 6 def bar(a, b, c):\n'
+ ' 7 baz(a, b, c)\n'
+ ' 8 \n'
+ ' 9 def baz(*args):\n'
+ ' >10 id(42)\n'
+ ' 11 \n'
+ ' 12 foo(1, 2, 3)\n',
bt)
def test_one_abs_arg(self):
bt = self.get_stack_trace(script=SAMPLE_SCRIPT,
cmds_after_breakpoint=['py-list 9'])
- self.assertListing(' 10 def baz(*args):\n'
- ' >11 _idfunc(42)\n'
- ' 12 \n'
- ' 13 foo(1, 2, 3)\n',
+ self.assertListing(' 9 def baz(*args):\n'
+ ' >10 id(42)\n'
+ ' 11 \n'
+ ' 12 foo(1, 2, 3)\n',
bt)
def test_two_abs_args(self):
'Verify the "py-list" command with two absolute arguments'
bt = self.get_stack_trace(script=SAMPLE_SCRIPT,
- cmds_after_breakpoint=['py-list 1,4'])
+ cmds_after_breakpoint=['py-list 1,3'])
self.assertListing(' 1 # Sample script for use by test_gdb\n'
- ' 2 from _typing import _idfunc\n'
- ' 3 \n'
- ' 4 def foo(a, b, c):\n',
+ ' 2 \n'
+ ' 3 def foo(a, b, c):\n',
bt)
SAMPLE_WITH_C_CALL = """
from _testcapi import pyobject_vectorcall
-from _typing import _idfunc
def foo(a, b, c):
bar(a, b, c)
pyobject_vectorcall(baz, (a, b, c), None)
def baz(*args):
- _idfunc(42)
+ id(42)
foo(1, 2, 3)
cmds_after_breakpoint=['py-up', 'py-up'])
self.assertMultilineMatches(bt,
r'''^.*
-#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 13, in baz \(args=\(1, 2, 3\)\)
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 12, in baz \(args=\(1, 2, 3\)\)
#[0-9]+ <built-in method pyobject_vectorcall of module object at remote 0x[0-9a-f]+>
$''')
cmds_after_breakpoint=['py-up', 'py-up', 'py-down'])
self.assertMultilineMatches(bt,
r'''^.*
-#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 13, in baz \(args=\(1, 2, 3\)\)
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 12, in baz \(args=\(1, 2, 3\)\)
#[0-9]+ <built-in method pyobject_vectorcall of module object at remote 0x[0-9a-f]+>
-#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 13, in baz \(args=\(1, 2, 3\)\)
+#[0-9]+ Frame 0x-?[0-9a-f]+, for file <string>, line 12, in baz \(args=\(1, 2, 3\)\)
$''')
class PyPrintTests(DebuggerTests):
import_site=False):
# Given an input python source representation of data,
# run "python -c'id(DATA)'" under gdb with a breakpoint on
- # _typing__idfunc and scrape out gdb's representation of the "op"
+ # builtin_id and scrape out gdb's representation of the "op"
# parameter, and verify that the gdb displays the same string
#
# Verify that the gdb displays the expected string
# undecodable characters may lurk there in optimized mode
# (issue #19743).
cmds_after_breakpoint = cmds_after_breakpoint or ["backtrace 1"]
- source = "from _typing import _idfunc\n" + source
gdb_output = self.get_stack_trace(source, breakpoint=BREAKPOINT_FN,
cmds_after_breakpoint=cmds_after_breakpoint,
import_site=import_site)
# in its output, depending on the width of the terminal it's connected
# to (using its "wrap_here" function)
m = re.search(
- # Match '#0 _typing_idfunc(module=..., x=...)'
- r'#0\s+_typing__idfunc\s+\(module\=.*,\s+x=\s*(.*?)?\)'
+ # Match '#0 builtin_id(self=..., v=...)'
+ r'#0\s+builtin_id\s+\(self\=.*,\s+v=\s*(.*?)?\)'
# Match ' at Python/bltinmodule.c'.
- # bpo-38239: typing_idfunc() is defined in Module/_typingmldule.c,
+ # bpo-38239: builtin_id() is defined in Python/bltinmodule.c,
# but accept any "Directory\file.c" to support Link Time
# Optimization (LTO).
r'\s+at\s+\S*[A-Za-z]+/[A-Za-z0-9_-]+\.c',
return m.group(1), gdb_output
def test_getting_backtrace(self):
- gdb_output = self.get_stack_trace('from _typing import _idfunc;_idfunc(42)')
+ gdb_output = self.get_stack_trace('id(42)')
self.assertTrue(BREAKPOINT_FN in gdb_output)
def assertGdbRepr(self, val, exp_repr=None):
# Ensure that gdb's rendering of the value in a debugged process
# matches repr(value) in this process:
- gdb_repr, gdb_output = self.get_gdb_repr('_idfunc(' + ascii(val) + ')')
+ gdb_repr, gdb_output = self.get_gdb_repr('id(' + ascii(val) + ')')
if not exp_repr:
exp_repr = repr(val)
self.assertEqual(gdb_repr, exp_repr,
# which happens on deletion:
gdb_repr, gdb_output = self.get_gdb_repr('''s = set(['a','b'])
s.remove('a')
-_idfunc(s)''')
+id(s)''')
self.assertEqual(gdb_repr, "{'b'}")
@support.requires_resource('cpu')
try:
raise RuntimeError("I am an error")
except RuntimeError as e:
- _idfunc(e)
+ id(e)
''')
self.assertEqual(gdb_repr,
"RuntimeError('I am an error',)")
try:
a = 1 / 0
except ZeroDivisionError as e:
- _idfunc(e)
+ id(e)
''')
self.assertEqual(gdb_repr,
"ZeroDivisionError('division by zero',)")
pass
foo = Foo()
foo.an_int = 42
-_idfunc(foo)''')
+id(foo)''')
m = re.match(r'<Foo\(an_int=42\) at remote 0x-?[0-9a-f]+>', gdb_repr)
self.assertTrue(m,
msg='Unexpected new-style class rendering %r' % gdb_repr)
foo = Foo()
foo += [1, 2, 3]
foo.an_int = 42
-_idfunc(foo)''')
+id(foo)''')
m = re.match(r'<Foo\(an_int=42\) at remote 0x-?[0-9a-f]+>', gdb_repr)
self.assertTrue(m,
pass
foo = Foo((1, 2, 3))
foo.an_int = 42
-_idfunc(foo)''')
+id(foo)''')
m = re.match(r'<Foo\(an_int=42\) at remote 0x-?[0-9a-f]+>', gdb_repr)
self.assertTrue(m,
def test_NULL_ptr(self):
'Ensure that a NULL PyObject* is handled gracefully'
gdb_repr, gdb_output = (
- self.get_gdb_repr('_idfunc(42)',
- cmds_after_breakpoint=['set variable x=0',
+ self.get_gdb_repr('id(42)',
+ cmds_after_breakpoint=['set variable v=0',
'backtrace'])
)
def test_NULL_ob_type(self):
'Ensure that a PyObject* with NULL ob_type is handled gracefully'
- self.assertSane('_idfunc(42)',
- 'set x->ob_type=0')
+ self.assertSane('id(42)',
+ 'set v->ob_type=0')
def test_corrupt_ob_type(self):
'Ensure that a PyObject* with a corrupt ob_type is handled gracefully'
- self.assertSane('_idfunc(42)',
- 'set x->ob_type=0xDEADBEEF',
+ self.assertSane('id(42)',
+ 'set v->ob_type=0xDEADBEEF',
exprepr='42')
def test_corrupt_tp_flags(self):
'Ensure that a PyObject* with a type with corrupt tp_flags is handled'
- self.assertSane('_idfunc(42)',
- 'set x->ob_type->tp_flags=0x0',
+ self.assertSane('id(42)',
+ 'set v->ob_type->tp_flags=0x0',
exprepr='42')
def test_corrupt_tp_name(self):
'Ensure that a PyObject* with a type with corrupt tp_name is handled'
- self.assertSane('_idfunc(42)',
- 'set x->ob_type->tp_name=0xDEADBEEF',
+ self.assertSane('id(42)',
+ 'set v->ob_type->tp_name=0xDEADBEEF',
exprepr='42')
def test_builtins_help(self):
# (this was the issue causing tracebacks in
# http://bugs.python.org/issue8032#msg100537 )
- gdb_repr, gdb_output = self.get_gdb_repr('_idfunc(__builtins__.help)', import_site=True)
+ gdb_repr, gdb_output = self.get_gdb_repr('id(__builtins__.help)', import_site=True)
m = re.match(r'<_Helper\(\) at remote 0x-?[0-9a-f]+>', gdb_repr)
self.assertTrue(m,
'''Ensure that a reference loop involving a list doesn't lead proxyval
into an infinite loop:'''
gdb_repr, gdb_output = \
- self.get_gdb_repr("a = [3, 4, 5] ; a.append(a) ; _idfunc(a)")
+ self.get_gdb_repr("a = [3, 4, 5] ; a.append(a) ; id(a)")
self.assertEqual(gdb_repr, '[3, 4, 5, [...]]')
gdb_repr, gdb_output = \
- self.get_gdb_repr("a = [3, 4, 5] ; b = [a] ; a.append(b) ; _idfunc(a)")
+ self.get_gdb_repr("a = [3, 4, 5] ; b = [a] ; a.append(b) ; id(a)")
self.assertEqual(gdb_repr, '[3, 4, 5, [[...]]]')
def test_selfreferential_dict(self):
'''Ensure that a reference loop involving a dict doesn't lead proxyval
into an infinite loop:'''
gdb_repr, gdb_output = \
- self.get_gdb_repr("a = {} ; b = {'bar':a} ; a['foo'] = b ; _idfunc(a)")
+ self.get_gdb_repr("a = {} ; b = {'bar':a} ; a['foo'] = b ; id(a)")
self.assertEqual(gdb_repr, "{'foo': {'bar': {...}}}")
pass
foo = Foo()
foo.an_attr = foo
-_idfunc(foo)''')
+id(foo)''')
self.assertTrue(re.match(r'<Foo\(an_attr=<\.\.\.>\) at remote 0x-?[0-9a-f]+>',
gdb_repr),
'Unexpected gdb representation: %r\n%s' % \
pass
foo = Foo()
foo.an_attr = foo
-_idfunc(foo)''')
+id(foo)''')
self.assertTrue(re.match(r'<Foo\(an_attr=<\.\.\.>\) at remote 0x-?[0-9a-f]+>',
gdb_repr),
'Unexpected gdb representation: %r\n%s' % \
b = Foo()
a.an_attr = b
b.an_attr = a
-_idfunc(a)''')
+id(a)''')
self.assertTrue(re.match(r'<Foo\(an_attr=<Foo\(an_attr=<\.\.\.>\) at remote 0x-?[0-9a-f]+>\) at remote 0x-?[0-9a-f]+>',
gdb_repr),
'Unexpected gdb representation: %r\n%s' % \
def test_truncation(self):
'Verify that very long output is truncated'
- gdb_repr, gdb_output = self.get_gdb_repr('_idfunc(list(range(1000)))')
+ gdb_repr, gdb_output = self.get_gdb_repr('id(list(range(1000)))')
self.assertEqual(gdb_repr,
"[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, "
"14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, "
1024 + len('...(truncated)'))
def test_builtin_method(self):
- gdb_repr, gdb_output = self.get_gdb_repr('import sys; _idfunc(sys.stdout.readlines)')
+ gdb_repr, gdb_output = self.get_gdb_repr('import sys; id(sys.stdout.readlines)')
self.assertTrue(re.match(r'<built-in method readlines of _io.TextIOWrapper object at remote 0x-?[0-9a-f]+>',
gdb_repr),
'Unexpected gdb representation: %r\n%s' % \
def test_frames(self):
gdb_output = self.get_stack_trace('''
import sys
-from _typing import _idfunc
def foo(a, b, c):
return sys._getframe(0)
f = foo(3, 4, 5)
-_idfunc(f)''',
- breakpoint='_typing__idfunc',
- cmds_after_breakpoint=['print (PyFrameObject*)x']
+id(f)''',
+ breakpoint='builtin_id',
+ cmds_after_breakpoint=['print (PyFrameObject*)v']
)
- self.assertTrue(re.match(r'.*\s+\$1 =\s+Frame 0x-?[0-9a-f]+, for file <string>, line 5, in foo \(a=3.*',
+ self.assertTrue(re.match(r'.*\s+\$1 =\s+Frame 0x-?[0-9a-f]+, for file <string>, line 4, in foo \(a=3.*',
gdb_output,
re.DOTALL),
'Unexpected gdb representation: %r\n%s' % (gdb_output, gdb_output))