pyglove 0.4.5.dev202410100808__py3-none-any.whl → 0.4.5.dev202410110808__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.
@@ -15,13 +15,14 @@
15
15
 
16
16
  import inspect
17
17
  import re
18
- from typing import Any, Dict, Iterable, Optional, Sequence, Set, Union
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,34 @@ 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_collapse_level(self) -> int:
58
+ """Returns the level to collapse the tree (relative to this node)."""
59
+ return 0
60
+
61
+ def _html_tree_view_uncollapse(self) -> KeyPathSet:
62
+ """Returns the node paths (relative to current node) to uncollapse."""
63
+ return KeyPathSet()
64
+
65
+ #
66
+ # Default behavior overrides.
67
+ #
68
+
40
69
  def _html_tree_view_render(
41
70
  self,
42
71
  *,
@@ -48,6 +77,8 @@ class HtmlTreeView(HtmlView):
48
77
  special_keys: Optional[Sequence[Union[int, str]]] = None,
49
78
  include_keys: Optional[Iterable[Union[int, str]]] = None,
50
79
  exclude_keys: Optional[Iterable[Union[int, str]]] = None,
80
+ collapse_level: Optional[int] = 1,
81
+ uncollapse: Union[KeyPathSet, base.NodeFilter, None] = None,
51
82
  filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
52
83
  highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
53
84
  lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
@@ -55,10 +86,6 @@ class HtmlTreeView(HtmlView):
55
86
  max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
56
87
  enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
57
88
  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
89
  **kwargs,
63
90
  ) -> Html:
64
91
  """Returns the topmost HTML representation of the object.
@@ -73,6 +100,10 @@ class HtmlTreeView(HtmlView):
73
100
  level).
74
101
  include_keys: The keys to include (at the immediate child level).
75
102
  exclude_keys: The keys to exclude (at the immediate child level).
103
+ collapse_level: The level to collapse the tree (relative to this node).
104
+ uncollapse: A key path set (relative to root_path) for the nodes to
105
+ uncollapse. or a function with signature (path, value, parent) -> bool
106
+ to filter nodes to uncollapse.
76
107
  filter: A function with signature (path, value, parent) -> include
77
108
  to determine whether to include a field (at all levels).
78
109
  highlight: A function with signature (path, value, parent) -> bool
@@ -85,10 +116,6 @@ class HtmlTreeView(HtmlView):
85
116
  max_summary_len_for_str: The maximum length of the string to display.
86
117
  enable_summary_tooltip: Whether to enable the tooltip for the summary.
87
118
  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
119
  **kwargs: Additional keyword arguments passed from `pg.to_html`.
93
120
 
94
121
  Returns:
@@ -122,7 +149,6 @@ class HtmlTreeView(HtmlView):
122
149
  name: Optional[str],
123
150
  parent: Any,
124
151
  root_path: KeyPath,
125
- css_class: Optional[Sequence[str]] = None,
126
152
  title: Union[str, Html, None] = None,
127
153
  enable_summary: Optional[bool] = HtmlView.PresetArgValue(None),
128
154
  max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
@@ -136,7 +162,6 @@ class HtmlTreeView(HtmlView):
136
162
  name: The name of the object.
137
163
  parent: The parent of the object.
138
164
  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
165
  title: The title of the summary.
141
166
  enable_summary: Whether to enable the summary. If None, summary will
142
167
  be enabled for complex types or when string exceeds
@@ -156,7 +181,6 @@ class HtmlTreeView(HtmlView):
156
181
  name=name,
157
182
  parent=parent,
158
183
  root_path=root_path,
159
- css_class=css_class,
160
184
  title=title,
161
185
  enable_summary=enable_summary,
162
186
  max_summary_len_for_str=max_summary_len_for_str,
@@ -174,16 +198,14 @@ class HtmlTreeView(HtmlView):
174
198
  special_keys: Optional[Sequence[Union[int, str]]] = None,
175
199
  include_keys: Optional[Iterable[Union[int, str]]] = None,
176
200
  exclude_keys: Optional[Iterable[Union[int, str]]] = None,
201
+ collapse_level: Optional[int] = 1,
202
+ uncollapse: Union[KeyPathSet, base.NodeFilter, None] = None,
177
203
  filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
178
204
  highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
179
205
  lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
180
206
  max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
181
207
  enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
182
208
  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
209
  **kwargs,
188
210
  ) -> Html:
189
211
  """Returns the main content for the object.
