@@ -1095,69 +1095,145 @@ def runScript(cmds=[], wait=False, G2frame=None):
10951095 sys .exit ()
10961096
10971097def IPyBreak_base (userMsg = None ):
1098- '''A routine that invokes an IPython session at the calling location
1098+ '''A routine that invokes an IPython session at the calling location.
1099+ Called by a call to :func:`IPyBreak` or command ``breakpoint()``.
10991100 This routine is only used when debug=True is set in the configuration
1100- settings
1101+ settings.
11011102 '''
11021103 savehook = sys .excepthook # save the exception hook
11031104 try :
1104- from IPython .terminal .embed import InteractiveShellEmbed
1105+ import IPython .core
1106+ # get the Ipython shell routine
1107+ if IPython .core .getipython .get_ipython () is None :
1108+ ipshell = IPython .terminal .embed .InteractiveShellEmbed .instance (banner1 = '' )
1109+ else : # older IPython (still needed?)
1110+ ipshell = IPython .terminal .embed .InteractiveShellEmbed ()
1111+ import inspect
11051112 except ImportError :
1106- try :
1107- # try the IPython 0.12 approach
1108- from IPython .frontend .terminal .embed import InteractiveShellEmbed
1109- except ImportError :
1110- print ('IPython InteractiveShellEmbed not found' )
1111- return
1112- import inspect
1113- #from IPython import __version__
1114- #if __version__.startswith('8.12.'): # see https://github.com/ipython/ipython/issues/13966
1115- from IPython .core import getipython
1116- if getipython .get_ipython () is None :
1117- ipshell = InteractiveShellEmbed .instance ()
1118- else :
1119- ipshell = InteractiveShellEmbed ()
1113+ return
1114+
1115+ stack = inspect .stack () # Get the full stack
1116+ current_level = [1 ] # mutable so inner function can modify it
1117+
1118+ def up (levels = 1 ):
1119+ '''Move the IPython shell environment up the call stack.
1120+ Initially coded by Claude Sonnet 4.5
1121+ '''
1122+ new_level = current_level [0 ] + levels
1123+ if new_level < len (stack ):
1124+ current_level [0 ] = new_level
1125+ frame = stack [current_level [0 ]].frame
1126+ print (f"Moving to: { stack [current_level [0 ]].filename } :{ stack [current_level [0 ]].lineno } in { stack [current_level [0 ]].function } " )
1127+ # Replace the IPython namespace (not update), but preserve IPython internals
1128+ # Save IPython internal variables and built-in commands
1129+ ipython_preserve = {k : v for k , v in ipshell .user_ns .items ()
1130+ if k .startswith ('_' ) or k in ('exit' , 'quit' , 'get_ipython' )}
1131+ ipshell .user_ns .clear ()
1132+ ipshell .user_ns .update (ipython_preserve ) # Restore IPython internals
1133+ ipshell .user_ns .update (frame .f_globals )
1134+ ipshell .user_ns .update (frame .f_locals )
1135+ ipshell .user_ns ['TB' ] = TB
1136+ ipshell .user_ns ['up' ] = up
1137+ ipshell .user_ns ['down' ] = down
1138+ ipshell .user_ns ['where' ] = where
1139+ else :
1140+ print (f"Already at top of stack (level { current_level [0 ]} of { len (stack )- 1 } )" )
1141+
1142+ def down (levels = 1 ):
1143+ '''Move the IPython shell environment down the call stack.
1144+ Initially coded by Claude Sonnet 4.5
1145+ '''
1146+ new_level = current_level [0 ] - levels
1147+ if new_level >= 0 :
1148+ current_level [0 ] = new_level
1149+ frame = stack [current_level [0 ]].frame
1150+ print (f"Moving to: { stack [current_level [0 ]].filename } :{ stack [current_level [0 ]].lineno } in { stack [current_level [0 ]].function } " )
1151+ # Replace the IPython namespace (not update), but preserve IPython internals
1152+ # Save IPython internal variables and built-in commands
1153+ ipython_preserve = {k : v for k , v in ipshell .user_ns .items ()
1154+ if k .startswith ('_' ) or k in ('exit' , 'quit' , 'get_ipython' )}
1155+ ipshell .user_ns .clear ()
1156+ ipshell .user_ns .update (ipython_preserve ) # Restore IPython internals
1157+ ipshell .user_ns .update (frame .f_globals )
1158+ ipshell .user_ns .update (frame .f_locals )
1159+ ipshell .user_ns ['TB' ] = TB
1160+ ipshell .user_ns ['up' ] = up
1161+ ipshell .user_ns ['down' ] = down
1162+ ipshell .user_ns ['where' ] = where
1163+ else :
1164+ print (f"Already at bottom of stack (level 0)" )
1165+
1166+ def where ():
1167+ '''Show current position in stack related to up/down commands.
1168+ Initially coded by Claude Sonnet 4.5 & revised to reverse display order.
1169+ '''
1170+ i = len (stack )
1171+ for frame_info in reversed (stack ):
1172+ i -= 1
1173+ marker = ">>>" if i == current_level [0 ] else " "
1174+ print (f"{ marker } [{ i } ] { frame_info .filename } :{ frame_info .lineno } in { frame_info .function } " )
1175+
1176+ def TB (depth = None ):
1177+ '''Show a traceback (to the optional specified depth) to how we got to
1178+ the breakpoint. Omit the current level as the calling level to here
1179+ and above is likely all that we would be interested in.
1180+ '''
1181+ if depth is not None : depth += 1
1182+ for frame_info in reversed (stack [1 :depth ]):
1183+ print (f' File "{ frame_info .filename } ", line { frame_info .lineno } , in { frame_info .function } ' )
1184+ if frame_info .code_context :
1185+ print (f' { frame_info .code_context [0 ].strip ()} ' )
11201186
11211187 frame = inspect .currentframe ().f_back
11221188 msg = 'Entering IPython console inside {0.f_code.co_filename} at line {0.f_lineno}\n ' .format (frame )
1189+ msg += '\n [up()/down()/where() to navigate stack; TB()/TB(n) for n level tracebacks]'
11231190 if userMsg : msg += userMsg
1191+
1192+ # Add commands to shell namespace
1193+ locals = frame .f_locals
1194+ locals ['TB' ] = TB
1195+ locals ['up' ] = up
1196+ locals ['down' ] = down
1197+ locals ['where' ] = where
1198+
11241199 # globals().update(locals()) # This might help with vars inside list comprehensions, etc.
1125- ipshell (msg ,stack_depth = 2 ) # Go up one level, to see the calling routine
1200+ ipshell (msg ,stack_depth = 2 , local_ns = locals , global_ns = frame . f_globals )
11261201 sys .excepthook = savehook # reset IPython's change to the exception hook
11271202
11281203def exceptHook (* args ):
11291204 '''A routine to be called when an exception occurs. It prints the traceback
11301205 with fancy formatting and then calls an IPython shell with the environment
11311206 of the exception location.
11321207
1133- This routine is only used when debug=True is set in the configuration settings
1208+ This routine is only used when debug=True is set in the configuration
1209+ settings.
11341210 '''
11351211 import IPython .core
11361212 savehook = sys .excepthook # save the exception hook
11371213 # show the error location
1138- tb_formatter = IPython .core .ultratb .FormattedTB ()
1139- #tb_formatter = IPython.core.ultratb.ListTB() # better for windows?
1140- print () # blank line
1214+ if sys .platform == "win32" :
1215+ tb_formatter = IPython .core .ultratb .ListTB () # better for windows?
1216+ else :
1217+ tb_formatter = IPython .core .ultratb .FormattedTB ()
11411218 print (tb_formatter .text (* args ,- 1 ),end = '' ) # show only last routine
11421219 # get the Ipython shell routine
11431220 if IPython .core .getipython .get_ipython () is None :
11441221 ipshell = IPython .terminal .embed .InteractiveShellEmbed .instance (banner1 = '' )
11451222 else : # older IPython (still needed?)
11461223 ipshell = IPython .terminal .embed .InteractiveShellEmbed ()
11471224 # traceback display routines
1148- def TB (): print (IPython .core .ultratb .FormattedTB ().text (* args ))
1149- def vTB (): print (IPython .core .ultratb .VerboseTB ().text (* args ))
1150- def bwTB (): print (IPython .core .ultratb .ListTB ().text (* args )) # uncolored
1225+ def TB (depth = None ): print (IPython .core .ultratb .FormattedTB ().text (* args , depth ))
1226+ def vTB (depth = - 1 ): print (IPython .core .ultratb .VerboseTB ().text (* args , depth ))
1227+ def bwTB (depth = None ): print (IPython .core .ultratb .ListTB ().text (* args , depth )) # uncolored
11511228 try : # get to the right frame
11521229 import inspect
11531230 frame = inspect .getinnerframes (args [2 ])[- 1 ][0 ]
1154- import copy
11551231 locals = frame .f_locals # add traceback commands to shell namespace
11561232 locals ['TB' ] = TB
11571233 locals ['vTB' ] = vTB
11581234 locals ['bwTB' ] = bwTB
11591235 msg = f'IPython console: { frame .f_code .co_filename } , line { frame .f_lineno } '
1160- msg += '\n [TB(), vTB() & bwTB() for tracebacks]'
1236+ msg += '\n [TB()/TB(-n) , vTB()/vTB(-n)/vTB(0) & bwTB() for tracebacks to n levels back ]'
11611237 ipshell (msg ,local_ns = locals ,global_ns = frame .f_globals )
11621238 except :
11631239 msg = 'Entering IPython console (not in error contex)'
@@ -1854,16 +1930,6 @@ def postURL(URL,postdict,getcookie=None,usecookie=None,
18541930 if r .status_code == 200 :
18551931 if GetConfigValue ('debug' ): print ('request OK' )
18561932 page = r .text
1857- if 'cryst.ehu.es' in URL and "currently down" in page :
1858- # Bilbao is down. Tell user
1859- import re
1860- print (f"Website down? See message below:\n \n { re .sub ('<.+>' ,'' ,page )} " )
1861- try :
1862- import wx
1863- import GSASII .GSASIIctrlGUI as G2G
1864- dlg = G2G .viewWebPage (wx .GetApp ().GetMainTopWindow (),URL ,HTML = page )
1865- except :
1866- pass
18671933 if getcookie is not None :
18681934 getcookie .update (r .cookies )
18691935 return page # success
0 commit comments