From d9dca1e7a51b807ae0b48a1aa6b30ca11588cac0 Mon Sep 17 00:00:00 2001 From: Michael van der Kamp Date: Sat, 30 Jul 2022 13:18:04 -0700 Subject: [PATCH] Persist InspectInfo for global watches --- pudb/var_view.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/pudb/var_view.py b/pudb/var_view.py index 01532d71..90e95987 100644 --- a/pudb/var_view.py +++ b/pudb/var_view.py @@ -29,6 +29,7 @@ import urwid import inspect import warnings +import weakref from abc import ABC, abstractmethod from collections.abc import Callable, Sized @@ -170,11 +171,14 @@ def length(cls, mapping): # {{{ data class FrameVarInfo: - def __init__(self): + def __init__(self, global_watch_iinfo): self.id_path_to_iinfo = {} self.watches = [] + self.global_watch_iinfo = global_watch_iinfo def get_inspect_info(self, id_path, read_only): + if id_path in self.global_watch_iinfo: + return self.global_watch_iinfo[id_path] if read_only: return self.id_path_to_iinfo.get( id_path, InspectInfo()) @@ -206,6 +210,9 @@ def __init__(self, expression="", scope="local", method="expression"): self.method = method self._value = self.NOT_EVALUATED + def id_path(self): + return str(id(self)) + def eval(self, frame_globals, frame_locals): if (self.method == "expression" or self._value is self.NOT_EVALUATED): @@ -778,8 +785,9 @@ def make_var_view(global_watches, frame_var_info, frame_globals, frame_locals): for watch_expr in chain(global_watches, frame_var_info.watches): value = watch_expr.eval(frame_globals, frame_locals) label = watch_expr.label(value, frame_globals, frame_locals) + id_path = watch_expr.id_path() WatchValueWalker(frame_var_info, watch_widget_list, watch_expr) \ - .walk_value(None, label, value) + .walk_value(None, label, value, id_path) if "__return__" in vars: ret_walker.walk_value(None, "Return", frame_locals["__return__"], @@ -808,14 +816,18 @@ def __init__(self): self.frame_var_info = {} self.global_watches = [] + # In order to have the global watch expression presented the same way in + # all frames, we need persistent storage for global InspectInfo. + self.global_watch_iinfo = {} + def get_frame_var_info(self, read_only, ssid=None): if ssid is None: # self.debugger set by subclass ssid = self.debugger.get_stack_situation_id() # noqa: E501 # pylint: disable=no-member if read_only: - return self.frame_var_info.get(ssid, FrameVarInfo()) + return self.frame_var_info.get(ssid, FrameVarInfo(self.global_watch_iinfo)) else: - return self.frame_var_info.setdefault(ssid, FrameVarInfo()) + return self.frame_var_info.setdefault(ssid, FrameVarInfo(self.global_watch_iinfo)) def add_watch(self, watch_expr: WatchExpression, fvi=None): if watch_expr.scope == "local": @@ -824,6 +836,7 @@ def add_watch(self, watch_expr: WatchExpression, fvi=None): fvi.watches.append(watch_expr) elif watch_expr.scope == "global": self.global_watches.append(watch_expr) + self.global_watch_iinfo[watch_expr.id_path()] = InspectInfo() def delete_watch(self, watch_expr: WatchExpression, fvi=None): if fvi is None: @@ -836,6 +849,7 @@ def delete_watch(self, watch_expr: WatchExpression, fvi=None): pass try: self.global_watches.remove(watch_expr) + self.global_watch_iinfo.pop(watch_expr.id_path()) except ValueError: pass