@@ -197,6 +219,10 @@ class HtmlTreeView(HtmlView):
197
219
  level).
198
220
  include_keys: The keys to include (at the immediate child level).
199
221
  exclude_keys: The keys to exclude (at the immediate child level).
222
+ collapse_level: The level to collapse the tree (relative to this node).
223
+ uncollapse: A key path set (relative to root_path) for the nodes to
224
+ uncollapse. or a function with signature (path, value, parent) -> bool
225
+ to filter nodes to uncollapse.
200
226
  filter: A function with signature (path, value, parent) -> include
201
227
  to determine whether to include a field (at all levels).
202
228
  highlight: A function with signature (path, value, parent) -> bool
@@ -206,8 +232,6 @@ class HtmlTreeView(HtmlView):
206
232
  max_summary_len_for_str: The maximum length of the string to display.
207
233
  enable_summary_tooltip: Whether to enable the tooltip for the summary.
208
234
  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
235
  **kwargs: Additional keyword arguments passed from `pg.to_html`. These
212
236
  arguments may be handled by the user logic but not the general
213
237
  HtmlTreeView.
@@ -273,11 +297,12 @@ class HtmlTreeView(HtmlView):
273
297
  name: Optional[str] = None,
274
298
  parent: Any = None,
275
299
  root_path: Optional[KeyPath] = None,
276
- css_class: Optional[Sequence[str]] = None,
277
300
  title: Union[str, Html, None] = None,
278
301
  special_keys: Optional[Sequence[Union[int, str]]] = None,
279
302
  include_keys: Optional[Iterable[Union[int, str]]] = None,
280
303
  exclude_keys: Optional[Iterable[Union[int, str]]] = None,
304
+ collapse_level: Optional[int] = 1,
305
+ uncollapse: Union[KeyPathSet, base.NodeFilter, None] = None,
281
306
  filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
282
307
  highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
283
308
  lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
@@ -285,10 +310,6 @@ class HtmlTreeView(HtmlView):
285
310
  max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
286
311
  enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
287
312
  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
313
  **kwargs
293
314
  ) -> Html:
294
315
  """Renders the entire HTML tree view for the value.
@@ -298,11 +319,14 @@ class HtmlTreeView(HtmlView):
298
319
  name: The name of the value.
299
320
  parent: The parent of the value.
300
321
  root_path: The root path of the value.
301
- css_class: The CSS classes to add to the root element
302
322
  title: The title of the summary.
303
323
  special_keys: The special keys to display (at the immediate child level).
304
324
  include_keys: The keys to include (at the immediate child level).
305
325
  exclude_keys: The keys to exclude (at the immediate child level).
326
+ collapse_level: The level to collapse the tree (relative to this node).
327
+ uncollapse: A key path set (relative to root_path) for the nodes to
328
+ uncollapse. or a function with signature (path, value, parent) -> bool
329
+ to filter nodes to uncollapse.
306
330
  filter: A function with signature (path, value, parent) -> include
307
331
  to determine whether to include a field (at all levels).
308
332
  highlight: A function with signature (path, value, parent) -> bool
@@ -315,15 +339,31 @@ class HtmlTreeView(HtmlView):
315
339
  max_summary_len_for_str: The maximum length of the string to display.
316
340
  enable_summary_tooltip: Whether to enable the tooltip for the summary.
317
341
  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
342
  **kwargs: Additional keyword arguments passed from `pg.to_html`.
321
343
 
322
344
  Returns:
323
345
  The rendered HTML.
324
346
  """
325
347
  root_path = root_path or KeyPath()
