Skip to content

Commit

Permalink
Allow editing scope/method of watch expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
mvanderkamp committed Jun 29, 2022
1 parent 8babd03 commit ececc64
Show file tree
Hide file tree
Showing 2 changed files with 93 additions and 63 deletions.
124 changes: 64 additions & 60 deletions pudb/debugger.py
Original file line number Diff line number Diff line change
Expand Up @@ -1006,14 +1006,59 @@ def change_var_state(w, size, key):
elif key == "m":
iinfo.show_methods = not iinfo.show_methods
elif key == "delete":
fvi = self.get_frame_var_info(read_only=False)
try:
fvi.watches.remove(var.watch_expr)
except ValueError:
pass
self.delete_watch(var.watch_expr)

self.update_var_view(focus_index=focus_index)

def _watch_editors(watch_expr):
"""
Create widgets for editing the given expression.
"""
def set_watch_scope(radio_button, new_state, user_data):
if new_state:
watch_expr.set_scope(user_data)

def set_watch_method(radio_button, new_state, user_data):
if new_state:
watch_expr.set_method(user_data)

watch_edit = urwid.Edit([("label", "Watch expression: ")],
watch_expr.expression)

scope_rbs = []
urwid.RadioButton(
group=scope_rbs,
label="Local: watch in current frame only",
state=watch_expr.scope == "local",
on_state_change=set_watch_scope,
user_data="local",
)
urwid.RadioButton(
group=scope_rbs,
label="Global: watch in all frames",
state=watch_expr.scope == "global",
on_state_change=set_watch_scope,
user_data="global",
)

method_rbs = []
urwid.RadioButton(
group=method_rbs,
label="Expression: always re-evaluate the expression",
state=watch_expr.method == "expression",
on_state_change=set_watch_method,
user_data="expression",
)
urwid.RadioButton(
group=method_rbs,
label="Reference: evaluate once, watch the resulting value",
state=watch_expr.method == "reference",
on_state_change=set_watch_method,
user_data="reference",
)

return watch_edit, scope_rbs, method_rbs

def edit_inspector_detail(w, size, key):
var, pos = self.var_list._w.get_focus()

Expand All @@ -1029,13 +1074,17 @@ def edit_inspector_detail(w, size, key):
]

if var.watch_expr is not None:
watch_edit = urwid.Edit([
("label", "Watch expression: ")
], var.watch_expr.expression)
watch_edit, scope_rbs, method_rbs = _watch_editors(var.watch_expr)
id_segment = [
urwid.AttrMap(watch_edit, "input", "focused input"),
urwid.Text(""),
]
urwid.AttrMap(watch_edit, "input", "focused input"),
urwid.Text(""),
urwid.Text("Scope:"),
] + scope_rbs + [
urwid.Text(""),
urwid.Text("Method:"),
] + method_rbs + [
urwid.Text("")
]

buttons.extend([None, ("Delete", "del")])

Expand Down Expand Up @@ -1123,63 +1172,18 @@ def edit_inspector_detail(w, size, key):
iinfo.access_level = "all"

if var.watch_expr is not None:
new_expression = watch_edit.get_edit_text()
if new_expression != var.watch_expr.expression:
var.watch_expr.set_expression(new_expression)
var.watch_expr.set_expression(watch_edit.get_edit_text())
self.change_watch_scope(var.watch_expr, fvi)

elif result == "del":
try:
fvi.watches.remove(var.watch_expr)
except ValueError:
pass
self.delete_watch(var.watch_expr, fvi)

self.update_var_view()

def insert_watch(w, size, key):
from pudb.var_view import WatchExpression
watch_expr = WatchExpression()

def set_watch_scope(radio_button, new_state, user_data):
if new_state == True:
watch_expr.scope = user_data

def set_watch_method(radio_button, new_state, user_data):
if new_state == True:
watch_expr.method = user_data

watch_edit = urwid.Edit([("label", "Watch expression: ")])

scope_rbs = []
urwid.RadioButton(
group=scope_rbs,
label="Local: watch in current frame only",
state=True,
on_state_change=set_watch_scope,
user_data="local",
)
urwid.RadioButton(
group=scope_rbs,
label="Global: watch in all frames",
state=False,
on_state_change=set_watch_scope,
user_data="global",
)

method_rbs = []
urwid.RadioButton(
group=method_rbs,
label="Expression: always re-evaluate the expression",
state=True,
on_state_change=set_watch_method,
user_data="expression",
)
urwid.RadioButton(
group=method_rbs,
label="Reference: evaluate once, watch the resulting value",
state=False,
on_state_change=set_watch_method,
user_data="reference",
)
watch_edit, scope_rbs, method_rbs = _watch_editors(watch_expr)

if self.dialog(
urwid.ListBox(urwid.SimpleListWalker([
Expand Down
32 changes: 29 additions & 3 deletions pudb/var_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,17 @@ def eval(self, frame_globals, frame_locals):
return self._value

def set_expression(self, expression):
self.expression = expression
if expression != self.expression:
self.expression = expression
self._value = self.NOT_EVALUATED

def set_method(self, method):
self.method = method
self._value = self.NOT_EVALUATED

def set_scope(self, scope):
self.scope = scope


class WatchEvalError:
def __str__(self):
Expand Down Expand Up @@ -803,13 +811,31 @@ def get_frame_var_info(self, read_only, ssid=None):
else:
return self.frame_var_info.setdefault(ssid, FrameVarInfo())

def add_watch(self, watch_expr: WatchExpression):
def add_watch(self, watch_expr: WatchExpression, fvi=None):
if watch_expr.scope == "local":
fvi = self.get_frame_var_info(read_only=False)
if fvi is None:
fvi = self.get_frame_var_info(read_only=False)
fvi.watches.append(watch_expr)
elif watch_expr.scope == "global":
self.global_watches.append(watch_expr)

def delete_watch(self, watch_expr: WatchExpression, fvi=None):
if fvi is None:
fvi = self.get_frame_var_info(read_only=False)
# Need to delete both locally and globally- could be in either!
# (The watch_expr.scope attribute may have changed)
try:
fvi.watches.remove(watch_expr)
except ValueError:
pass
try:
self.global_watches.remove(watch_expr)
except ValueError:
pass

def change_watch_scope(self, watch_expr, fvi=None):
self.delete_watch(watch_expr, fvi)
self.add_watch(watch_expr, fvi)

# }}}

Expand Down

0 comments on commit ececc64

Please sign in to comment.