Skip to content

Commit

Permalink
Implement locals panel
Browse files Browse the repository at this point in the history
  • Loading branch information
DubiousCactus committed Nov 3, 2024
1 parent 6b195cf commit ef4aaa4
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 10 deletions.
4 changes: 3 additions & 1 deletion bootstrap/hot_reloading/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ async def catch_and_hang(self, module: MatchboxModule, *args, **kwargs):
# call tree (our MatchboxModule's underlying function). What we want is
# to go down to the function that threw, and reload that only if it
# wasn't called anywhere in the frozen module's call tree.
frame = None
frame: Optional[FrameType] = None
if inspect.isclass(func):
frame = self.get_class_frame(func, exc_traceback)
elif inspect.isfunction(func) and func.__name__ == "<lambda>":
Expand All @@ -156,6 +156,8 @@ async def catch_and_hang(self, module: MatchboxModule, *args, **kwargs):
self.ui.print_err(
f"Could not find the frame of the original function {func} in the traceback."
)
else:
await self.ui.set_locals(frame.f_locals)
module.throw_frame = frame
self.ui.print_info("Exception thrown in:")
self.ui.print_pretty(frame)
Expand Down
16 changes: 12 additions & 4 deletions bootstrap/tui/builder_ui.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
Checkbox,
Footer,
Header,
Placeholder,
RichLog,
)

Expand All @@ -24,6 +23,7 @@
from bootstrap.tui.widgets.checkbox_panel import CheckboxPanel
from bootstrap.tui.widgets.editor import CodeEditor
from bootstrap.tui.widgets.files_tree import FilesTree
from bootstrap.tui.widgets.locals_panel import LocalsPanel
from bootstrap.tui.widgets.logger import Logger
from bootstrap.tui.widgets.tracer import Tracer

Expand Down Expand Up @@ -62,12 +62,15 @@ async def _chain_up(self) -> None:
if module.uid in keys:
raise ValueError(f"Duplicate module '{module}' with uid {module.uid}")
keys.append(module.uid)
self.query_one(CheckboxPanel).ready()

async def _run_chain(self) -> None:
self.log_tracer("Running the chain...")
if len(self._module_chain) == 0:
self.log_tracer(Text("The chain is empty!", style="bold red"))
for module in self._module_chain:
await self.query_one(LocalsPanel).clear()
self.query_one(Tracer).clear()
if module.is_frozen:
self.log_tracer(Text(f"Skipping frozen module {module}", style="green"))
continue
Expand All @@ -91,7 +94,9 @@ def run_chain(self) -> None:

def compose(self) -> ComposeResult:
yield Header()
yield CheckboxPanel(classes="box")
checkboxes = CheckboxPanel(classes="box")
checkboxes.loading = True
yield checkboxes
yield CodeEditor(classes="box", id="code")
logs = Logger(classes="box", id="logger")
logs.border_title = "User logs"
Expand All @@ -101,8 +106,8 @@ def compose(self) -> ComposeResult:
ftree.border_title = "Project tree"
ftree.styles.border = ("solid", "gray")
yield ftree
lcls = Placeholder("Locals area", classes="box")
lcls.loading = True
lcls = LocalsPanel(classes="box")
lcls.styles.border = ("solid", "gray")
lcls.border_title = "Frame locals"
yield lcls
yield Tracer(classes="box")
Expand Down Expand Up @@ -157,6 +162,9 @@ def noop(*args, **kwargs):
def log_tracer(self, message: str | RenderableType) -> None:
self.query_one(Tracer).write(message)

async def set_locals(self, locals: List[Any]) -> None:
await self.query_one(LocalsPanel).add_locals(locals)

async def hang(self, threw: bool) -> None:
"""
Give visual signal that the builder is hung, either due to an exception or
Expand Down
9 changes: 4 additions & 5 deletions bootstrap/tui/widgets/checkbox_panel.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
from textual.app import ComposeResult
from textual.containers import ScrollableContainer
from textual.containers import VerticalScroll
from textual.widgets import Checkbox, Static


class CheckboxPanel(Static):
def compose(self) -> ComposeResult:
yield ScrollableContainer(id="tickers")
yield VerticalScroll(id="tickers")

async def add_checkbox(self, label: str, id: str) -> None:
# yield Switch() # TODO: Use switches!!
await self.query_one("#tickers", ScrollableContainer).mount(
Checkbox(label, value=False, id=id)
)
await self.query_one("#tickers").mount(Checkbox(label, value=False, id=id))

def on_mount(self):
self.ready()
Expand All @@ -34,6 +32,7 @@ def hang(self, threw: bool) -> None:
self.due()

def ready(self) -> None:
self.loading = False
self.styles.border = ("solid", "green")
self.styles.opacity = 1.0
self.border_title = "Frozen modules: active"
22 changes: 22 additions & 0 deletions bootstrap/tui/widgets/locals_panel.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from typing import Any, Dict

from textual.app import ComposeResult
from textual.containers import VerticalScroll
from textual.widgets import Collapsible, Pretty, Static


class LocalsPanel(Static):
def compose(self) -> ComposeResult:
yield VerticalScroll(id="locals")

async def add_locals(self, locals: Dict[str, Any]) -> None:
for name, val in locals.items():
await self.query_one("#locals").mount(
Collapsible(
Pretty(val),
title=name,
)
)

async def clear(self) -> None:
await self.query_one("#locals", VerticalScroll).recompose()

0 comments on commit ef4aaa4

Please sign in to comment.