326
- uncollapse = self.normalize_uncollapse(uncollapse)
348
+ uncollapse = self.init_uncollapse(uncollapse)
349
+
350
+ if isinstance(value, HtmlTreeView.Extension):
351
+ extension_collapse_level = value._html_tree_view_collapse_level() # pylint: disable=protected-access
352
+
353
+ # If the extension has child levels to uncollapse, honor them above the
354
+ # collapse level passed from the root. However, we can see the
355
+ # uncollapsed extension subtree only when the extension's parent node is
356
+ # uncollapsed.
357
+ if (extension_collapse_level > 0
358
+ and root_path.depth + extension_collapse_level > collapse_level):
359
+ collapse_level = root_path.depth + extension_collapse_level
360
+
361
+ if not callable(uncollapse):
362
+ extension_uncollapse = value._html_tree_view_uncollapse().copy() # pylint: disable=protected-access
363
+ if extension_uncollapse:
364
+ extension_uncollapse.rebase(root_path)
365
+ uncollapse = uncollapse.union(extension_uncollapse)
366
+
327
367
  summary = self.summary(
328
368
  value,
329
369
  name=name,
@@ -340,21 +380,25 @@ class HtmlTreeView(HtmlView):
340
380
  name=name,
341
381
  parent=parent,
342
382
  root_path=root_path,
343
- css_class=css_class if summary is None else None,
344
383
  filter=filter,
345
384
  special_keys=special_keys,
346
385
  include_keys=include_keys,
347
386
  exclude_keys=exclude_keys,
387
+ collapse_level=collapse_level,
388
+ uncollapse=uncollapse,
348
389
  max_summary_len_for_str=max_summary_len_for_str,
349
390
  enable_summary_tooltip=enable_summary_tooltip,
350
391
  enable_key_tooltip=enable_key_tooltip,
351
- collapse_level=collapse_level,
352
- uncollapse=uncollapse,
353
392
  **kwargs,
354
393
  )
394
+ extension_style = (
395
+ value._html_style() if isinstance(value, HtmlView.Extension) else [] # pylint: disable=protected-access
396
+ )
397
+
355
398
  if summary is None:
356
399
  content = Html.from_value(content)
357
400
  assert content is not None
401
+ content.add_style(*extension_style)
358
402
  return content
359
403
 
