pyglove 0.4.5.dev202410100808__py3-none-any.whl → 0.4.5.dev202410160809__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyglove/core/__init__.py +1 -0
- pyglove/core/object_utils/__init__.py +2 -0
- pyglove/core/object_utils/formatting.py +16 -0
- pyglove/core/object_utils/formatting_test.py +9 -0
- pyglove/core/object_utils/value_location.py +246 -3
- pyglove/core/object_utils/value_location_test.py +363 -74
- pyglove/core/symbolic/base_test.py +5 -5
- pyglove/core/symbolic/diff.py +18 -13
- pyglove/core/symbolic/diff_test.py +30 -29
- pyglove/core/symbolic/ref.py +6 -3
- pyglove/core/symbolic/ref_test.py +9 -9
- pyglove/core/views/base.py +2 -0
- pyglove/core/views/base_test.py +1 -1
- pyglove/core/views/html/base.py +43 -14
- pyglove/core/views/html/base_test.py +9 -0
- pyglove/core/views/html/tree_view.py +253 -164
- pyglove/core/views/html/tree_view_test.py +172 -52
- {pyglove-0.4.5.dev202410100808.dist-info → pyglove-0.4.5.dev202410160809.dist-info}/METADATA +1 -1
- {pyglove-0.4.5.dev202410100808.dist-info → pyglove-0.4.5.dev202410160809.dist-info}/RECORD +22 -22
- {pyglove-0.4.5.dev202410100808.dist-info → pyglove-0.4.5.dev202410160809.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev202410100808.dist-info → pyglove-0.4.5.dev202410160809.dist-info}/WHEEL +0 -0
- {pyglove-0.4.5.dev202410100808.dist-info → pyglove-0.4.5.dev202410160809.dist-info}/top_level.txt +0 -0
@@ -15,13 +15,14 @@
|
|
15
15
|
|
16
16
|
import inspect
|
17
17
|
import re
|
18
|
-
from typing import Any, Dict, Iterable, Optional, Sequence,
|
18
|
+
from typing import Any, Callable, Dict, Iterable, Optional, Sequence, Union
|
19
19
|
|
20
20
|
from pyglove.core import object_utils
|
21
21
|
from pyglove.core.views.html import base
|
22
22
|
|
23
23
|
|
24
24
|
KeyPath = object_utils.KeyPath
|
25
|
+
KeyPathSet = object_utils.KeyPathSet
|
25
26
|
Html = base.Html
|
26
27
|
HtmlView = base.HtmlView
|
27
28
|
|
@@ -37,6 +38,40 @@ class HtmlTreeView(HtmlView):
|
|
37
38
|
class Extension(HtmlView.Extension):
|
38
39
|
"""The base class for extensions for HtmlTreeView."""
|
39
40
|
|
41
|
+
#
|
42
|
+
# Default extension-level rendering options overrides.
|
43
|
+
#
|
44
|
+
|
45
|
+
def _html_tree_view_special_keys(self) -> Sequence[str]:
|
46
|
+
"""Returns the special keys to display (at the immediate child level)."""
|
47
|
+
return []
|
48
|
+
|
49
|
+
def _html_tree_view_include_keys(self) -> Optional[Sequence[str]]:
|
50
|
+
"""Returns the keys to include (at the immediate child level)."""
|
51
|
+
return None
|
52
|
+
|
53
|
+
def _html_tree_view_exclude_keys(self) -> Sequence[str]:
|
54
|
+
"""Returns the keys to include (at the immediate child level)."""
|
55
|
+
return []
|
56
|
+
|
57
|
+
def _html_tree_view_uncollapse_level(self) -> Optional[int]:
|
58
|
+
"""Returns the level of the subtree to uncollapse.
|
59
|
+
|
60
|
+
Returns:
|
61
|
+
The level of subtree to uncollapse. If None, the subtree will be fully
|
62
|
+
expanded. Please note that the uncollapsed subtree will show only when
|
63
|
+
current node is uncollapsed.
|
64
|
+
"""
|
65
|
+
return 1
|
66
|
+
|
67
|
+
def _html_tree_view_uncollapse(self) -> KeyPathSet:
|
68
|
+
"""Returns the node paths (relative to current node) to uncollapse."""
|
69
|
+
return KeyPathSet()
|
70
|
+
|
71
|
+
#
|
72
|
+
# Default behavior overrides.
|
73
|
+
#
|
74
|
+
|
40
75
|
def _html_tree_view_render(
|
41
76
|
self,
|
42
77
|
*,
|
@@ -48,6 +83,10 @@ class HtmlTreeView(HtmlView):
|
|
48
83
|
special_keys: Optional[Sequence[Union[int, str]]] = None,
|
49
84
|
include_keys: Optional[Iterable[Union[int, str]]] = None,
|
50
85
|
exclude_keys: Optional[Iterable[Union[int, str]]] = None,
|
86
|
+
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
87
|
+
uncollapse: Union[
|
88
|
+
KeyPathSet, base.NodeFilter, None
|
89
|
+
] = HtmlView.PresetArgValue(None),
|
51
90
|
filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
|
52
91
|
highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
53
92
|
lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
@@ -55,10 +94,6 @@ class HtmlTreeView(HtmlView):
|
|
55
94
|
max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
|
56
95
|
enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
|
57
96
|
enable_key_tooltip: bool = HtmlView.PresetArgValue(True),
|
58
|
-
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
59
|
-
uncollapse: Union[
|
60
|
-
Iterable[Union[KeyPath, str]], base.NodeFilter, None
|
61
|
-
] = HtmlView.PresetArgValue(None),
|
62
97
|
**kwargs,
|
63
98
|
) -> Html:
|
64
99
|
"""Returns the topmost HTML representation of the object.
|
@@ -73,6 +108,10 @@ class HtmlTreeView(HtmlView):
|
|
73
108
|
level).
|
74
109
|
include_keys: The keys to include (at the immediate child level).
|
75
110
|
exclude_keys: The keys to exclude (at the immediate child level).
|
111
|
+
collapse_level: The level to collapse the tree (relative to this node).
|
112
|
+
uncollapse: A key path set (relative to root_path) for the nodes to
|
113
|
+
uncollapse. or a function with signature (path, value, parent) -> bool
|
114
|
+
to filter nodes to uncollapse.
|
76
115
|
filter: A function with signature (path, value, parent) -> include
|
77
116
|
to determine whether to include a field (at all levels).
|
78
117
|
highlight: A function with signature (path, value, parent) -> bool
|
@@ -85,10 +124,6 @@ class HtmlTreeView(HtmlView):
|
|
85
124
|
max_summary_len_for_str: The maximum length of the string to display.
|
86
125
|
enable_summary_tooltip: Whether to enable the tooltip for the summary.
|
87
126
|
enable_key_tooltip: Whether to enable the tooltip for the key.
|
88
|
-
collapse_level: The level to collapse the tree
|
89
|
-
uncollapse: A set of key paths for the nodes to uncollapse. or a
|
90
|
-
function with signature (path, value, parent) -> bool to determine
|
91
|
-
whether to uncollapse a node.
|
92
127
|
**kwargs: Additional keyword arguments passed from `pg.to_html`.
|
93
128
|
|
94
129
|
Returns:
|
@@ -122,7 +157,6 @@ class HtmlTreeView(HtmlView):
|
|
122
157
|
name: Optional[str],
|
123
158
|
parent: Any,
|
124
159
|
root_path: KeyPath,
|
125
|
-
css_class: Optional[Sequence[str]] = None,
|
126
160
|
title: Union[str, Html, None] = None,
|
127
161
|
enable_summary: Optional[bool] = HtmlView.PresetArgValue(None),
|
128
162
|
max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
|
@@ -136,7 +170,6 @@ class HtmlTreeView(HtmlView):
|
|
136
170
|
name: The name of the object.
|
137
171
|
parent: The parent of the object.
|
138
172
|
root_path: The key path of the object relative to the root.
|
139
|
-
css_class: The CSS classes to add to the root element
|
140
173
|
title: The title of the summary.
|
141
174
|
enable_summary: Whether to enable the summary. If None, summary will
|
142
175
|
be enabled for complex types or when string exceeds
|
@@ -156,7 +189,6 @@ class HtmlTreeView(HtmlView):
|
|
156
189
|
name=name,
|
157
190
|
parent=parent,
|
158
191
|
root_path=root_path,
|
159
|
-
css_class=css_class,
|
160
192
|
title=title,
|
161
193
|
enable_summary=enable_summary,
|
162
194
|
max_summary_len_for_str=max_summary_len_for_str,
|
@@ -174,16 +206,16 @@ class HtmlTreeView(HtmlView):
|
|
174
206
|
special_keys: Optional[Sequence[Union[int, str]]] = None,
|
175
207
|
include_keys: Optional[Iterable[Union[int, str]]] = None,
|
176
208
|
exclude_keys: Optional[Iterable[Union[int, str]]] = None,
|
209
|
+
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
210
|
+
uncollapse: Union[
|
211
|
+
KeyPathSet, base.NodeFilter, None
|
212
|
+
] = HtmlView.PresetArgValue(None),
|
177
213
|
filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
|
178
214
|
highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
179
215
|
lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
180
216
|
max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
|
181
217
|
enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
|
182
218
|
enable_key_tooltip: bool = HtmlView.PresetArgValue(True),
|
183
|
-
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
184
|
-
uncollapse: Union[
|
185
|
-
Iterable[Union[KeyPath, str]], base.NodeFilter, None
|
186
|
-
] = HtmlView.PresetArgValue(None),
|
187
219
|
**kwargs,
|
188
220
|
) -> Html:
|
189
221
|
"""Returns the main content for the object.
|
@@ -197,6 +229,10 @@ class HtmlTreeView(HtmlView):
|
|
197
229
|
level).
|
198
230
|
include_keys: The keys to include (at the immediate child level).
|
199
231
|
exclude_keys: The keys to exclude (at the immediate child level).
|
232
|
+
collapse_level: The level to collapse the tree (relative to this node).
|
233
|
+
uncollapse: A key path set (relative to root_path) for the nodes to
|
234
|
+
uncollapse. or a function with signature (path, value, parent) -> bool
|
235
|
+
to filter nodes to uncollapse.
|
200
236
|
filter: A function with signature (path, value, parent) -> include
|
201
237
|
to determine whether to include a field (at all levels).
|
202
238
|
highlight: A function with signature (path, value, parent) -> bool
|
@@ -206,8 +242,6 @@ class HtmlTreeView(HtmlView):
|
|
206
242
|
max_summary_len_for_str: The maximum length of the string to display.
|
207
243
|
enable_summary_tooltip: Whether to enable the tooltip for the summary.
|
208
244
|
enable_key_tooltip: Whether to enable the key tooltip.
|
209
|
-
collapse_level: The level to collapse the tree
|
210
|
-
uncollapse: The paths to uncollapse.
|
211
245
|
**kwargs: Additional keyword arguments passed from `pg.to_html`. These
|
212
246
|
arguments may be handled by the user logic but not the general
|
213
247
|
HtmlTreeView.
|
@@ -273,11 +307,14 @@ class HtmlTreeView(HtmlView):
|
|
273
307
|
name: Optional[str] = None,
|
274
308
|
parent: Any = None,
|
275
309
|
root_path: Optional[KeyPath] = None,
|
276
|
-
css_class: Optional[Sequence[str]] = None,
|
277
310
|
title: Union[str, Html, None] = None,
|
278
311
|
special_keys: Optional[Sequence[Union[int, str]]] = None,
|
279
312
|
include_keys: Optional[Iterable[Union[int, str]]] = None,
|
280
313
|
exclude_keys: Optional[Iterable[Union[int, str]]] = None,
|
314
|
+
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
315
|
+
uncollapse: Union[
|
316
|
+
KeyPathSet, base.NodeFilter, None
|
317
|
+
] = HtmlView.PresetArgValue(None),
|
281
318
|
filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
|
282
319
|
highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
283
320
|
lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
@@ -285,10 +322,6 @@ class HtmlTreeView(HtmlView):
|
|
285
322
|
max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
|
286
323
|
enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
|
287
324
|
enable_key_tooltip: bool = HtmlView.PresetArgValue(True),
|
288
|
-
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
289
|
-
uncollapse: Union[
|
290
|
-
Iterable[Union[KeyPath, str]], base.NodeFilter, None
|
291
|
-
] = HtmlView.PresetArgValue(None),
|
292
325
|
**kwargs
|
293
326
|
) -> Html:
|
294
327
|
"""Renders the entire HTML tree view for the value.
|
@@ -298,11 +331,14 @@ class HtmlTreeView(HtmlView):
|
|
298
331
|
name: The name of the value.
|
299
332
|
parent: The parent of the value.
|
300
333
|
root_path: The root path of the value.
|
301
|
-
css_class: The CSS classes to add to the root element
|
302
334
|
title: The title of the summary.
|
303
335
|
special_keys: The special keys to display (at the immediate child level).
|
304
336
|
include_keys: The keys to include (at the immediate child level).
|
305
337
|
exclude_keys: The keys to exclude (at the immediate child level).
|
338
|
+
collapse_level: The level to collapse the tree (relative to this node).
|
339
|
+
uncollapse: A key path set (relative to root_path) for the nodes to
|
340
|
+
uncollapse. or a function with signature (path, value, parent) -> bool
|
341
|
+
to filter nodes to uncollapse.
|
306
342
|
filter: A function with signature (path, value, parent) -> include
|
307
343
|
to determine whether to include a field (at all levels).
|
308
344
|
highlight: A function with signature (path, value, parent) -> bool
|
@@ -315,15 +351,31 @@ class HtmlTreeView(HtmlView):
|
|
315
351
|
max_summary_len_for_str: The maximum length of the string to display.
|
316
352
|
enable_summary_tooltip: Whether to enable the tooltip for the summary.
|
317
353
|
enable_key_tooltip: Whether to enable the key tooltip.
|
318
|
-
collapse_level: The level to collapse the tree.
|
319
|
-
uncollapse: The paths to uncollapse.
|
320
354
|
**kwargs: Additional keyword arguments passed from `pg.to_html`.
|
321
355
|
|
322
356
|
Returns:
|
323
357
|
The rendered HTML.
|
324
358
|
"""
|
325
359
|
root_path = root_path or KeyPath()
|
326
|
-
uncollapse = self.
|
360
|
+
uncollapse = self.init_uncollapse(uncollapse)
|
361
|
+
|
362
|
+
child_collapse_level = collapse_level
|
363
|
+
if isinstance(value, HtmlTreeView.Extension):
|
364
|
+
subtree_uncollapse_level = value._html_tree_view_uncollapse_level() # pylint: disable=protected-access
|
365
|
+
|
366
|
+
# If the extension has child levels to uncollapse, honor them above the
|
367
|
+
# collapse level passed from the root. However, we can see the
|
368
|
+
# uncollapsed extension subtree only when the extension's parent node is
|
369
|
+
# uncollapsed.
|
370
|
+
child_collapse_level = self.max_collapse_level(
|
371
|
+
collapse_level, subtree_uncollapse_level, root_path
|
372
|
+
)
|
373
|
+
if not callable(uncollapse):
|
374
|
+
extension_uncollapse = value._html_tree_view_uncollapse().copy() # pylint: disable=protected-access
|
375
|
+
if extension_uncollapse:
|
376
|
+
extension_uncollapse.rebase(root_path)
|
377
|
+
uncollapse = uncollapse.union(extension_uncollapse)
|
378
|
+
|
327
379
|
summary = self.summary(
|
328
380
|
value,
|
329
381
|
name=name,
|
@@ -340,21 +392,25 @@ class HtmlTreeView(HtmlView):
|
|
340
392
|
name=name,
|
341
393
|
parent=parent,
|
342
394
|
root_path=root_path,
|
343
|
-
css_class=css_class if summary is None else None,
|
344
395
|
filter=filter,
|
345
396
|
special_keys=special_keys,
|
346
397
|
include_keys=include_keys,
|
347
398
|
exclude_keys=exclude_keys,
|
399
|
+
collapse_level=child_collapse_level,
|
400
|
+
uncollapse=uncollapse,
|
348
401
|
max_summary_len_for_str=max_summary_len_for_str,
|
349
402
|
enable_summary_tooltip=enable_summary_tooltip,
|
350
403
|
enable_key_tooltip=enable_key_tooltip,
|
351
|
-
collapse_level=collapse_level,
|
352
|
-
uncollapse=uncollapse,
|
353
404
|
**kwargs,
|
354
405
|
)
|
406
|
+
extension_style = (
|
407
|
+
value._html_style() if isinstance(value, HtmlView.Extension) else [] # pylint: disable=protected-access
|
408
|
+
)
|
409
|
+
|
355
410
|
if summary is None:
|
356
411
|
content = Html.from_value(content)
|
357
412
|
assert content is not None
|
413
|
+
content.add_style(*extension_style)
|
358
414
|
return content
|
359
415
|
|
360
416
|
collapse_view = self.should_collapse(
|
@@ -371,7 +427,7 @@ class HtmlTreeView(HtmlView):
|
|
371
427
|
css_class=[
|
372
428
|
'pyglove',
|
373
429
|
self.css_class_name(value),
|
374
|
-
]
|
430
|
+
],
|
375
431
|
).add_style(
|
376
432
|
"""
|
377
433
|
/* Value details styles. */
|
@@ -393,29 +449,23 @@ class HtmlTreeView(HtmlView):
|
|
393
449
|
.lowlight {
|
394
450
|
opacity: 0.2;
|
395
451
|
}
|
396
|
-
"""
|
452
|
+
""",
|
453
|
+
*extension_style,
|
397
454
|
)
|
398
455
|
|
399
|
-
def
|
456
|
+
def init_uncollapse(
|
400
457
|
self,
|
401
458
|
uncollapse: Union[
|
402
459
|
Iterable[Union[KeyPath, str]], base.NodeFilter, None
|
403
460
|
] = HtmlView.PresetArgValue(None),
|
404
|
-
) -> Union[
|
461
|
+
) -> Union[KeyPathSet, base.NodeFilter]:
|
405
462
|
"""Normalize the uncollapse argument."""
|
406
463
|
if uncollapse is None:
|
407
|
-
return
|
408
|
-
elif
|
464
|
+
return KeyPathSet()
|
465
|
+
elif callable(uncollapse):
|
409
466
|
return uncollapse
|
410
467
|
else:
|
411
|
-
|
412
|
-
for path in uncollapse:
|
413
|
-
path = object_utils.KeyPath.from_value(path)
|
414
|
-
expanded.add(path)
|
415
|
-
while path:
|
416
|
-
expanded.add(path.parent)
|
417
|
-
path = path.parent
|
418
|
-
return expanded
|
468
|
+
return KeyPathSet.from_value(uncollapse, include_intermediate=True)
|
419
469
|
|
420
470
|
def should_collapse(
|
421
471
|
self,
|
@@ -423,16 +473,12 @@ class HtmlTreeView(HtmlView):
|
|
423
473
|
root_path: KeyPath,
|
424
474
|
parent: Any,
|
425
475
|
collapse_level: Optional[int] = 0,
|
426
|
-
uncollapse: Union[
|
427
|
-
Set[Union[KeyPath, str]], base.NodeFilter, None
|
428
|
-
] = None,
|
476
|
+
uncollapse: Union[KeyPathSet, base.NodeFilter] = None,
|
429
477
|
) -> bool:
|
430
478
|
"""Returns whether the object should be collapsed."""
|
431
479
|
if collapse_level is None or root_path.depth < collapse_level:
|
432
480
|
return False
|
433
|
-
if uncollapse
|
434
|
-
return True
|
435
|
-
elif callable(uncollapse):
|
481
|
+
if callable(uncollapse):
|
436
482
|
return not uncollapse(root_path, value, parent)
|
437
483
|
else:
|
438
484
|
return root_path not in uncollapse
|
@@ -468,7 +514,6 @@ class HtmlTreeView(HtmlView):
|
|
468
514
|
name: Optional[str] = None,
|
469
515
|
parent: Any = None,
|
470
516
|
root_path: Optional[KeyPath] = None,
|
471
|
-
css_class: Optional[Sequence[str]] = None,
|
472
517
|
title: Union[str, Html, None] = None,
|
473
518
|
enable_summary: Optional[bool] = HtmlView.PresetArgValue(None),
|
474
519
|
enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
|
@@ -482,7 +527,6 @@ class HtmlTreeView(HtmlView):
|
|
482
527
|
name: The name of the value.
|
483
528
|
parent: The parent of the value.
|
484
529
|
root_path: The root path of the value.
|
485
|
-
css_class: The CSS classes to add to the root element
|
486
530
|
title: The title of the summary.
|
487
531
|
enable_summary: Whether to enable the summary. If None, summary will
|
488
532
|
be enabled for complex types or when string exceeds
|
@@ -542,7 +586,6 @@ class HtmlTreeView(HtmlView):
|
|
542
586
|
**kwargs,
|
543
587
|
) if enable_summary_tooltip else None,
|
544
588
|
],
|
545
|
-
css_class=css_class,
|
546
589
|
).add_style(
|
547
590
|
"""
|
548
591
|
/* Summary styles. */
|
@@ -583,7 +626,7 @@ class HtmlTreeView(HtmlView):
|
|
583
626
|
name: Optional[str] = None,
|
584
627
|
parent: Any,
|
585
628
|
root_path: Optional[KeyPath] = None,
|
586
|
-
css_class:
|
629
|
+
css_class: Union[str, Sequence[str], None] = None,
|
587
630
|
key_color: Optional[str] = None,
|
588
631
|
enable_tooltip: bool = HtmlView.PresetArgValue(True),
|
589
632
|
**kwargs
|
@@ -595,7 +638,7 @@ class HtmlTreeView(HtmlView):
|
|
595
638
|
name: The name of the value.
|
596
639
|
parent: The parent value of the key.
|
597
640
|
root_path: The root path of the value.
|
598
|
-
css_class:
|
641
|
+
css_class: Additional CSS classes to add to the HTML element.
|
599
642
|
key_color: The color of the key.
|
600
643
|
enable_tooltip: Whether to enable the tooltip.
|
601
644
|
**kwargs: Additional keyword arguments passed from `pg.to_html`.
|
@@ -610,7 +653,11 @@ class HtmlTreeView(HtmlView):
|
|
610
653
|
[
|
611
654
|
str(key),
|
612
655
|
],
|
613
|
-
css_class=[
|
656
|
+
css_class=[
|
657
|
+
'object_key',
|
658
|
+
type(key).__name__,
|
659
|
+
css_class,
|
660
|
+
],
|
614
661
|
style=dict(
|
615
662
|
color=key_color,
|
616
663
|
)
|
@@ -634,26 +681,26 @@ class HtmlTreeView(HtmlView):
|
|
634
681
|
visibility: visible;
|
635
682
|
background-color: darkblue;
|
636
683
|
}
|
637
|
-
.
|
684
|
+
.object_key.str {
|
638
685
|
color: gray;
|
639
686
|
border: 1px solid lightgray;
|
640
687
|
background-color: ButtonFace;
|
641
688
|
border-radius: 0.2em;
|
642
689
|
padding: 0.3em;
|
643
690
|
}
|
644
|
-
.
|
691
|
+
.object_key.int::before{
|
692
|
+
content: '[';
|
693
|
+
}
|
694
|
+
.object_key.int::after{
|
695
|
+
content: ']';
|
696
|
+
}
|
697
|
+
.object_key.int{
|
645
698
|
border: 0;
|
646
699
|
color: lightgray;
|
647
700
|
background-color: transparent;
|
648
701
|
border-radius: 0;
|
649
702
|
padding: 0;
|
650
703
|
}
|
651
|
-
.complex_value.list .object_key::before{
|
652
|
-
content: '[';
|
653
|
-
}
|
654
|
-
.complex_value.list .object_key::after{
|
655
|
-
content: ']';
|
656
|
-
}
|
657
704
|
"""
|
658
705
|
)
|
659
706
|
|
@@ -665,20 +712,19 @@ class HtmlTreeView(HtmlView):
|
|
665
712
|
name: Optional[str] = None,
|
666
713
|
parent: Any = None,
|
667
714
|
root_path: Optional[KeyPath] = None,
|
668
|
-
css_class: Optional[Sequence[str]] = None,
|
669
715
|
special_keys: Optional[Sequence[Union[int, str]]] = None,
|
670
716
|
include_keys: Optional[Iterable[Union[int, str]]] = None,
|
671
717
|
exclude_keys: Optional[Iterable[Union[int, str]]] = None,
|
718
|
+
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
719
|
+
uncollapse: Union[
|
720
|
+
KeyPathSet, base.NodeFilter, None
|
721
|
+
] = HtmlView.PresetArgValue(None),
|
672
722
|
filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
|
673
723
|
highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
674
724
|
lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
675
725
|
max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
|
676
726
|
enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
|
677
727
|
enable_key_tooltip: bool = HtmlView.PresetArgValue(True),
|
678
|
-
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
679
|
-
uncollapse: Union[
|
680
|
-
Iterable[Union[KeyPath, str]], base.NodeFilter, None
|
681
|
-
] = HtmlView.PresetArgValue(None),
|
682
728
|
**kwargs
|
683
729
|
) -> Html:
|
684
730
|
"""Renders the main content for the value.
|
@@ -688,10 +734,13 @@ class HtmlTreeView(HtmlView):
|
|
688
734
|
name: The name of the value.
|
689
735
|
parent: The parent of the value.
|
690
736
|
root_path: The root path of the value.
|
691
|
-
css_class: Additional CSS classes for root element.
|
692
737
|
special_keys: The special keys to display (at the immediate child level).
|
693
738
|
include_keys: The keys to include (at the immediate child level).
|
694
739
|
exclude_keys: The keys to exclude (at the immediate child level).
|
740
|
+
collapse_level: The level to collapse the tree (relative to this node).
|
741
|
+
uncollapse: A key path set (relative to root_path) for the nodes to
|
742
|
+
uncollapse. or a function with signature (path, value, parent) -> bool
|
743
|
+
to filter nodes to uncollapse.
|
695
744
|
filter: A function with signature (path, value, parent) -> include
|
696
745
|
to determine whether to include a field (at all levels).
|
697
746
|
highlight: A function with signature (path, value, parent) -> bool
|
@@ -701,8 +750,6 @@ class HtmlTreeView(HtmlView):
|
|
701
750
|
max_summary_len_for_str: The maximum length of the string to display.
|
702
751
|
enable_summary_tooltip: Whether to enable the summary tooltip.
|
703
752
|
enable_key_tooltip: Whether to enable the key tooltip.
|
704
|
-
collapse_level: The level of the tree to collapse.
|
705
|
-
uncollapse: The keys to uncollapse.
|
706
753
|
**kwargs: Additional keyword arguments passed from `pg.to_html`.
|
707
754
|
|
708
755
|
Returns:
|
@@ -715,25 +762,24 @@ class HtmlTreeView(HtmlView):
|
|
715
762
|
else:
|
716
763
|
return self.simple_value(
|
717
764
|
value, name=name, parent=parent, root_path=root_path,
|
718
|
-
|
765
|
+
max_summary_len_for_str=max_summary_len_for_str
|
719
766
|
)
|
720
767
|
return self.complex_value(
|
721
768
|
items,
|
722
769
|
name=name,
|
723
770
|
parent=value,
|
724
771
|
root_path=root_path or KeyPath(),
|
725
|
-
css_class=css_class,
|
726
772
|
special_keys=special_keys,
|
727
773
|
include_keys=include_keys,
|
728
774
|
exclude_keys=exclude_keys,
|
775
|
+
collapse_level=collapse_level,
|
776
|
+
uncollapse=uncollapse,
|
729
777
|
filter=filter,
|
730
778
|
highlight=highlight,
|
731
779
|
lowlight=lowlight,
|
732
780
|
max_summary_len_for_str=max_summary_len_for_str,
|
733
781
|
enable_summary_tooltip=enable_summary_tooltip,
|
734
782
|
enable_key_tooltip=enable_key_tooltip,
|
735
|
-
collapse_level=collapse_level,
|
736
|
-
uncollapse=uncollapse,
|
737
783
|
**kwargs,
|
738
784
|
)
|
739
785
|
|
@@ -744,7 +790,7 @@ class HtmlTreeView(HtmlView):
|
|
744
790
|
name: Optional[str] = None,
|
745
791
|
parent: Any = None,
|
746
792
|
root_path: Optional[KeyPath] = None,
|
747
|
-
css_class:
|
793
|
+
css_class: Union[str, Sequence[str], None] = None,
|
748
794
|
max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
|
749
795
|
) -> Html:
|
750
796
|
"""Renders a simple value.
|
@@ -754,7 +800,7 @@ class HtmlTreeView(HtmlView):
|
|
754
800
|
name: The name of the value.
|
755
801
|
parent: The parent of the value.
|
756
802
|
root_path: The root path of the value.
|
757
|
-
css_class: Additional CSS classes
|
803
|
+
css_class: Additional CSS classes to add to the HTML element.
|
758
804
|
max_summary_len_for_str: The maximum length of the string to display.
|
759
805
|
|
760
806
|
Returns:
|
@@ -778,9 +824,11 @@ class HtmlTreeView(HtmlView):
|
|
778
824
|
[
|
779
825
|
Html.escape(value_repr),
|
780
826
|
],
|
781
|
-
css_class=[
|
782
|
-
|
783
|
-
|
827
|
+
css_class=[
|
828
|
+
'simple_value',
|
829
|
+
self.css_class_name(value),
|
830
|
+
css_class,
|
831
|
+
],
|
784
832
|
).add_style(
|
785
833
|
"""
|
786
834
|
/* Simple value styles. */
|
@@ -805,36 +853,48 @@ class HtmlTreeView(HtmlView):
|
|
805
853
|
self,
|
806
854
|
kv: Dict[Union[int, str], Any],
|
807
855
|
*,
|
856
|
+
parent: Any,
|
857
|
+
root_path: KeyPath,
|
808
858
|
name: Optional[str] = None,
|
809
|
-
|
810
|
-
|
811
|
-
|
859
|
+
css_class: Union[str, Sequence[str], None] = None,
|
860
|
+
render_key_fn: Optional[Callable[..., Html]] = None,
|
861
|
+
render_value_fn: Optional[Callable[..., Html]] = None,
|
812
862
|
special_keys: Optional[Sequence[Union[int, str]]] = None,
|
813
863
|
include_keys: Optional[Iterable[Union[int, str]]] = None,
|
814
864
|
exclude_keys: Optional[Iterable[Union[int, str]]] = None,
|
865
|
+
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
866
|
+
uncollapse: Union[
|
867
|
+
KeyPathSet, base.NodeFilter, None
|
868
|
+
] = HtmlView.PresetArgValue(None),
|
815
869
|
filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
|
816
870
|
highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
817
871
|
lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
|
818
872
|
max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
|
819
873
|
enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
|
820
874
|
enable_key_tooltip: bool = HtmlView.PresetArgValue(True),
|
821
|
-
collapse_level: Optional[int] = HtmlView.PresetArgValue(1),
|
822
|
-
uncollapse: Union[
|
823
|
-
Iterable[Union[KeyPath, str]], base.NodeFilter, None
|
824
|
-
] = HtmlView.PresetArgValue(None),
|
825
875
|
**kwargs,
|
826
876
|
) -> Html:
|
827
877
|
"""Renders a list of key-value pairs.
|
828
878
|
|
829
879
|
Args:
|
830
880
|
kv: The key-value pairs to render.
|
831
|
-
name: The name of the value.
|
832
881
|
parent: The parent value of the key-value pairs.
|
833
882
|
root_path: The root path of the value.
|
834
|
-
|
883
|
+
name: The name of the value.
|
884
|
+
css_class: Additional CSS classes to add to the HTML element.
|
885
|
+
render_key_fn: A function to render the key. The function has the
|
886
|
+
same signature as `HtmlTreeView.object_key`.
|
887
|
+
If None, `HtmlTreeView.object_key` will be used to render the key.
|
888
|
+
render_value_fn: A function to render the value. The function has the
|
889
|
+
same signature as `HtmlTreeView.render`.
|
890
|
+
If None, `HtmlTreeView.render` will be used to render child value.
|
835
891
|
special_keys: The special keys to display (at the immediate child level).
|
836
892
|
include_keys: The keys to include (at the immediate child level).
|
837
893
|
exclude_keys: The keys to exclude (at the immediate child level).
|
894
|
+
collapse_level: The level to collapse the tree (relative to this node).
|
895
|
+
uncollapse: A key path set (relative to root_path) for the nodes to
|
896
|
+
uncollapse. or a function with signature (path, value, parent) -> bool
|
897
|
+
to filter nodes to uncollapse.
|
838
898
|
filter: A function with signature (path, value, parent) -> include
|
839
899
|
to determine whether to include.
|
840
900
|
highlight: A function with signature (path, value, parent) -> bool
|
@@ -844,18 +904,26 @@ class HtmlTreeView(HtmlView):
|
|
844
904
|
max_summary_len_for_str: The maximum length of the string to display.
|
845
905
|
enable_summary_tooltip: Whether to enable the summary tooltip.
|
846
906
|
enable_key_tooltip: Whether to enable the key tooltip.
|
847
|
-
collapse_level: The level of the tree to collapse.
|
848
|
-
uncollapse: The keys to uncollapse.
|
849
907
|
**kwargs: Additional keyword arguments passed from `pg.to_html`.
|
850
908
|
|
851
909
|
Returns:
|
852
910
|
The rendered HTML as the key-value pairs.
|
853
911
|
"""
|
854
912
|
del name
|
913
|
+
root_path = root_path or KeyPath()
|
914
|
+
uncollapse = self.init_uncollapse(uncollapse)
|
915
|
+
|
916
|
+
if isinstance(parent, HtmlTreeView.Extension):
|
917
|
+
special_keys = special_keys or parent._html_tree_view_special_keys() # pylint: disable=protected-access
|
918
|
+
include_keys = include_keys or parent._html_tree_view_include_keys() # pylint: disable=protected-access
|
919
|
+
exclude_keys = exclude_keys or parent._html_tree_view_exclude_keys() # pylint: disable=protected-access
|
920
|
+
|
855
921
|
special_keys = special_keys or []
|
856
922
|
include_keys = set(include_keys or [])
|
857
923
|
exclude_keys = set(exclude_keys or [])
|
858
|
-
|
924
|
+
|
925
|
+
render_key_fn = render_key_fn or self.object_key
|
926
|
+
render_value_fn = render_value_fn or self.render
|
859
927
|
|
860
928
|
s = Html()
|
861
929
|
if kv:
|
@@ -873,37 +941,40 @@ class HtmlTreeView(HtmlView):
|
|
873
941
|
if k in include_keys and k in kv:
|
874
942
|
child_path = root_path + k
|
875
943
|
v = kv[k]
|
876
|
-
|
877
|
-
child_css_class = [
|
878
|
-
'special_value',
|
879
|
-
(
|
880
|
-
'highlight' if highlight
|
881
|
-
and highlight(child_path, v, parent) else None
|
882
|
-
),
|
883
|
-
(
|
884
|
-
'lowlight' if lowlight
|
885
|
-
and lowlight(child_path, v, parent) else None
|
886
|
-
)
|
887
|
-
]
|
888
944
|
s.write(
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
|
897
|
-
|
898
|
-
|
899
|
-
|
900
|
-
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
945
|
+
Html.element(
|
946
|
+
'div',
|
947
|
+
[
|
948
|
+
render_value_fn(
|
949
|
+
value=v,
|
950
|
+
name=k,
|
951
|
+
parent=parent,
|
952
|
+
root_path=child_path,
|
953
|
+
filter=filter,
|
954
|
+
special_keys=None,
|
955
|
+
include_keys=None,
|
956
|
+
exclude_keys=None,
|
957
|
+
collapse_level=collapse_level,
|
958
|
+
uncollapse=uncollapse,
|
959
|
+
highlight=highlight,
|
960
|
+
lowlight=lowlight,
|
961
|
+
max_summary_len_for_str=max_summary_len_for_str,
|
962
|
+
enable_summary_tooltip=enable_summary_tooltip,
|
963
|
+
enable_key_tooltip=enable_key_tooltip,
|
964
|
+
**kwargs
|
965
|
+
)
|
966
|
+
],
|
967
|
+
css_class=[
|
968
|
+
'special_value',
|
969
|
+
(
|
970
|
+
'highlight' if highlight
|
971
|
+
and highlight(child_path, v, parent) else None
|
972
|
+
),
|
973
|
+
(
|
974
|
+
'lowlight' if lowlight
|
975
|
+
and lowlight(child_path, v, parent) else None
|
976
|
+
)
|
977
|
+
],
|
907
978
|
)
|
908
979
|
)
|
909
980
|
include_keys.remove(k)
|
@@ -914,45 +985,51 @@ class HtmlTreeView(HtmlView):
|
|
914
985
|
if k not in include_keys:
|
915
986
|
continue
|
916
987
|
child_path = root_path + k
|
917
|
-
|
918
|
-
key=k,
|
988
|
+
key_cell = render_key_fn(
|
989
|
+
key=k,
|
990
|
+
parent=parent,
|
991
|
+
root_path=child_path,
|
919
992
|
enable_tooltip=enable_key_tooltip,
|
920
993
|
)
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
|
933
|
-
|
934
|
-
|
935
|
-
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
|
940
|
-
|
941
|
-
|
942
|
-
|
943
|
-
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
994
|
+
value_cell = Html.element(
|
995
|
+
'div',
|
996
|
+
[
|
997
|
+
render_value_fn(
|
998
|
+
value=v,
|
999
|
+
name=None,
|
1000
|
+
parent=parent,
|
1001
|
+
root_path=child_path,
|
1002
|
+
special_keys=None,
|
1003
|
+
include_keys=None,
|
1004
|
+
exclude_keys=None,
|
1005
|
+
collapse_level=collapse_level,
|
1006
|
+
uncollapse=uncollapse,
|
1007
|
+
filter=filter,
|
1008
|
+
highlight=highlight,
|
1009
|
+
lowlight=lowlight,
|
1010
|
+
max_summary_len_for_str=max_summary_len_for_str,
|
1011
|
+
enable_summary_tooltip=enable_summary_tooltip,
|
1012
|
+
enable_key_tooltip=enable_key_tooltip,
|
1013
|
+
**kwargs,
|
1014
|
+
)
|
1015
|
+
],
|
1016
|
+
css_class=[
|
1017
|
+
(
|
1018
|
+
'highlight' if highlight
|
1019
|
+
and highlight(child_path, v, parent) else None
|
1020
|
+
),
|
1021
|
+
(
|
1022
|
+
'lowlight' if lowlight
|
1023
|
+
and lowlight(child_path, v, parent) else None
|
1024
|
+
)
|
1025
|
+
],
|
949
1026
|
)
|
950
1027
|
s.write(
|
951
1028
|
Html.element(
|
952
1029
|
'tr',
|
953
1030
|
[
|
954
|
-
'<td>',
|
955
|
-
'<td>',
|
1031
|
+
'<td>', key_cell, '</td>',
|
1032
|
+
'<td>', value_cell, '</td>',
|
956
1033
|
],
|
957
1034
|
)
|
958
1035
|
)
|
@@ -962,9 +1039,11 @@ class HtmlTreeView(HtmlView):
|
|
962
1039
|
return Html.element(
|
963
1040
|
'div',
|
964
1041
|
[s],
|
965
|
-
css_class=[
|
966
|
-
|
967
|
-
|
1042
|
+
css_class=[
|
1043
|
+
'complex_value',
|
1044
|
+
self.css_class_name(parent),
|
1045
|
+
css_class,
|
1046
|
+
]
|
968
1047
|
).add_style(
|
969
1048
|
"""
|
970
1049
|
/* Complex value styles. */
|
@@ -985,7 +1064,6 @@ class HtmlTreeView(HtmlView):
|
|
985
1064
|
name: Optional[str] = None,
|
986
1065
|
parent: Any = None,
|
987
1066
|
root_path: Optional[KeyPath] = None,
|
988
|
-
css_class: Optional[Sequence[str]] = None,
|
989
1067
|
content: Union[str, Html, None] = HtmlView.PresetArgValue(None),
|
990
1068
|
**kwargs
|
991
1069
|
) -> Html:
|
@@ -996,7 +1074,6 @@ class HtmlTreeView(HtmlView):
|
|
996
1074
|
name: The name of the value.
|
997
1075
|
parent: The parent value of the key-value pairs.
|
998
1076
|
root_path: The root path of the value.
|
999
|
-
css_class: Additional CSS classes for the tooltip span.
|
1000
1077
|
content: The content of the tooltip. If None, the formatted value will be
|
1001
1078
|
used as the content.
|
1002
1079
|
**kwargs: Additional keyword arguments passed from `pg.to_html`.
|
@@ -1021,7 +1098,7 @@ class HtmlTreeView(HtmlView):
|
|
1021
1098
|
return Html.element(
|
1022
1099
|
'span',
|
1023
1100
|
[content],
|
1024
|
-
css_class=['tooltip'
|
1101
|
+
css_class=['tooltip', self.css_class_name(value)],
|
1025
1102
|
).add_style(
|
1026
1103
|
"""
|
1027
1104
|
/* Tooltip styles. */
|
@@ -1040,11 +1117,23 @@ class HtmlTreeView(HtmlView):
|
|
1040
1117
|
)
|
1041
1118
|
|
1042
1119
|
@staticmethod
|
1043
|
-
def css_class_name(value: Any) -> str:
|
1120
|
+
def css_class_name(value: Any) -> Optional[str]:
|
1044
1121
|
"""Returns the CSS class name for the value."""
|
1122
|
+
if isinstance(value, HtmlTreeView.Extension):
|
1123
|
+
return Html.concate(value._html_element_class()) # pylint: disable=protected-access
|
1045
1124
|
value = value if inspect.isclass(value) else type(value)
|
1046
|
-
|
1047
|
-
|
1125
|
+
return object_utils.camel_to_snake(value.__name__, '-')
|
1126
|
+
|
1127
|
+
@staticmethod
|
1128
|
+
def max_collapse_level(
|
1129
|
+
original_level: int | None,
|
1130
|
+
subtree_uncollapse_level: int | None,
|
1131
|
+
root_path: KeyPath
|
1132
|
+
) -> int | None:
|
1133
|
+
"""Consolidates the collapse level."""
|
1134
|
+
if original_level is None or subtree_uncollapse_level is None:
|
1135
|
+
return None
|
1136
|
+
return max(original_level, root_path.depth + subtree_uncollapse_level)
|
1048
1137
|
|
1049
1138
|
|
1050
1139
|
_REGEX_CAMEL_TO_SNAKE = re.compile(r'(?<!^)(?=[A-Z])')
|