8282import signal
8383import inspect
8484import tokenize
85- import functools
8685import traceback
8786import linecache
8887
8988from contextlib import contextmanager
9089from rlcompleter import Completer
91- from typing import Union
90+ from types import CodeType
9291
9392
9493class Restart (Exception ):
@@ -156,77 +155,75 @@ def __repr__(self):
156155 return self
157156
158157
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
163162
164- # Store the original path for error reporting.
165- res .orig = val
166163
167- return res
164+ class _ScriptTarget (_ExecutableTarget ):
165+ def __init__ (self , target ):
166+ self ._target = os .path .realpath (target )
168167
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' )
172170 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' )
175173 sys .exit (1 )
176174
177175 # If safe_path(-P) is not set, sys.path[0] is the directory
178176 # of pdb, and we should replace it with the directory of the script
179177 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
181182
182183 @property
183184 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'))"
185192
186193 @property
187194 def namespace (self ):
188195 return dict (
189196 __name__ = '__main__' ,
190- __file__ = self ,
197+ __file__ = self . _target ,
191198 __builtins__ = __builtins__ ,
192199 __spec__ = None ,
193200 )
194201
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'))"
199202
203+ class _ModuleTarget (_ExecutableTarget ):
204+ def __init__ (self , target ):
205+ self ._target = target
200206
201- class _ModuleTarget (str ):
202- def check (self ):
207+ import runpy
203208 try :
204- self ._details
209+ _ , self ._spec , self . _code = runpy . _get_module_details ( self . _target )
205210 except ImportError as e :
206211 print (f"ImportError: { e } " )
207212 sys .exit (1 )
208213 except Exception :
209214 traceback .print_exc ()
210215 sys .exit (1 )
211216
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
216219
217220 @property
218221 def filename (self ):
219- return self .code .co_filename
222+ return self ._code .co_filename
220223
221224 @property
222225 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
230227
231228 @property
232229 def namespace (self ):
@@ -2029,7 +2026,7 @@ def lookupmodule(self, filename):
20292026 return fullname
20302027 return None
20312028
2032- def _run (self , target : Union [ _ModuleTarget , _ScriptTarget ] ):
2029+ def _run (self , target : _ExecutableTarget ):
20332030 # When bdb sets tracing, a number of call and line events happen
20342031 # BEFORE debugger even reaches user's code (and the exact sequence of
20352032 # events depends on python version). Take special measures to
@@ -2281,8 +2278,6 @@ def main():
22812278 file = opts .args .pop (0 )
22822279 target = _ScriptTarget (file )
22832280
2284- target .check ()
2285-
22862281 sys .argv [:] = [file ] + opts .args # Hide "pdb.py" and pdb options from argument list
22872282
22882283 # Note on saving/restoring sys.argv: it's a good idea when sys.argv was
@@ -2306,8 +2301,8 @@ def main():
23062301 print ("Uncaught exception. Entering post mortem debugging" )
23072302 print ("Running 'cont' or 'step' will restart the program" )
23082303 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" )
23112306 if pdb ._user_requested_quit :
23122307 break
23132308 print ("The program finished and will be restarted" )
0 commit comments