360
404
  collapse_view = self.should_collapse(
@@ -371,7 +415,7 @@ class HtmlTreeView(HtmlView):
371
415
  css_class=[
372
416
  'pyglove',
373
417
  self.css_class_name(value),
374
- ] + (css_class or []),
418
+ ],
375
419
  ).add_style(
376
420
  """
377
421
  /* Value details styles. */
@@ -393,29 +437,23 @@ class HtmlTreeView(HtmlView):
393
437
  .lowlight {
394
438
  opacity: 0.2;
395
439
  }
396
- """
440
+ """,
441
+ *extension_style,
397
442
  )
398
443
 
399
- def normalize_uncollapse(
444
+ def init_uncollapse(
400
445
  self,
401
446
  uncollapse: Union[
402
447
  Iterable[Union[KeyPath, str]], base.NodeFilter, None
403
448
  ] = HtmlView.PresetArgValue(None),
404
- ) -> Union[None, Set[KeyPath], base.NodeFilter]:
449
+ ) -> Union[KeyPathSet, base.NodeFilter]:
405
450
  """Normalize the uncollapse argument."""
406
451
  if uncollapse is None:
407
- return None
408
- elif isinstance(uncollapse, set) or callable(uncollapse):
452
+ return KeyPathSet()
453
+ elif callable(uncollapse):
409
454
  return uncollapse
410
455
  else:
411
- expanded = set()
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
456
+ return KeyPathSet.from_value(uncollapse, include_intermediate=True)
419
457
 
420
458
  def should_collapse(
421
459
  self,
@@ -423,16 +461,12 @@ class HtmlTreeView(HtmlView):
423
461
  root_path: KeyPath,
424
462
  parent: Any,
425
463
  collapse_level: Optional[int] = 0,
426
- uncollapse: Union[
427
- Set[Union[KeyPath, str]], base.NodeFilter, None
428
- ] = None,
464
+ uncollapse: Union[KeyPathSet, base.NodeFilter] = None,
429
465
  ) -> bool:
430
466
  """Returns whether the object should be collapsed."""
431
467
  if collapse_level is None or root_path.depth < collapse_level:
432
468
  return False
433
- if uncollapse is None:
434
- return True
435
- elif callable(uncollapse):
469
+ if callable(uncollapse):
436
470
  return not uncollapse(root_path, value, parent)
437
471
  else:
438
472
  return root_path not in uncollapse
@@ -468,7 +502,6 @@ class HtmlTreeView(HtmlView):
468
502
  name: Optional[str] = None,
469
503
  parent: Any = None,
470
504
  root_path: Optional[KeyPath] = None,
471
- css_class: Optional[Sequence[str]] = None,
472
505
  title: Union[str, Html, None] = None,
473
506
  enable_summary: Optional[bool] = HtmlView.PresetArgValue(None),
474
507
  enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
@@ -482,7 +515,6 @@ class HtmlTreeView(HtmlView):
482
515
  name: The name of the value.
483
516
  parent: The parent of the value.
484
517
  root_path: The root path of the value.
485
- css_class: The CSS classes to add to the root element
486
518
  title: The title of the summary.
487
519
  enable_summary: Whether to enable the summary. If None, summary will
488
520
  be enabled for complex types or when string exceeds
@@ -542,7 +574,6 @@ class HtmlTreeView(HtmlView):
542
574
  **kwargs,
543
575
  ) if enable_summary_tooltip else None,
544
576
  ],
545
- css_class=css_class,
546
577
  ).add_style(
547
578
  """
548
579
  /* Summary styles. */
@@ -583,7 +614,7 @@ class HtmlTreeView(HtmlView):
583
614
  name: Optional[str] = None,
584
615
  parent: Any,
585
616
  root_path: Optional[KeyPath] = None,
586
- css_class: Optional[Sequence[str]] = None,
617
+ css_class: Union[str, Sequence[str], None] = None,
587
618
  key_color: Optional[str] = None,
588
619
  enable_tooltip: bool = HtmlView.PresetArgValue(True),
589
620
  **kwargs
@@ -595,7 +626,7 @@ class HtmlTreeView(HtmlView):
595
626
  name: The name of the value.
596
627
  parent: The parent value of the key.
597
628
  root_path: The root path of the value.
598
- css_class: The CSS classes to add to the root element.
629
+ css_class: Additional CSS classes to add to the HTML element.
599
630
  key_color: The color of the key.
600
631
  enable_tooltip: Whether to enable the tooltip.
601
632
  **kwargs: Additional keyword arguments passed from `pg.to_html`.
@@ -610,7 +641,11 @@ class HtmlTreeView(HtmlView):
610
641
  [
611
642
  str(key),
612
643
  ],
613
- css_class=['object_key'] + (css_class or []),
644
+ css_class=[
645
+ 'object_key',
646
+ type(key).__name__,
647
+ css_class,
648
+ ],
614
649
  style=dict(
615
650
  color=key_color,
616
651
  )
@@ -634,26 +669,26 @@ class HtmlTreeView(HtmlView):
634
669
  visibility: visible;
635
670
  background-color: darkblue;
636
671
  }
