Skip to content

Commit 5c351fc

Browse files
gh-112343: pdb: Use tokenize to replace convenience variables (#112380)
1 parent f497525 commit 5c351fc

File tree

3 files changed

+45
-1
lines changed

3 files changed

+45
-1
lines changed

Lib/pdb.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
import dis
7777
import code
7878
import glob
79+
import token
7980
import codeop
8081
import pprint
8182
import signal
@@ -601,6 +602,39 @@ def default(self, line):
601602
except:
602603
self._error_exc()
603604

605+
def _replace_convenience_variables(self, line):
606+
"""Replace the convenience variables in 'line' with their values.
607+
e.g. $foo is replaced by __pdb_convenience_variables["foo"].
608+
Note: such pattern in string literals will be skipped"""
609+
610+
if "$" not in line:
611+
return line
612+
613+
dollar_start = dollar_end = -1
614+
replace_variables = []
615+
try:
616+
for t in tokenize.generate_tokens(io.StringIO(line).readline):
617+
token_type, token_string, start, end, _ = t
618+
if token_type == token.OP and token_string == '$':
619+
dollar_start, dollar_end = start, end
620+
elif start == dollar_end and token_type == token.NAME:
621+
# line is a one-line command so we only care about column
622+
replace_variables.append((dollar_start[1], end[1], token_string))
623+
except tokenize.TokenError:
624+
return line
625+
626+
if not replace_variables:
627+
return line
628+
629+
last_end = 0
630+
line_pieces = []
631+
for start, end, name in replace_variables:
632+
line_pieces.append(line[last_end:start] + f'__pdb_convenience_variables["{name}"]')
633+
last_end = end
634+
line_pieces.append(line[last_end:])
635+
636+
return ''.join(line_pieces)
637+
604638
def precmd(self, line):
605639
"""Handle alias expansion and ';;' separator."""
606640
if not line.strip():
@@ -635,7 +669,7 @@ def precmd(self, line):
635669
line = line[:marker].rstrip()
636670

637671
# Replace all the convenience variables
638-
line = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'__pdb_convenience_variables["\1"]', line)
672+
line = self._replace_convenience_variables(line)
639673

640674
return line
641675

Lib/test/test_pdb.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,9 +847,12 @@ def test_convenience_variables():
847847
848848
>>> with PdbTestInput([ # doctest: +ELLIPSIS, +NORMALIZE_WHITESPACE
849849
... '$_frame.f_lineno', # Check frame convenience variable
850+
... '$ _frame', # This should be a syntax error
850851
... '$a = 10', # Set a convenience variable
851852
... '$a', # Print its value
853+
... 'p "$a"', # Print the string $a
852854
... 'p $a + 2', # Do some calculation
855+
... 'p f"$a = {$a}"', # Make sure $ in string is not converted and f-string works
853856
... 'u', # Switch frame
854857
... '$_frame.f_lineno', # Make sure the frame changed
855858
... '$a', # Make sure the value persists
@@ -869,11 +872,17 @@ def test_convenience_variables():
869872
-> try:
870873
(Pdb) $_frame.f_lineno
871874
3
875+
(Pdb) $ _frame
876+
*** SyntaxError: invalid syntax
872877
(Pdb) $a = 10
873878
(Pdb) $a
874879
10
880+
(Pdb) p "$a"
881+
'$a'
875882
(Pdb) p $a + 2
876883
12
884+
(Pdb) p f"$a = {$a}"
885+
'$a = 10'
877886
(Pdb) u
878887
> <doctest test.test_pdb.test_convenience_variables[1]>(2)test_function()
879888
-> util_function()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Improve handling of pdb convenience variables to avoid replacing string contents.

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy