82
82
import signal
83
83
import inspect
84
84
import tokenize
85
- import functools
86
85
import traceback
87
86
import linecache
88
87
89
88
from contextlib import contextmanager
90
89
from rlcompleter import Completer
91
- from typing import Union
90
+ from types import CodeType
92
91
93
92
94
93
class Restart (Exception ):
@@ -156,77 +155,75 @@ def __repr__(self):
156
155
return self
157
156
158
157
159
- class _ScriptTarget ( str ) :
160
- def __new__ ( cls , val ):
161
- # Mutate self to be the "real path".
162
- res = super (). __new__ ( cls , os . path . realpath ( val ))
158
+ class _ExecutableTarget :
159
+ filename : str
160
+ code : CodeType | str
161
+ namespace : dict
163
162
164
- # Store the original path for error reporting.
165
- res .orig = val
166
163
167
- return res
164
+ class _ScriptTarget (_ExecutableTarget ):
165
+ def __init__ (self , target ):
166
+ self ._target = os .path .realpath (target )
168
167
169
- def check (self ):
170
- if not os .path .exists (self ):
171
- print ('Error:' , self .orig , 'does not exist' )
168
+ if not os .path .exists (self ._target ):
169
+ print (f'Error: { target } does not exist' )
172
170
sys .exit (1 )
173
- if os .path .isdir (self ):
174
- print ('Error:' , self . orig , ' is a directory' )
171
+ if os .path .isdir (self . _target ):
172
+ print (f 'Error: { target } is a directory' )
175
173
sys .exit (1 )
176
174
177
175
# If safe_path(-P) is not set, sys.path[0] is the directory
178
176
# of pdb, and we should replace it with the directory of the script
179
177
if not sys .flags .safe_path :
180
- sys .path [0 ] = os .path .dirname (self )
178
+ sys .path [0 ] = os .path .dirname (self ._target )
179
+
180
+ def __repr__ (self ):
181
+ return self ._target
181
182
182
183
@property
183
184
def filename (self ):
184
- return self
185
+ return self ._target
186
+
187
+ @property
188
+ def code (self ):
189
+ # Open the file each time because the file may be modified
190
+ with io .open_code (self ._target ) as fp :
191
+ return f"exec(compile({ fp .read ()!r} , { self ._target !r} , 'exec'))"
185
192
186
193
@property
187
194
def namespace (self ):
188
195
return dict (
189
196
__name__ = '__main__' ,
190
- __file__ = self ,
197
+ __file__ = self . _target ,
191
198
__builtins__ = __builtins__ ,
192
199
__spec__ = None ,
193
200
)
194
201
195
- @property
196
- def code (self ):
197
- with io .open_code (self ) as fp :
198
- return f"exec(compile({ fp .read ()!r} , { self !r} , 'exec'))"
199
202
203
+ class _ModuleTarget (_ExecutableTarget ):
204
+ def __init__ (self , target ):
205
+ self ._target = target
200
206
201
- class _ModuleTarget (str ):
202
- def check (self ):
207
+ import runpy
203
208
try :
204
- self ._details
209
+ _ , self ._spec , self . _code = runpy . _get_module_details ( self . _target )
205
210
except ImportError as e :
206
211
print (f"ImportError: { e } " )
207
212
sys .exit (1 )
208
213
except Exception :
209
214
traceback .print_exc ()
210
215
sys .exit (1 )
211
216
212
- @functools .cached_property
213
- def _details (self ):
214
- import runpy
215
- return runpy ._get_module_details (self )
217
+ def __repr__ (self ):
218
+ return self ._target
216
219
217
220
@property
218
221
def filename (self ):
219
- return self .code .co_filename
222
+ return self ._code .co_filename
220
223
221
224
@property
222
225
def code (self ):
223
- name , spec , code = self ._details
224
- return code
225
-
226
- @property
227
- def _spec (self ):
228
- name , spec , code = self ._details
229
- return spec
226
+ return self ._code
230
227
231
228
@property
232
229
def namespace (self ):
@@ -2029,7 +2026,7 @@ def lookupmodule(self, filename):
2029
2026
return fullname
2030
2027
return None
2031
2028
2032
- def _run (self , target : Union [ _ModuleTarget , _ScriptTarget ] ):
2029
+ def _run (self , target : _ExecutableTarget ):
2033
2030
# When bdb sets tracing, a number of call and line events happen
2034
2031
# BEFORE debugger even reaches user's code (and the exact sequence of
2035
2032
# events depends on python version). Take special measures to
@@ -2281,8 +2278,6 @@ def main():
2281
2278
file = opts .args .pop (0 )
2282
2279
target = _ScriptTarget (file )
2283
2280
2284
- target .check ()
2285
-
2286
2281
sys .argv [:] = [file ] + opts .args # Hide "pdb.py" and pdb options from argument list
2287
2282
2288
2283
# Note on saving/restoring sys.argv: it's a good idea when sys.argv was
@@ -2306,8 +2301,8 @@ def main():
2306
2301
print ("Uncaught exception. Entering post mortem debugging" )
2307
2302
print ("Running 'cont' or 'step' will restart the program" )
2308
2303
pdb .interaction (None , e )
2309
- print ("Post mortem debugger finished. The " + target +
2310
- " will be restarted" )
2304
+ print (f "Post mortem debugger finished. The { target } will "
2305
+ "be restarted" )
2311
2306
if pdb ._user_requested_quit :
2312
2307
break
2313
2308
print ("The program finished and will be restarted" )
0 commit comments