637
- .complex_value .object_key{
672
+ .object_key.str {
638
673
  color: gray;
639
674
  border: 1px solid lightgray;
640
675
  background-color: ButtonFace;
641
676
  border-radius: 0.2em;
642
677
  padding: 0.3em;
643
678
  }
644
- .complex_value.list .object_key{
679
+ .object_key.int::before{
680
+ content: '[';
681
+ }
682
+ .object_key.int::after{
683
+ content: ']';
684
+ }
685
+ .object_key.int{
645
686
  border: 0;
646
687
  color: lightgray;
647
688
  background-color: transparent;
648
689
  border-radius: 0;
649
690
  padding: 0;
650
691
  }
651
- .complex_value.list .object_key::before{
652
- content: '[';
653
- }
654
- .complex_value.list .object_key::after{
655
- content: ']';
656
- }
657
692
  """
658
693
  )
659
694
 
@@ -665,20 +700,17 @@ class HtmlTreeView(HtmlView):
665
700
  name: Optional[str] = None,
666
701
  parent: Any = None,
667
702
  root_path: Optional[KeyPath] = None,
668
- css_class: Optional[Sequence[str]] = None,
669
703
  special_keys: Optional[Sequence[Union[int, str]]] = None,
670
704
  include_keys: Optional[Iterable[Union[int, str]]] = None,
671
705
  exclude_keys: Optional[Iterable[Union[int, str]]] = None,
706
+ collapse_level: Optional[int] = 1,
707
+ uncollapse: Union[KeyPathSet, base.NodeFilter, None] = None,
672
708
  filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
673
709
  highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
674
710
  lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
675
711
  max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
676
712
  enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
677
713
  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
714
  **kwargs
683
715
  ) -> Html:
684
716
  """Renders the main content for the value.
@@ -688,10 +720,13 @@ class HtmlTreeView(HtmlView):
688
720
  name: The name of the value.
689
721
  parent: The parent of the value.
690
722
  root_path: The root path of the value.
691
- css_class: Additional CSS classes for root element.
692
723
  special_keys: The special keys to display (at the immediate child level).
693
724
  include_keys: The keys to include (at the immediate child level).
694
725
  exclude_keys: The keys to exclude (at the immediate child level).
726
+ collapse_level: The level to collapse the tree (relative to this node).
727
+ uncollapse: A key path set (relative to root_path) for the nodes to
728
+ uncollapse. or a function with signature (path, value, parent) -> bool
729
+ to filter nodes to uncollapse.
695
730
  filter: A function with signature (path, value, parent) -> include
696
731
  to determine whether to include a field (at all levels).
697
732
  highlight: A function with signature (path, value, parent) -> bool
@@ -701,8 +736,6 @@ class HtmlTreeView(HtmlView):
701
736
  max_summary_len_for_str: The maximum length of the string to display.
702
737
  enable_summary_tooltip: Whether to enable the summary tooltip.
703
738
  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
739
  **kwargs: Additional keyword arguments passed from `pg.to_html`.
707
740
 
708
741
  Returns:
@@ -715,25 +748,24 @@ class HtmlTreeView(HtmlView):
715
748
  else:
716
749
  return self.simple_value(
717
750
  value, name=name, parent=parent, root_path=root_path,
718
- css_class=css_class, max_summary_len_for_str=max_summary_len_for_str
751
+ max_summary_len_for_str=max_summary_len_for_str
719
752
  )
720
753
  return self.complex_value(
721
754
  items,
722
755
  name=name,
723
756
  parent=value,
724
757
  root_path=root_path or KeyPath(),
725
- css_class=css_class,
726
758
  special_keys=special_keys,
727
759
  include_keys=include_keys,
728
760
  exclude_keys=exclude_keys,
761
+ collapse_level=collapse_level,
762
+ uncollapse=uncollapse,
729
763
  filter=filter,
730
764
  highlight=highlight,
731
765
  lowlight=lowlight,
732
766
  max_summary_len_for_str=max_summary_len_for_str,
733
767
  enable_summary_tooltip=enable_summary_tooltip,
734
768
  enable_key_tooltip=enable_key_tooltip,
735
- collapse_level=collapse_level,
736
- uncollapse=uncollapse,
737
769
  **kwargs,
738
770
  )
739
771
 
@@ -744,7 +776,7 @@ class HtmlTreeView(HtmlView):
744
776
  name: Optional[str] = None,
745
777
  parent: Any = None,
746
778
  root_path: Optional[KeyPath] = None,
747
- css_class: Optional[Sequence[str]] = None,
779
+ css_class: Union[str, Sequence[str], None] = None,
748
780
  max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
749
781
  ) -> Html:
750
782
  """Renders a simple value.
@@ -754,7 +786,7 @@ class HtmlTreeView(HtmlView):
754
786
  name: The name of the value.
755
787
  parent: The parent of the value.
756
788
  root_path: The root path of the value.
757
- css_class: Additional CSS classes for root span.
789
+ css_class: Additional CSS classes to add to the HTML element.
758
790
  max_summary_len_for_str: The maximum length of the string to display.
759
791
 
760
792
  Returns:
@@ -778,9 +810,11 @@ class HtmlTreeView(HtmlView):
778
810
  [
779
811
  Html.escape(value_repr),
780
812
  ],
781
- css_class=['simple_value', self.css_class_name(value)] + (
782
- css_class or []
783
- ),
813
+ css_class=[
814
+ 'simple_value',
815
+ self.css_class_name(value),
816
+ css_class,
817
+ ],
784
818
  ).add_style(
785
819
  """
786
820
  /* Simple value styles. */
@@ -805,36 +839,46 @@ class HtmlTreeView(HtmlView):
805
839
  self,
806
840
  kv: Dict[Union[int, str], Any],
807
841
  *,
842
+ parent: Any,
843
+ root_path: KeyPath,
808
844
  name: Optional[str] = None,
809
- parent: Any = None,
810
- root_path: Optional[KeyPath] = None,
811
- css_class: Optional[Sequence[str]] = None,
845
+ css_class: Union[str, Sequence[str], None] = None,
846
+ render_key_fn: Optional[Callable[..., Html]] = None,
847
+ render_value_fn: Optional[Callable[..., Html]] = None,
812
848
  special_keys: Optional[Sequence[Union[int, str]]] = None,
813
849
  include_keys: Optional[Iterable[Union[int, str]]] = None,
814
850
  exclude_keys: Optional[Iterable[Union[int, str]]] = None,
851
+ collapse_level: Optional[int] = 1,
852
+ uncollapse: Union[KeyPathSet, base.NodeFilter, None] = None,
815
853
  filter: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None), # pylint: disable=redefined-builtin
