Skip to content

Commit 949e922

Browse files
committed
pdb: Initial micropython support.
1 parent b15b1e0 commit 949e922

File tree

1 file changed

+62
-46
lines changed

1 file changed

+62
-46
lines changed

python-stdlib/pdb/pdb.py

Lines changed: 62 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -66,25 +66,28 @@
6666
"""
6767
# NOTE: the actual command documentation is collected from docstrings of the
6868
# commands and is appended to __doc__ after the class has been defined.
69-
69+
import builtins as __builtins__
7070
import os
7171
import io
7272
import re
7373
import sys
7474
import cmd
7575
import bdb
76-
import dis
76+
# import dis # MPY: dis not currently available
7777
import code
7878
import glob
7979
import pprint
80-
import signal
81-
import inspect
80+
# import signal # MPY: signal not currently available
81+
# import inspect # MPY: inspect not currently available
8282
import tokenize
83-
import functools
83+
# import functools
8484
import traceback
8585
import linecache
8686

87-
from typing import Union
87+
try:
88+
from typing import Union
89+
except ImportError:
90+
pass
8891

8992

9093
class Restart(Exception):
@@ -104,7 +107,9 @@ def find_function(funcname, filename):
104107
with fp:
105108
for lineno, line in enumerate(fp, start=1):
106109
if cre.match(line):
107-
return funcname, filename, lineno
110+
## MPY: increment line number by 1 as we want to break on the
111+
# first line of the function, not the function def line itself
112+
return funcname, filename, lineno + 1
108113
return None
109114

110115
def getsourcelines(obj):
@@ -117,11 +122,12 @@ def getsourcelines(obj):
117122
return inspect.getblock(lines[lineno:]), lineno+1
118123

119124
def lasti2lineno(code, lasti):
120-
linestarts = list(dis.findlinestarts(code))
121-
linestarts.reverse()
122-
for i, lineno in linestarts:
123-
if lasti >= i:
124-
return lineno
125+
## MPY: dis not currently available
126+
# linestarts = list(dis.findlinestarts(code))
127+
# linestarts.reverse()
128+
# for i, lineno in linestarts:
129+
# if lasti >= i:
130+
# return lineno
125131
return 0
126132

127133

@@ -131,40 +137,39 @@ def __repr__(self):
131137
return self
132138

133139

134-
class ScriptTarget(str):
135-
def __new__(cls, val):
140+
class ScriptTarget:
141+
def __init__(self, val):
136142
# Mutate self to be the "real path".
137-
res = super().__new__(cls, os.path.realpath(val))
143+
self.path = os.path.realpath(val)
138144

139145
# Store the original path for error reporting.
140-
res.orig = val
141-
142-
return res
146+
self.orig = val
143147

144148
def check(self):
145-
if not os.path.exists(self):
149+
if not os.path.exists(self.path):
146150
print('Error:', self.orig, 'does not exist')
147151
sys.exit(1)
148152

149153
# Replace pdb's dir with script's dir in front of module search path.
150-
sys.path[0] = os.path.dirname(self)
154+
sys.path[0] = os.path.dirname(self.path)
151155

152156
@property
153157
def filename(self):
154-
return self
158+
return self.path
155159

156160
@property
157161
def namespace(self):
158162
return dict(
159163
__name__='__main__',
160-
__file__=self,
164+
__file__=self.path,
161165
__builtins__=__builtins__,
162166
)
163167

164168
@property
165169
def code(self):
166-
with io.open(self) as fp:
167-
return f"exec(compile({fp.read()!r}, {self!r}, 'exec'))"
170+
with io.open(self.path) as fp:
171+
## MPY: f-string !r syntax not supported
172+
return f"exec(compile({repr(fp.read())}, {repr(self.path)}, 'exec'))"
168173

169174

170175
class ModuleTarget(str):
@@ -175,7 +180,7 @@ def check(self):
175180
traceback.print_exc()
176181
sys.exit(1)
177182

178-
@functools.cached_property
183+
# @functools.cached_property
179184
def _details(self):
180185
import runpy
181186
return runpy._get_module_details(self)
@@ -219,9 +224,9 @@ class Pdb(bdb.Bdb, cmd.Cmd):
219224

220225
def __init__(self, completekey='tab', stdin=None, stdout=None, skip=None,
221226
nosigint=False, readrc=True):
222-
bdb.Bdb.__init__(self, skip=skip)
227+
bdb.Bdb.__init__(self, skip)
223228
cmd.Cmd.__init__(self, completekey, stdin, stdout)
224-
sys.audit("pdb.Pdb")
229+
# sys.audit("pdb.Pdb")
225230
if stdout:
226231
self.use_rawinput = 0
227232
self.prompt = '(Pdb) '
@@ -422,7 +427,7 @@ def interaction(self, frame, traceback):
422427
if Pdb._previous_sigint_handler:
423428
try:
424429
signal.signal(signal.SIGINT, Pdb._previous_sigint_handler)
425-
except ValueError: # ValueError: signal only works in main thread
430+
except (ValueError, NameError): # ValueError: signal only works in main thread
426431
pass
427432
else:
428433
Pdb._previous_sigint_handler = None
@@ -573,7 +578,9 @@ def _complete_expression(self, text, line, begidx, endidx):
573578
# Collect globals and locals. It is usually not really sensible to also
574579
# complete builtins, and they clutter the namespace quite heavily, so we
575580
# leave them out.
576-
ns = {**self.curframe.f_globals, **self.curframe_locals}
581+
ns = {}
582+
ns.update(self.curframe.f_globals)
583+
ns.update(self.curframe_locals)
577584
if '.' in text:
578585
# Walk an attribute chain up to the last part, similar to what
579586
# rlcompleter does. This will bail if any of the parts are not
@@ -1137,7 +1144,7 @@ def do_continue(self, arg):
11371144
try:
11381145
Pdb._previous_sigint_handler = \
11391146
signal.signal(signal.SIGINT, self.sigint_handler)
1140-
except ValueError:
1147+
except (ValueError, NameError):
11411148
# ValueError happens when do_continue() is invoked from
11421149
# a non-main thread in which case we just continue without
11431150
# SIGINT set. Would printing a message here (once) make
@@ -1475,7 +1482,9 @@ def do_interact(self, arg):
14751482
Start an interactive interpreter whose global namespace
14761483
contains all the (global and local) names found in the current scope.
14771484
"""
1478-
ns = {**self.curframe.f_globals, **self.curframe_locals}
1485+
ns = {}
1486+
ns.update(self.curframe.f_globals)
1487+
ns.update(self.curframe_locals)
14791488
code.interact("*interactive*", local=ns)
14801489

14811490
def do_alias(self, arg):
@@ -1640,29 +1649,34 @@ def _run(self, target: Union[ModuleTarget, ScriptTarget]):
16401649
# __main__ will break). Clear __main__ and replace with
16411650
# the target namespace.
16421651
import __main__
1652+
try:
1653+
__main__.__dict__
1654+
except AttributeError:
1655+
__main__.__dict__ = dict()
16431656
__main__.__dict__.clear()
16441657
__main__.__dict__.update(target.namespace)
1658+
16451659

16461660
self.run(target.code)
16471661

16481662

16491663
# Collect all command help into docstring, if not run with -OO
1664+
## MPY: NameError: name '__doc__' isn't defined
1665+
# if __doc__ is not None:
1666+
# # unfortunately we can't guess this order from the class definition
1667+
# _help_order = [
1668+
# 'help', 'where', 'down', 'up', 'break', 'tbreak', 'clear', 'disable',
1669+
# 'enable', 'ignore', 'condition', 'commands', 'step', 'next', 'until',
1670+
# 'jump', 'return', 'retval', 'run', 'continue', 'list', 'longlist',
1671+
# 'args', 'p', 'pp', 'whatis', 'source', 'display', 'undisplay',
1672+
# 'interact', 'alias', 'unalias', 'debug', 'quit',
1673+
# ]
16501674

1651-
if __doc__ is not None:
1652-
# unfortunately we can't guess this order from the class definition
1653-
_help_order = [
1654-
'help', 'where', 'down', 'up', 'break', 'tbreak', 'clear', 'disable',
1655-
'enable', 'ignore', 'condition', 'commands', 'step', 'next', 'until',
1656-
'jump', 'return', 'retval', 'run', 'continue', 'list', 'longlist',
1657-
'args', 'p', 'pp', 'whatis', 'source', 'display', 'undisplay',
1658-
'interact', 'alias', 'unalias', 'debug', 'quit',
1659-
]
1660-
1661-
for _command in _help_order:
1662-
__doc__ += getattr(Pdb, 'do_' + _command).__doc__.strip() + '\n\n'
1663-
__doc__ += Pdb.help_exec.__doc__
1675+
# for _command in _help_order:
1676+
# __doc__ += getattr(Pdb, 'do_' + _command).__doc__.strip() + '\n\n'
1677+
# __doc__ += Pdb.help_exec.__doc__
16641678

1665-
del _help_order, _command
1679+
# del _help_order, _command
16661680

16671681

16681682
# Simplified interface
@@ -1781,9 +1795,11 @@ def main():
17811795
sys.exit(1)
17821796
except:
17831797
traceback.print_exc()
1798+
t = sys.exc_info()[2]
1799+
if t is None:
1800+
break
17841801
print("Uncaught exception. Entering post mortem debugging")
17851802
print("Running 'cont' or 'step' will restart the program")
1786-
t = sys.exc_info()[2]
17871803
pdb.interaction(None, t)
17881804
print("Post mortem debugger finished. The " + target +
17891805
" will be restarted")

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