Skip to content

Commit 9c68dfb

Browse files
authored
Merge branch 'python:main' into main
2 parents 6c531e2 + 2b4feee commit 9c68dfb

File tree

8 files changed

+65
-31
lines changed

8 files changed

+65
-31
lines changed

Doc/library/pdb.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -520,7 +520,8 @@ can be overridden by the local file.
520520
To remove all commands from a breakpoint, type ``commands`` and follow it
521521
immediately with ``end``; that is, give no commands.
522522

523-
With no *bpnumber* argument, ``commands`` refers to the last breakpoint set.
523+
With no *bpnumber* argument, ``commands`` refers to the most recently set
524+
breakpoint that still exists.
524525

525526
You can use breakpoint commands to start your program up again. Simply use
526527
the :pdbcmd:`continue` command, or :pdbcmd:`step`,

Include/internal/pycore_parser.h

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,8 @@ extern "C" {
1414
#include "pycore_pyarena.h" // PyArena
1515

1616
_Py_DECLARE_STR(empty, "")
17-
#if defined(Py_DEBUG) && defined(Py_GIL_DISABLED)
1817
#define _parser_runtime_state_INIT \
1918
{ \
20-
.mutex = {0}, \
2119
.dummy_name = { \
2220
.kind = Name_kind, \
2321
.v.Name.id = &_Py_STR(empty), \
@@ -28,20 +26,6 @@ _Py_DECLARE_STR(empty, "")
2826
.end_col_offset = 0, \
2927
}, \
3028
}
31-
#else
32-
#define _parser_runtime_state_INIT \
33-
{ \
34-
.dummy_name = { \
35-
.kind = Name_kind, \
36-
.v.Name.id = &_Py_STR(empty), \
37-
.v.Name.ctx = Load, \
38-
.lineno = 1, \
39-
.col_offset = 0, \
40-
.end_lineno = 1, \
41-
.end_col_offset = 0, \
42-
}, \
43-
}
44-
#endif
4529

4630
extern struct _mod* _PyParser_ASTFromString(
4731
const char *str,

Include/internal/pycore_runtime_structs.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,7 @@ struct _fileutils_state {
7777
struct _parser_runtime_state {
7878
#ifdef Py_DEBUG
7979
long memo_statistics[_PYPEGEN_NSTATISTICS];
80-
#ifdef Py_GIL_DISABLED
8180
PyMutex mutex;
82-
#endif
8381
#else
8482
int _not_used;
8583
#endif

Lib/pdb.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1315,7 +1315,14 @@ def do_commands(self, arg):
13151315
reached.
13161316
"""
13171317
if not arg:
1318-
bnum = len(bdb.Breakpoint.bpbynumber) - 1
1318+
for bp in reversed(bdb.Breakpoint.bpbynumber):
1319+
if bp is None:
1320+
continue
1321+
bnum = bp.number
1322+
break
1323+
else:
1324+
self.error('cannot set commands: no existing breakpoint')
1325+
return
13191326
else:
13201327
try:
13211328
bnum = int(arg)

Lib/test/test_pdb.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3478,6 +3478,49 @@ def test_pdb_issue_gh_65052():
34783478
(Pdb) continue
34793479
"""
34803480

3481+
def test_pdb_commands_last_breakpoint():
3482+
"""See GH-142834
3483+
3484+
>>> def test_function():
3485+
... import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
3486+
... foo = 1
3487+
... bar = 2
3488+
3489+
>>> with PdbTestInput([ # doctest: +NORMALIZE_WHITESPACE
3490+
... 'break 4',
3491+
... 'break 3',
3492+
... 'clear 2',
3493+
... 'commands',
3494+
... 'p "success"',
3495+
... 'end',
3496+
... 'continue',
3497+
... 'clear 1',
3498+
... 'commands',
3499+
... 'continue',
3500+
... ]):
3501+
... test_function()
3502+
> <doctest test.test_pdb.test_pdb_commands_last_breakpoint[0]>(2)test_function()
3503+
-> import pdb; pdb.Pdb(nosigint=True, readrc=False).set_trace()
3504+
(Pdb) break 4
3505+
Breakpoint 1 at <doctest test.test_pdb.test_pdb_commands_last_breakpoint[0]>:4
3506+
(Pdb) break 3
3507+
Breakpoint 2 at <doctest test.test_pdb.test_pdb_commands_last_breakpoint[0]>:3
3508+
(Pdb) clear 2
3509+
Deleted breakpoint 2 at <doctest test.test_pdb.test_pdb_commands_last_breakpoint[0]>:3
3510+
(Pdb) commands
3511+
(com) p "success"
3512+
(com) end
3513+
(Pdb) continue
3514+
'success'
3515+
> <doctest test.test_pdb.test_pdb_commands_last_breakpoint[0]>(4)test_function()
3516+
-> bar = 2
3517+
(Pdb) clear 1
3518+
Deleted breakpoint 1 at <doctest test.test_pdb.test_pdb_commands_last_breakpoint[0]>:4
3519+
(Pdb) commands
3520+
*** cannot set commands: no existing breakpoint
3521+
(Pdb) continue
3522+
"""
3523+
34813524

34823525
@support.force_not_colorized_test_class
34833526
@support.requires_subprocess()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Change the :mod:`pdb` ``commands`` command to use the last available breakpoint instead of failing when the most recently created breakpoint was deleted.

Objects/genobject.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -422,7 +422,8 @@ gen_close(PyObject *self, PyObject *args)
422422
int8_t frame_state = FT_ATOMIC_LOAD_INT8_RELAXED(gen->gi_frame_state);
423423
do {
424424
if (frame_state == FRAME_CREATED) {
425-
if (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_CLEARED)) {
425+
// && (1) to avoid -Wunreachable-code warning on Clang
426+
if (!_Py_GEN_TRY_SET_FRAME_STATE(gen, frame_state, FRAME_CLEARED) && (1)) {
426427
continue;
427428
}
428429
gen_clear_frame(gen);

Parser/pegen.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
#include "pycore_pystate.h" // _PyThreadState_GET()
44
#include "pycore_parser.h" // _PYPEGEN_NSTATISTICS
55
#include "pycore_pyerrors.h" // PyExc_IncompleteInputError
6-
#include "pycore_runtime.h" // _PyRuntime
6+
#include "pycore_runtime.h" // _PyRuntime
77
#include "pycore_unicodeobject.h" // _PyUnicode_InternImmortal
8-
#include "pycore_pyatomic_ft_wrappers.h"
98
#include <errcode.h>
109

1110
#include "lexer/lexer.h"
@@ -303,11 +302,11 @@ _PyPegen_fill_token(Parser *p)
303302
void
304303
_PyPegen_clear_memo_statistics(void)
305304
{
306-
FT_MUTEX_LOCK(&_PyRuntime.parser.mutex);
305+
PyMutex_Lock(&_PyRuntime.parser.mutex);
307306
for (int i = 0; i < NSTATISTICS; i++) {
308307
memo_statistics[i] = 0;
309308
}
310-
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
309+
PyMutex_Unlock(&_PyRuntime.parser.mutex);
311310
}
312311

313312
PyObject *
@@ -318,22 +317,22 @@ _PyPegen_get_memo_statistics(void)
318317
return NULL;
319318
}
320319

321-
FT_MUTEX_LOCK(&_PyRuntime.parser.mutex);
320+
PyMutex_Lock(&_PyRuntime.parser.mutex);
322321
for (int i = 0; i < NSTATISTICS; i++) {
323322
PyObject *value = PyLong_FromLong(memo_statistics[i]);
324323
if (value == NULL) {
325-
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
324+
PyMutex_Unlock(&_PyRuntime.parser.mutex);
326325
Py_DECREF(ret);
327326
return NULL;
328327
}
329328
// PyList_SetItem borrows a reference to value.
330329
if (PyList_SetItem(ret, i, value) < 0) {
331-
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
330+
PyMutex_Unlock(&_PyRuntime.parser.mutex);
332331
Py_DECREF(ret);
333332
return NULL;
334333
}
335334
}
336-
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
335+
PyMutex_Unlock(&_PyRuntime.parser.mutex);
337336
return ret;
338337
}
339338
#endif
@@ -359,9 +358,9 @@ _PyPegen_is_memoized(Parser *p, int type, void *pres)
359358
if (count <= 0) {
360359
count = 1;
361360
}
362-
FT_MUTEX_LOCK(&_PyRuntime.parser.mutex);
361+
PyMutex_Lock(&_PyRuntime.parser.mutex);
363362
memo_statistics[type] += count;
364-
FT_MUTEX_UNLOCK(&_PyRuntime.parser.mutex);
363+
PyMutex_Unlock(&_PyRuntime.parser.mutex);
365364
}
366365
#endif
367366
p->mark = m->mark;

0 commit comments

Comments
 (0)