816
854
  highlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
817
855
  lowlight: Optional[base.NodeFilter] = HtmlView.PresetArgValue(None),
818
856
  max_summary_len_for_str: int = HtmlView.PresetArgValue(40),
819
857
  enable_summary_tooltip: bool = HtmlView.PresetArgValue(True),
820
858
  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
859
  **kwargs,
826
860
  ) -> Html:
827
861
  """Renders a list of key-value pairs.
828
862
 
829
863
  Args:
830
864
  kv: The key-value pairs to render.
831
- name: The name of the value.
832
865
  parent: The parent value of the key-value pairs.
833
866
  root_path: The root path of the value.
834
- css_class: Additional CSS classes for root div.
867
+ name: The name of the value.
868
+ css_class: Additional CSS classes to add to the HTML element.
869
+ render_key_fn: A function to render the key. The function has the
870
+ same signature as `HtmlTreeView.object_key`.
871
+ If None, `HtmlTreeView.object_key` will be used to render the key.
872
+ render_value_fn: A function to render the value. The function has the
873
+ same signature as `HtmlTreeView.render`.
874
+ If None, `HtmlTreeView.render` will be used to render child value.
835
875
  special_keys: The special keys to display (at the immediate child level).
836
876
  include_keys: The keys to include (at the immediate child level).
837
877
  exclude_keys: The keys to exclude (at the immediate child level).
878
+ collapse_level: The level to collapse the tree (relative to this node).
879
+ uncollapse: A key path set (relative to root_path) for the nodes to
880
+ uncollapse. or a function with signature (path, value, parent) -> bool
881
+ to filter nodes to uncollapse.
838
882
  filter: A function with signature (path, value, parent) -> include
839
883
  to determine whether to include.
840
884
  highlight: A function with signature (path, value, parent) -> bool
@@ -844,18 +888,26 @@ class HtmlTreeView(HtmlView):
844
888
  max_summary_len_for_str: The maximum length of the string to display.
845
889
  enable_summary_tooltip: Whether to enable the summary tooltip.
846
890
  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
891
  **kwargs: Additional keyword arguments passed from `pg.to_html`.
850
892
 
851
893
  Returns:
852
894
  The rendered HTML as the key-value pairs.
853
895
  """
854
896
  del name
897
+ root_path = root_path or KeyPath()
898
+ uncollapse = self.init_uncollapse(uncollapse)
899
+
900
+ if isinstance(parent, HtmlTreeView.Extension):
901
+ special_keys = special_keys or parent._html_tree_view_special_keys() # pylint: disable=protected-access
902
+ include_keys = include_keys or parent._html_tree_view_include_keys() # pylint: disable=protected-access
903
+ exclude_keys = exclude_keys or parent._html_tree_view_exclude_keys() # pylint: disable=protected-access
904
+
855
905
  special_keys = special_keys or []
