11
11
from typing import Optional
12
12
from typing import Tuple
13
13
14
- from textual import events
15
14
from textual .app import App
16
- from textual import log
17
15
from textual .app import ComposeResult
18
16
from textual .binding import Binding
19
- from textual .containers import Grid , Container
17
+ from textual .containers import Container
18
+ from textual .containers import Grid
19
+ from textual .containers import Horizontal
20
+ from textual .containers import Vertical
20
21
from textual .dom import DOMNode
21
- from textual .screen import ModalScreen
22
+ from textual .reactive import reactive
23
+ from textual .widget import Widget
22
24
from textual .widgets import Footer
23
25
from textual .widgets import Label
24
26
from textual .widgets import ListItem
27
29
from textual .widgets import Tree
28
30
from textual .widgets ._text_area import Edit
29
31
from textual .widgets .tree import TreeNode
30
- from textual .containers import Horizontal , Vertical
31
- from textual .reactive import reactive
32
- from textual .widget import Widget
33
-
34
32
35
33
from memray import AllocationRecord
36
34
from memray ._memray import size_fmt
@@ -66,15 +64,19 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
66
64
super ().__init__ (* args , ** kwargs )
67
65
self .cursor_blink = False
68
66
67
+ def edit (self , edit : Edit ) -> Any :
68
+ return
69
+
70
+
69
71
class FrameDetailScreen (Widget ):
70
72
"""A screen that displays information about a frame"""
71
73
72
- frame = reactive (None )
74
+ frame = reactive (Frame ( location = ROOT_NODE , value = 0 ) )
73
75
74
76
def __init__ (self , * args : Any , ** kwargs : Any ) -> None :
75
77
super ().__init__ (* args , ** kwargs )
76
78
self .is_mounted = False
77
-
79
+
78
80
def on_mount (self ) -> None :
79
81
self .is_mounted = True
80
82
@@ -86,14 +88,20 @@ def watch_frame(self) -> None:
86
88
text = self .query_one ("#textarea" , FrozenTextArea )
87
89
delta = text .size .height // 2
88
90
lines = linecache .getlines (file )[line - delta : line + delta ]
89
-
91
+
90
92
self .query_one ("#function" , Label ).update (f":compass: Function: { function } " )
91
93
self .query_one ("#location" , Label ).update (f":compass: Location: { file } :{ line } " )
92
- self .query_one ("#allocs" , Label ).update (f":floppy_disk: Allocations: { self .frame .n_allocations } " )
93
- self .query_one ("#size" , Label ).update (f":package: Size: { size_fmt (self .frame .value )} " )
94
- self .query_one ("#thread" , Label ).update (f":thread: Thread: { self .frame .thread_id } " )
94
+ self .query_one ("#allocs" , Label ).update (
95
+ f":floppy_disk: Allocations: { self .frame .n_allocations } "
96
+ )
97
+ self .query_one ("#size" , Label ).update (
98
+ f":package: Size: { size_fmt (self .frame .value )} "
99
+ )
100
+ self .query_one ("#thread" , Label ).update (
101
+ f":thread: Thread: { self .frame .thread_id } "
102
+ )
95
103
text .text = "\n " .join (tuple (line .rstrip () for line in lines ))
96
- text .select_line ((delta - 1 ))
104
+ text .select_line ((delta - 1 ))
97
105
text .show_line_numbers = False
98
106
99
107
def compose (self ) -> ComposeResult :
@@ -113,21 +121,31 @@ def compose(self) -> ComposeResult:
113
121
ListItem (Label (f":compass: Function: { function } " , id = "function" )),
114
122
ListItem (Label (f":compass: Location: { file } :{ line } " , id = "location" )),
115
123
ListItem (
116
- Label (f":floppy_disk: Allocations: { self .frame .n_allocations } " , id = "allocs" )
124
+ Label (
125
+ f":floppy_disk: Allocations: { self .frame .n_allocations } " ,
126
+ id = "allocs" ,
127
+ )
128
+ ),
129
+ ListItem (
130
+ Label (f":package: Size: { size_fmt (self .frame .value )} " , id = "size" )
131
+ ),
132
+ ListItem (
133
+ Label (f":thread: Thread: { self .frame .thread_id } " , id = "thread" )
117
134
),
118
- ListItem (Label (f":package: Size: { size_fmt (self .frame .value )} " , id = "size" )),
119
- ListItem (Label (f":thread: Thread: { self .frame .thread_id } " , id = "thread" )),
120
135
),
121
136
id = "node" ,
122
137
)
123
138
139
+
124
140
class FrameTree (Tree [Frame ]):
125
- def on_tree_node_selected (self , node : Tree .NodeSelected ) -> None :
126
- self .app .query_one (FrameDetailScreen ).frame = node .node .data
127
-
128
- def on_tree_node_highlighted (self , node : Tree .NodeHighlighted ) -> None :
129
- self .app .query_one (FrameDetailScreen ).frame = node .node .data
130
-
141
+ def on_tree_node_selected (self , node : Tree .NodeSelected [Frame ]) -> None :
142
+ if node .node .data is not None :
143
+ self .app .query_one (FrameDetailScreen ).frame = node .node .data
144
+
145
+ def on_tree_node_highlighted (self , node : Tree .NodeHighlighted [Frame ]) -> None :
146
+ if node .node .data is not None :
147
+ self .app .query_one (FrameDetailScreen ).frame = node .node .data
148
+
131
149
132
150
class TreeApp (App [None ]):
133
151
BINDINGS = [
@@ -174,9 +192,7 @@ def compose(self) -> ComposeResult:
174
192
Vertical (
175
193
Container (tree , id = "treec" ),
176
194
),
177
- Vertical (
178
- FrameDetailScreen ()
179
- ),
195
+ Vertical (FrameDetailScreen ()),
180
196
)
181
197
yield Footer ()
182
198
@@ -190,7 +206,6 @@ def action_expand_linear_group(self) -> None:
190
206
break
191
207
current_node = current_node .children [0 ]
192
208
193
-
194
209
def create_tree (
195
210
self ,
196
211
node : Frame ,
0 commit comments