Skip to content

Commit 78080f0

Browse files
authored
fix: split up meta for label (#117)
Signed-off-by: Henry Schreiner <henryschreineriii@gmail.com>
1 parent 6832861 commit 78080f0

File tree

5 files changed

+77
-43
lines changed

5 files changed

+77
-43
lines changed

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ dependencies = [
4646
"plotext >=5.2.2",
4747
"hist >=2.4",
4848
"textual >=0.13.0",
49+
'typing_extensions; python_version<"3.8"'
4950
]
5051

5152
[project.optional-dependencies]

src/uproot_browser/tree.py

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66

77
import dataclasses
88
import functools
9+
import sys
910
from pathlib import Path
10-
from typing import Any, Dict
11+
from typing import Any
1112

1213
import uproot
1314
import uproot.reading
@@ -16,15 +17,36 @@
1617
from rich.text import Text
1718
from rich.tree import Tree
1819

20+
if sys.version_info < (3, 8):
21+
from typing_extensions import TypedDict
22+
else:
23+
from typing import TypedDict
24+
1925
console = Console()
2026

21-
__all__ = ("make_tree", "process_item", "print_tree", "UprootEntry", "console")
27+
__all__ = (
28+
"make_tree",
29+
"process_item",
30+
"print_tree",
31+
"UprootEntry",
32+
"console",
33+
"MetaDict",
34+
)
2235

2336

2437
def __dir__() -> tuple[str, ...]:
2538
return __all__
2639

2740

41+
class MetaDictRequired(TypedDict, total=True):
42+
label_text: Text
43+
label_icon: str
44+
45+
46+
class MetaDict(MetaDictRequired, total=False):
47+
guide_style: str
48+
49+
2850
@dataclasses.dataclass
2951
class UprootEntry:
3052
path: str
@@ -38,11 +60,18 @@ def is_dir(self) -> bool:
3860
return len(self.item.branches) > 0
3961
return False
4062

41-
def meta(self) -> dict[str, Any]:
63+
def meta(self) -> MetaDict:
4264
return process_item(self.item)
4365

4466
def label(self) -> Text:
45-
return process_item(self.item)["label"] # type: ignore[no-any-return]
67+
meta = self.meta()
68+
return Text.assemble(meta["label_icon"], meta["label_text"])
69+
70+
def tree_args(self) -> dict[str, Any]:
71+
d: dict[str, Text | str] = {"label": self.label()}
72+
if "guide_style" in self.meta():
73+
d["guide_style"] = self.meta()["guide_style"]
74+
return d
4675

4776
@property
4877
def children(self) -> list[UprootEntry]:
@@ -68,7 +97,7 @@ def make_tree(node: UprootEntry, *, tree: Tree | None = None) -> Tree:
6897
Given an object, build a rich.tree.Tree output.
6998
"""
7099

71-
tree = Tree(**node.meta()) if tree is None else tree.add(**node.meta())
100+
tree = Tree(**node.tree_args()) if tree is None else tree.add(**node.tree_args())
72101

73102
for child in node.children:
74103
make_tree(child, tree=tree)
@@ -77,24 +106,23 @@ def make_tree(node: UprootEntry, *, tree: Tree | None = None) -> Tree:
77106

78107

79108
@functools.singledispatch
80-
def process_item(uproot_object: Any) -> Dict[str, Any]:
109+
def process_item(uproot_object: Any) -> MetaDict:
81110
"""
82111
Given an unknown object, return a rich.tree.Tree output. Specialize for known objects.
83112
"""
84113
name = getattr(uproot_object, "name", "<unnamed>")
85114
classname = getattr(uproot_object, "classname", uproot_object.__class__.__name__)
86-
label = Text.assemble(
87-
"❓ ",
115+
label_text = Text.assemble(
88116
(f"{name} ", "bold"),
89117
(classname, "italic"),
90118
)
91-
return {"label": label}
119+
return MetaDict(label_icon="❓ ", label_text=label_text)
92120

93121

94122
@process_item.register
95123
def _process_item_tfile(
96124
uproot_object: uproot.reading.ReadOnlyDirectory,
97-
) -> Dict[str, Any]:
125+
) -> MetaDict:
98126
"""
99127
Given an TFile, return a rich.tree.Tree output.
100128
"""
@@ -109,33 +137,34 @@ def _process_item_tfile(
109137
path_name = escape(path.name)
110138
link_text = f"file://{path}"
111139

112-
label = Text.from_markup(f":file_folder: [link {link_text}]{path_name}")
140+
label_text = Text.from_markup(f"[link {link_text}]{path_name}")
113141

114-
return {
115-
"label": label,
116-
"guide_style": "bold bright_blue",
117-
}
142+
return MetaDict(
143+
label_icon="📁 ",
144+
label_text=label_text,
145+
guide_style="bold bright_blue",
146+
)
118147

119148

120149
@process_item.register
121-
def _process_item_ttree(uproot_object: uproot.TTree) -> Dict[str, Any]:
150+
def _process_item_ttree(uproot_object: uproot.TTree) -> MetaDict:
122151
"""
123152
Given an tree, return a rich.tree.Tree output.
124153
"""
125-
label = Text.assemble(
126-
"🌴 ",
154+
label_text = Text.assemble(
127155
(f"{uproot_object.name} ", "bold"),
128156
f"({uproot_object.num_entries:g})",
129157
)
130158

131-
return {
132-
"label": label,
133-
"guide_style": "bold bright_green",
134-
}
159+
return MetaDict(
160+
label_icon="🌴 ",
161+
label_text=label_text,
162+
guide_style="bold bright_green",
163+
)
135164

136165

137166
@process_item.register
138-
def _process_item_tbranch(uproot_object: uproot.TBranch) -> Dict[str, Any]:
167+
def _process_item_tbranch(uproot_object: uproot.TBranch) -> MetaDict:
139168
"""
140169
Given an branch, return a rich.tree.Tree output.
141170
"""
@@ -148,29 +177,35 @@ def _process_item_tbranch(uproot_object: uproot.TBranch) -> Dict[str, Any]:
148177
if len(uproot_object.branches):
149178
icon = "🌿 "
150179

151-
label = Text.assemble(
152-
icon,
180+
label_text = Text.assemble(
153181
(f"{uproot_object.name} ", "bold"),
154182
(f"{uproot_object.typename}", "italic"),
155183
)
156-
return {"label": label}
184+
185+
return MetaDict(
186+
label_icon=icon,
187+
label_text=label_text,
188+
guide_style="bold bright_green",
189+
)
157190

158191

159192
@process_item.register
160-
def _process_item_th(uproot_object: uproot.behaviors.TH1.Histogram) -> Dict[str, Any]:
193+
def _process_item_th(uproot_object: uproot.behaviors.TH1.Histogram) -> MetaDict:
161194
"""
162195
Given an histogram, return a rich.tree.Tree output.
163196
"""
164197
icon = "📊 " if uproot_object.kind == "COUNT" else "📈 "
165198
sizes = " × ".join(f"{len(ax)}" for ax in uproot_object.axes)
166199

167-
label = Text.assemble(
168-
icon,
200+
label_text = Text.assemble(
169201
(f"{uproot_object.name} ", "bold"),
170202
(f"{uproot_object.classname} ", "italic"),
171203
f"({sizes})",
172204
)
173-
return {"label": label}
205+
return MetaDict(
206+
label_icon=icon,
207+
label_text=label_text,
208+
)
174209

175210

176211
# pylint: disable-next=redefined-outer-name

src/uproot_browser/tui/browser.css

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ Browser Widget {
2323
}
2424

2525
Tree > .tree--cursor {
26-
background: $secondary-darken;
26+
background: $secondary-darken-1;
2727
color: $text;
2828
text-style: bold;
2929
}

src/uproot_browser/tui/browser.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from textual.reactive import var
1818

1919
with contextlib.suppress(AttributeError):
20-
light_background = 0xDF, 0xDF, 0xDF # $surface-darken-1
20+
light_background = 0xEF, 0xEF, 0xEF # $surface-darken-1
2121
# pylint: disable-next=protected-access
2222
plt._dict.themes["default"][0] = light_background
2323
# pylint: disable-next=protected-access
@@ -144,10 +144,11 @@ def on_uproot_selected(self, message: UprootSelected) -> None:
144144
content_switcher.current = "error"
145145

146146

147-
if __name__ == "<run_path>":
147+
if __name__ in {"<run_path>", "__main__"}:
148148
import uproot_browser.dirs
149149

150150
fname = uproot_browser.dirs.filename(
151151
"../scikit-hep-testdata/src/skhep_testdata/data/uproot-Event.root"
152152
)
153153
app = Browser(path=Path(fname))
154+
app.run()

src/uproot_browser/tui/left_panel.py

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -42,20 +42,17 @@ def __init__(self, path: Path, **args: Any) -> None:
4242
def render_label(
4343
self,
4444
node: textual.widgets.tree.TreeNode[UprootEntry],
45-
base_style: Style, # noqa: ARG002
45+
base_style: Style,
4646
style: Style, # ,
4747
) -> rich.text.Text:
48-
meta = {
49-
"@click": f"click_label({node.id})",
50-
"tree_node": node.id,
51-
}
5248
assert node.data
53-
icon_label = node.data.label()
54-
icon_label.apply_meta(meta)
49+
meta = node.data.meta()
50+
label_icon = rich.text.Text(meta["label_icon"])
51+
label_icon.stylize(base_style)
5552

56-
# label = icon_label.copy()
57-
icon_label.stylize(style)
58-
return icon_label
53+
label = rich.text.Text.assemble(label_icon, meta["label_text"])
54+
label.stylize(style)
55+
return label
5956

6057
def on_mount(self) -> None:
6158
self.load_directory(self.root)

0 commit comments

Comments
 (0)