856
906
  include_keys = set(include_keys or [])
857
907
  exclude_keys = set(exclude_keys or [])
858
- uncollapse = self.normalize_uncollapse(uncollapse)
908
+
909
+ render_key_fn = render_key_fn or self.object_key
910
+ render_value_fn = render_value_fn or self.render
859
911
 
860
912
  s = Html()
861
913
  if kv:
@@ -873,37 +925,40 @@ class HtmlTreeView(HtmlView):
873
925
  if k in include_keys and k in kv:
874
926
  child_path = root_path + k
875
927
  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
928
  s.write(
889
- self.render(
890
- value=v,
891
- name=k,
892
- parent=v,
893
- root_path=child_path,
894
- css_class=child_css_class,
895
- filter=filter,
896
- special_keys=None,
897
- include_keys=None,
898
- exclude_keys=None,
899
- highlight=highlight,
900
- lowlight=lowlight,
901
- max_summary_len_for_str=max_summary_len_for_str,
902
- enable_summary_tooltip=enable_summary_tooltip,
903
- enable_key_tooltip=enable_key_tooltip,
904
- collapse_level=collapse_level,
905
- uncollapse=uncollapse,
906
- **kwargs
929
+ Html.element(
930
+ 'div',
931
+ [
932
+ render_value_fn(
933
+ value=v,
934
+ name=k,
935
+ parent=parent,
936
+ root_path=child_path,
937
+ filter=filter,
938
+ special_keys=None,
939
+ include_keys=None,
940
+ exclude_keys=None,
941
+ collapse_level=collapse_level,
942
+ uncollapse=uncollapse,
943
+ highlight=highlight,
944
+ lowlight=lowlight,
945
+ max_summary_len_for_str=max_summary_len_for_str,
946
+ enable_summary_tooltip=enable_summary_tooltip,
947
+ enable_key_tooltip=enable_key_tooltip,
948
+ **kwargs
949
+ )
950
+ ],
951
+ css_class=[
952
+ 'special_value',
953
+ (
954
+ 'highlight' if highlight
955
+ and highlight(child_path, v, parent) else None
956
+ ),
957
+ (
958
+ 'lowlight' if lowlight
959
+ and lowlight(child_path, v, parent) else None
960
+ )
961
+ ],
907
962
  )
908
963
  )
909
964
  include_keys.remove(k)
@@ -914,45 +969,51 @@ class HtmlTreeView(HtmlView):
914
969
  if k not in include_keys:
915
970
  continue
916
971
  child_path = root_path + k
917
- key = self.object_key(
918
- key=k, parent=v, root_path=child_path,
972
+ key_cell = render_key_fn(
973
+ key=k,
974
+ parent=parent,
975
+ root_path=child_path,
919
976
  enable_tooltip=enable_key_tooltip,
920
977
  )
921
- child_css_class = [
922
- (
923
- 'highlight' if highlight and highlight(child_path, v, parent)
924
- else None
925
- ),
926
- (
927
- 'lowlight' if lowlight and lowlight(child_path, v, parent)
928
- else None
929
- )
930
- ]
931
- value = self.render(
932
- value=v,
933
- name=None,
934
- parent=v,
935
- root_path=child_path,
936
- css_class=child_css_class,
937
- special_keys=None,
938
- include_keys=None,
939
- exclude_keys=None,
940
- filter=filter,
941
- highlight=highlight,
942
- lowlight=lowlight,
943
- max_summary_len_for_str=max_summary_len_for_str,
944
- enable_summary_tooltip=enable_summary_tooltip,
945
- enable_key_tooltip=enable_key_tooltip,
946
- collapse_level=collapse_level,
947
- uncollapse=uncollapse,
948
- **kwargs,
978
+ value_cell = Html.element(
979
+ 'div',
980
+ [
981
+ render_value_fn(
982
+ value=v,
983
+ name=None,
984
+ parent=parent,
985
+ root_path=child_path,
986
+ special_keys=None,
987
+ include_keys=None,
988
+ exclude_keys=None,
989
+ collapse_level=collapse_level,
990
+ uncollapse=uncollapse,
991
+ filter=filter,
992
+ highlight=highlight,
993
+ lowlight=lowlight,
994
+ max_summary_len_for_str=max_summary_len_for_str,
995
+ enable_summary_tooltip=enable_summary_tooltip,
996
+ enable_key_tooltip=enable_key_tooltip,
997
+ **kwargs,
998
+ )
999
+ ],
1000
+ css_class=[
1001
+ (
1002
+ 'highlight' if highlight
1003
+ and highlight(child_path, v, parent) else None
1004
+ ),
1005
+ (
1006
+ 'lowlight' if lowlight
1007
+ and lowlight(child_path, v, parent) else None
1008
+ )
1009
+ ],
949
1010
  )
950
1011
  s.write(
951
1012
  Html.element(
952
1013
  'tr',
953
1014
  [
954
- '<td>', key, '</td>',
955
- '<td>', value, '</td>',
1015
+ '<td>', key_cell, '</td>',
1016
+ '<td>', value_cell, '</td>',
956
1017
  ],
957
1018
  )
958
1019
  )
@@ -962,9 +1023,11 @@ class HtmlTreeView(HtmlView):
962
1023
  return Html.element(
963
1024
  'div',
964
1025
  [s],
965
- css_class=['complex_value', self.css_class_name(parent)] + (
966
- css_class or []
967
- ),
1026
+ css_class=[
1027
+ 'complex_value',
1028
+ self.css_class_name(parent),
1029
+ css_class,
1030
+ ]
968
1031
  ).add_style(
969
1032
  """
970
1033
  /* Complex value styles. */
@@ -985,7 +1048,6 @@ class HtmlTreeView(HtmlView):
985
1048
  name: Optional[str] = None,
986
1049
  parent: Any = None,
987
1050
  root_path: Optional[KeyPath] = None,
988
- css_class: Optional[Sequence[str]] = None,
989
1051
  content: Union[str, Html, None] = HtmlView.PresetArgValue(None),
990
1052
  **kwargs
991
1053
  ) -> Html:
@@ -996,7 +1058,6 @@ class HtmlTreeView(HtmlView):
996
1058
  name: The name of the value.
997
1059
  parent: The parent value of the key-value pairs.
998
1060
  root_path: The root path of the value.
999
- css_class: Additional CSS classes for the tooltip span.
1000
1061
  content: The content of the tooltip. If None, the formatted value will be
1001
1062
  used as the content.
1002
1063
  **kwargs: Additional keyword arguments passed from `pg.to_html`.
@@ -1021,7 +1082,7 @@ class HtmlTreeView(HtmlView):
1021
1082
  return Html.element(
1022
1083
  'span',
1023
1084
  [content],
1024
- css_class=['tooltip'] + (css_class or []),
1085
+ css_class=['tooltip', self.css_class_name(value)],
1025
1086
  ).add_style(
1026
1087
  """
1027
1088
  /* Tooltip styles. */
@@ -1040,11 +1101,12 @@ class HtmlTreeView(HtmlView):
1040
1101
  )
1041
1102
 
1042
1103
  @staticmethod
1043
- def css_class_name(value: Any) -> str:
1104
+ def css_class_name(value: Any) -> Optional[str]:
1044
1105
  """Returns the CSS class name for the value."""
1106
+ if isinstance(value, HtmlTreeView.Extension):
1107
+ return Html.concate(value._html_element_class()) # pylint: disable=protected-access
1045
1108
  value = value if inspect.isclass(value) else type(value)
1046
- class_name = value.__name__
1047
- return _REGEX_CAMEL_TO_SNAKE.sub('-', class_name).lower()
1109
+ return object_utils.camel_to_snake(value.__name__, '-')
1048
1110
 
1049
1111
 
1050
1112
  _REGEX_CAMEL_TO_SNAKE = re.compile(r'(?<!^)(?=[A-Z])')