Skip to content
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

Added auto save/load of watch expressions #150

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions pudb/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,6 +901,20 @@ def edit_inspector_detail(w, size, key):
var.watch_expr.expression = watch_edit.get_edit_text()

elif result == "del":
if CONFIG["persist_watches"]:
from pudb.settings import load_watches, save_watches
stored_expressions = [expr.strip()
for expr in load_watches()]

# Remove saved expression
for i, stored_expr in enumerate(stored_expressions):
if stored_expr == var.watch_expr.expression:
del stored_expressions[i]

# Save it here because self.update_var_view() is going to
# read saved watches again
save_watches(stored_expressions)

for i, watch_expr in enumerate(fvi.watches):
if watch_expr is var.watch_expr:
del fvi.watches[i]
Expand Down
59 changes: 59 additions & 0 deletions pudb/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def get_save_config_path(*resource):

SAVED_BREAKPOINTS_FILE_NAME = "saved-breakpoints-%d.%d" % sys.version_info[:2]
BREAKPOINTS_FILE_NAME = "breakpoints-%d.%d" % sys.version_info[:2]
SAVED_WATCHES_FILE_NAME = "saved-watches-%d.%d" % sys.version_info[:2]


def load_config():
Expand Down Expand Up @@ -108,6 +109,8 @@ def load_config():
conf_dict.setdefault("wrap_variables", True)
conf_dict.setdefault("default_variables_access_level", "public")

conf_dict.setdefault("persist_watches", False)

conf_dict.setdefault("display", "auto")

conf_dict.setdefault("prompt_on_quit", True)
Expand All @@ -123,6 +126,7 @@ def normalize_bool_inplace(name):

normalize_bool_inplace("line_numbers")
normalize_bool_inplace("wrap_variables")
normalize_bool_inplace("persist_watches")
normalize_bool_inplace("prompt_on_quit")

return conf_dict
Expand Down Expand Up @@ -178,6 +182,9 @@ def _update_default_variables_access_level():
def _update_wrap_variables():
ui.update_var_view()

def _update_persist_watches():
pass

def _update_config(check_box, new_state, option_newvalue):
option, newvalue = option_newvalue
new_conf_dict = {option: newvalue}
Expand Down Expand Up @@ -229,6 +236,11 @@ def _update_config(check_box, new_state, option_newvalue):
conf_dict.update(new_conf_dict)
_update_wrap_variables()

elif option == "persist_watches":
new_conf_dict["persist_watches"] = not check_box.get_state()
conf_dict.update(new_conf_dict)
_update_persist_watches()

heading = urwid.Text("This is the preferences screen for PuDB. "
"Hit Ctrl-P at any time to get back to it.\n\n"
"Configuration settings are saved in "
Expand Down Expand Up @@ -383,6 +395,17 @@ def _update_config(check_box, new_state, option_newvalue):

# }}}

# {{{ persist watches

cb_persist_watches = urwid.CheckBox("Persist watches",
bool(conf_dict["persist_watches"]), on_state_change=_update_config,
user_data=("persist_watches", None))

persist_watches_info = urwid.Text("\nKeep watched expressions between "
"debugging sessions.")

# }}}

# {{{ display

display_info = urwid.Text("What driver is used to talk to your terminal. "
Expand Down Expand Up @@ -437,6 +460,10 @@ def _update_config(check_box, new_state, option_newvalue):
+ [cb_wrap_variables]
+ [wrap_variables_info]

+ [urwid.AttrMap(urwid.Text("\nPersist Watches:\n"), "group head")]
+ [cb_persist_watches]
+ [persist_watches_info]

+ [urwid.AttrMap(urwid.Text("\nDisplay driver:\n"), "group head")]
+ [display_info]
+ display_rbs
Expand Down Expand Up @@ -586,4 +613,36 @@ def save_breakpoints(bp_list):

# }}}


def get_watches_file_name():
from os.path import join
return join(get_save_config_path(), SAVED_WATCHES_FILE_NAME)


def save_watches(w_list):
"""
:arg w_list: a list of strings
"""

try:
with open(get_watches_file_name(), 'w+') as histfile:
for watch in w_list:
histfile.write(watch + '\n')
except:
pass


def load_watches():
if os.path.exists(get_watches_file_name()):
try:
with open(get_watches_file_name(), 'r') as histfile:
watches = histfile.readlines()
for line in watches:
line = line.strip()
return watches
except:
pass

return []

# vim:foldmethod=marker
17 changes: 17 additions & 0 deletions pudb/var_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,23 @@ def make_var_view(frame_var_info, locals, globals):
ret_walker = BasicValueWalker(frame_var_info)
watch_widget_list = []

if CONFIG["persist_watches"]:
Copy link

@Kevin-Prichard Kevin-Prichard Sep 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At this point CONFIG isn't in scope (on inducer:main today), so it needs to be imported

from pudb.settings import load_watches, save_watches
stored_expressions = [expr.strip() for expr in load_watches()]

# As watch expressions are stored in a list, simply appending stored
# expressions to that list will add duplicates. This part is to avoid that.
from pudb.var_view import WatchExpression
existing_expressions = [expr.expression
for expr in frame_var_info.watches]

for stored_expr in stored_expressions:
if stored_expr not in existing_expressions:
frame_var_info.watches.append(WatchExpression(stored_expr))

# Save watches because new ones may have added to a list
save_watches([expr.expression for expr in frame_var_info.watches])

for watch_expr in frame_var_info.watches:
try:
value = eval(watch_expr.expression, globals, locals)
Expand Down