-
Notifications
You must be signed in to change notification settings - Fork 2
implemented debug() editor function which lets you navigate in the stack frame #192
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,8 +11,9 @@ | |
import larray as la | ||
|
||
from larray_editor.editor import REOPEN_LAST_FILE, MappingEditor, ArrayEditor | ||
from larray_editor.traceback_tools import extract_stack, extract_tb, StackSummary | ||
|
||
__all__ = ['view', 'edit', 'compare', 'REOPEN_LAST_FILE', 'run_editor_on_exception'] | ||
__all__ = ['view', 'edit', 'debug', 'compare', 'REOPEN_LAST_FILE', 'run_editor_on_exception'] | ||
|
||
|
||
def qapplication(): | ||
|
@@ -104,7 +105,10 @@ def edit(obj=None, title='', minvalue=None, maxvalue=None, readonly=False, depth | |
>>> # will open an editor for a1 only | ||
>>> edit(a1) # doctest: +SKIP | ||
""" | ||
install_except_hook() | ||
# we don't use install_except_hook/restore_except_hook so that we can restore the hook actually used when | ||
# this function is called instead of the one which was used when the module was loaded. | ||
orig_except_hook = sys.excepthook | ||
sys.excepthook = _qt_except_hook | ||
|
||
_app = QApplication.instance() | ||
if _app is None: | ||
|
@@ -147,7 +151,7 @@ def edit(obj=None, title='', minvalue=None, maxvalue=None, readonly=False, depth | |
dlg.show() | ||
_app.exec_() | ||
|
||
restore_except_hook() | ||
sys.excepthook = orig_except_hook | ||
|
||
|
||
def view(obj=None, title='', depth=0, display_caller_info=True): | ||
|
@@ -182,6 +186,43 @@ def view(obj=None, title='', depth=0, display_caller_info=True): | |
edit(obj, title=title, readonly=True, depth=depth + 1, display_caller_info=display_caller_info) | ||
|
||
|
||
def _debug(stack_summary, stack_pos=None): | ||
# we don't use install_except_hook/restore_except_hook so that we can restore the hook actually used when | ||
# this function is called instead of the one which was used when the module was loaded. | ||
orig_except_hook = sys.excepthook | ||
sys.excepthook = _qt_except_hook | ||
|
||
_app = QApplication.instance() | ||
if _app is None: | ||
_app = qapplication() | ||
_app.setOrganizationName("LArray") | ||
_app.setApplicationName("Debugger") | ||
parent = None | ||
else: | ||
parent = _app.activeWindow() | ||
|
||
assert isinstance(stack_summary, StackSummary) | ||
dlg = MappingEditor(parent) | ||
setup_ok = dlg.setup_and_check(stack_summary, stack_pos=stack_pos) | ||
if setup_ok: | ||
dlg.show() | ||
_app.exec_() | ||
|
||
sys.excepthook = orig_except_hook | ||
|
||
|
||
def debug(depth=0): | ||
""" | ||
Opens a new debug window. | ||
|
||
depth : int, optional | ||
Stack depth where to look for variables. Defaults to 0 (where this function was called). | ||
""" | ||
caller_frame = sys._getframe(depth + 1) | ||
stack_summary = extract_stack(caller_frame) | ||
_debug(stack_summary) | ||
|
||
|
||
def compare(*args, **kwargs): | ||
""" | ||
Opens a new comparator window, comparing arrays or sessions. | ||
|
@@ -224,7 +265,10 @@ def compare(*args, **kwargs): | |
>>> compare(a1, a2, title='first comparison') # doctest: +SKIP | ||
>>> compare(a1 + 1, a2, title='second comparison', names=['a1+1', 'a2']) # doctest: +SKIP | ||
""" | ||
install_except_hook() | ||
# we don't use install_except_hook/restore_except_hook so that we can restore the hook actually used when | ||
# this function is called instead of the one which was used when the module was loaded. | ||
orig_except_hook = sys.excepthook | ||
sys.excepthook = _qt_except_hook | ||
|
||
title = kwargs.pop('title', '') | ||
names = kwargs.pop('names', None) | ||
|
@@ -267,7 +311,8 @@ def get_name(i, obj, depth=0): | |
dlg.show() | ||
_app.exec_() | ||
|
||
restore_except_hook() | ||
sys.excepthook = orig_except_hook | ||
|
||
|
||
_orig_except_hook = sys.excepthook | ||
|
||
|
@@ -307,15 +352,7 @@ def _trace_code_file(tb): | |
return os.path.normpath(tb.tb_frame.f_code.co_filename) | ||
|
||
|
||
def _get_vars_from_frame(frame): | ||
frame_globals, frame_locals = frame.f_globals, frame.f_locals | ||
d = collections.OrderedDict() | ||
d.update([(k, frame_globals[k]) for k in sorted(frame_globals.keys())]) | ||
d.update([(k, frame_locals[k]) for k in sorted(frame_locals.keys())]) | ||
return d | ||
|
||
|
||
def _get_debug_except_hook(root_path=None, usercode_traceback=True): | ||
def _get_debug_except_hook(root_path=None, usercode_traceback=True, usercode_frame=True): | ||
try: | ||
main_file = os.path.abspath(sys.modules['__main__'].__file__) | ||
except AttributeError: | ||
|
@@ -333,29 +370,31 @@ def excepthook(type, value, tback): | |
|
||
main_tb = current_tb if _trace_code_file(current_tb) == main_file else tback | ||
|
||
if usercode_traceback: | ||
user_tb_length = None | ||
if usercode_traceback or usercode_frame: | ||
if main_tb != current_tb: | ||
print("Warning: couldn't find frame corresponding to user code, showing the full traceback " | ||
"and inspect last frame instead (which might be in library code)", | ||
file=sys.stderr) | ||
limit = None | ||
else: | ||
user_tb_length = 1 | ||
# continue as long as the next tb is still in the current project | ||
while current_tb.tb_next and _trace_code_file(current_tb.tb_next).startswith(root_path): | ||
current_tb = current_tb.tb_next | ||
user_tb_length += 1 | ||
limit = user_tb_length | ||
else: | ||
limit = None | ||
traceback.print_exception(type, value, main_tb, limit=limit) | ||
|
||
tb_limit = user_tb_length if usercode_traceback else None | ||
traceback.print_exception(type, value, main_tb, limit=tb_limit) | ||
|
||
stack = extract_tb(main_tb, limit=tb_limit) | ||
stack_pos = user_tb_length - 1 if user_tb_length is not None and usercode_frame else None | ||
print("\nlaunching larray editor to debug...", file=sys.stderr) | ||
edit(_get_vars_from_frame(current_tb.tb_frame)) | ||
_debug(stack, stack_pos=stack_pos) | ||
|
||
return excepthook | ||
|
||
|
||
def run_editor_on_exception(root_path=None, usercode_traceback=True): | ||
def run_editor_on_exception(root_path=None, usercode_traceback=True, usercode_frame=True): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't forget to repeat the new argument in the file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. will do |
||
""" | ||
Run the editor when an unhandled exception (a fatal error) happens. | ||
|
||
|
@@ -366,9 +405,13 @@ def run_editor_on_exception(root_path=None, usercode_traceback=True): | |
usercode_traceback : bool, optional | ||
Whether or not to show only the part of the traceback (error log) which corresponds to the user code. | ||
Otherwise, it will show the complete traceback, including code inside libraries. Defaults to True. | ||
usercode_frame : bool, optional | ||
Whether or not to start the debug window in the frame corresponding to the user code. | ||
This argument is ignored (it is always True) if usercode_traceback is True. Defaults to True. | ||
|
||
Notes | ||
----- | ||
sets sys.excepthook | ||
""" | ||
sys.excepthook = _get_debug_except_hook(root_path=root_path, usercode_traceback=usercode_traceback) | ||
sys.excepthook = _get_debug_except_hook(root_path=root_path, usercode_traceback=usercode_traceback, | ||
usercode_frame=usercode_frame) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add this function to the
larray
repository ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
will do