pyglove 0.4.5.dev20240319__py3-none-any.whl → 0.4.5.dev202501132210__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 +54 -20
- pyglove/core/coding/__init__.py +42 -0
- pyglove/core/coding/errors.py +111 -0
- pyglove/core/coding/errors_test.py +98 -0
- pyglove/core/coding/execution.py +309 -0
- pyglove/core/coding/execution_test.py +333 -0
- pyglove/core/{object_utils/codegen.py → coding/function_generation.py} +10 -4
- pyglove/core/{object_utils/codegen_test.py → coding/function_generation_test.py} +5 -7
- pyglove/core/coding/parsing.py +153 -0
- pyglove/core/coding/parsing_test.py +150 -0
- pyglove/core/coding/permissions.py +100 -0
- pyglove/core/coding/permissions_test.py +93 -0
- pyglove/core/geno/base.py +54 -41
- pyglove/core/geno/base_test.py +2 -4
- pyglove/core/geno/categorical.py +37 -28
- pyglove/core/geno/custom.py +19 -16
- pyglove/core/geno/numerical.py +20 -17
- pyglove/core/geno/space.py +4 -5
- pyglove/core/hyper/base.py +6 -6
- pyglove/core/hyper/categorical.py +94 -55
- pyglove/core/hyper/custom.py +7 -7
- pyglove/core/hyper/custom_test.py +9 -10
- pyglove/core/hyper/derived.py +30 -22
- pyglove/core/hyper/derived_test.py +2 -4
- pyglove/core/hyper/dynamic_evaluation.py +5 -6
- pyglove/core/hyper/evolvable.py +57 -46
- pyglove/core/hyper/numerical.py +48 -24
- pyglove/core/hyper/numerical_test.py +9 -9
- pyglove/core/hyper/object_template.py +58 -46
- pyglove/core/io/__init__.py +1 -0
- pyglove/core/io/file_system.py +17 -7
- pyglove/core/io/file_system_test.py +2 -0
- pyglove/core/io/sequence.py +299 -0
- pyglove/core/io/sequence_test.py +124 -0
- pyglove/core/logging_test.py +0 -2
- pyglove/core/patching/object_factory.py +4 -4
- pyglove/core/patching/pattern_based.py +4 -4
- pyglove/core/patching/rule_based.py +17 -5
- pyglove/core/patching/rule_based_test.py +27 -4
- pyglove/core/symbolic/__init__.py +2 -7
- pyglove/core/symbolic/base.py +320 -183
- pyglove/core/symbolic/base_test.py +123 -19
- pyglove/core/symbolic/boilerplate.py +7 -13
- pyglove/core/symbolic/boilerplate_test.py +25 -23
- pyglove/core/symbolic/class_wrapper.py +48 -45
- pyglove/core/symbolic/class_wrapper_test.py +2 -2
- pyglove/core/symbolic/compounding.py +9 -15
- pyglove/core/symbolic/compounding_test.py +2 -4
- pyglove/core/symbolic/dict.py +154 -110
- pyglove/core/symbolic/dict_test.py +238 -130
- pyglove/core/symbolic/diff.py +199 -10
- pyglove/core/symbolic/diff_test.py +226 -0
- pyglove/core/symbolic/flags.py +1 -1
- pyglove/core/symbolic/functor.py +29 -26
- pyglove/core/symbolic/functor_test.py +102 -50
- pyglove/core/symbolic/inferred.py +2 -2
- pyglove/core/symbolic/list.py +81 -50
- pyglove/core/symbolic/list_test.py +119 -97
- pyglove/core/symbolic/object.py +225 -113
- pyglove/core/symbolic/object_test.py +320 -108
- pyglove/core/symbolic/origin.py +17 -14
- pyglove/core/symbolic/origin_test.py +4 -2
- pyglove/core/symbolic/pure_symbolic.py +4 -3
- pyglove/core/symbolic/ref.py +108 -21
- pyglove/core/symbolic/ref_test.py +93 -0
- pyglove/core/symbolic/symbolize_test.py +10 -2
- pyglove/core/tuning/local_backend.py +2 -2
- pyglove/core/tuning/protocols.py +3 -3
- pyglove/core/tuning/sample_test.py +3 -3
- pyglove/core/typing/__init__.py +14 -5
- pyglove/core/typing/annotation_conversion.py +43 -27
- pyglove/core/typing/annotation_conversion_test.py +23 -0
- pyglove/core/typing/callable_ext.py +241 -3
- pyglove/core/typing/callable_ext_test.py +255 -0
- pyglove/core/typing/callable_signature.py +510 -66
- pyglove/core/typing/callable_signature_test.py +619 -99
- pyglove/core/typing/class_schema.py +229 -154
- pyglove/core/typing/class_schema_test.py +149 -95
- pyglove/core/typing/custom_typing.py +5 -4
- pyglove/core/typing/inspect.py +63 -0
- pyglove/core/typing/inspect_test.py +39 -0
- pyglove/core/typing/key_specs.py +10 -11
- pyglove/core/typing/key_specs_test.py +7 -4
- pyglove/core/typing/type_conversion.py +4 -5
- pyglove/core/typing/type_conversion_test.py +12 -12
- pyglove/core/typing/typed_missing.py +6 -7
- pyglove/core/typing/typed_missing_test.py +7 -8
- pyglove/core/typing/value_specs.py +604 -362
- pyglove/core/typing/value_specs_test.py +328 -90
- pyglove/core/utils/__init__.py +164 -0
- pyglove/core/{object_utils → utils}/common_traits.py +3 -67
- pyglove/core/utils/common_traits_test.py +36 -0
- pyglove/core/{object_utils → utils}/docstr_utils.py +23 -0
- pyglove/core/{object_utils → utils}/docstr_utils_test.py +36 -4
- pyglove/core/{object_utils → utils}/error_utils.py +78 -9
- pyglove/core/{object_utils → utils}/error_utils_test.py +61 -5
- pyglove/core/utils/formatting.py +464 -0
- pyglove/core/utils/formatting_test.py +453 -0
- pyglove/core/{object_utils → utils}/hierarchical.py +23 -25
- pyglove/core/{object_utils → utils}/hierarchical_test.py +3 -5
- pyglove/core/{object_utils → utils}/json_conversion.py +177 -52
- pyglove/core/{object_utils → utils}/json_conversion_test.py +97 -16
- pyglove/core/{object_utils → utils}/missing.py +3 -3
- pyglove/core/{object_utils → utils}/missing_test.py +2 -4
- pyglove/core/utils/text_color.py +128 -0
- pyglove/core/utils/text_color_test.py +94 -0
- pyglove/core/{object_utils → utils}/thread_local_test.py +1 -3
- pyglove/core/utils/timing.py +236 -0
- pyglove/core/utils/timing_test.py +154 -0
- pyglove/core/{object_utils → utils}/value_location.py +275 -6
- pyglove/core/utils/value_location_test.py +707 -0
- pyglove/core/views/__init__.py +32 -0
- pyglove/core/views/base.py +804 -0
- pyglove/core/views/base_test.py +580 -0
- pyglove/core/views/html/__init__.py +27 -0
- pyglove/core/views/html/base.py +547 -0
- pyglove/core/views/html/base_test.py +830 -0
- pyglove/core/views/html/controls/__init__.py +35 -0
- pyglove/core/views/html/controls/base.py +275 -0
- pyglove/core/views/html/controls/label.py +207 -0
- pyglove/core/views/html/controls/label_test.py +157 -0
- pyglove/core/views/html/controls/progress_bar.py +183 -0
- pyglove/core/views/html/controls/progress_bar_test.py +97 -0
- pyglove/core/views/html/controls/tab.py +320 -0
- pyglove/core/views/html/controls/tab_test.py +87 -0
- pyglove/core/views/html/controls/tooltip.py +99 -0
- pyglove/core/views/html/controls/tooltip_test.py +99 -0
- pyglove/core/views/html/tree_view.py +1517 -0
- pyglove/core/views/html/tree_view_test.py +1461 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/METADATA +18 -4
- pyglove-0.4.5.dev202501132210.dist-info/RECORD +214 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/WHEEL +1 -1
- pyglove/core/object_utils/__init__.py +0 -154
- pyglove/core/object_utils/common_traits_test.py +0 -82
- pyglove/core/object_utils/formatting.py +0 -234
- pyglove/core/object_utils/formatting_test.py +0 -223
- pyglove/core/object_utils/value_location_test.py +0 -385
- pyglove/core/symbolic/schema_utils.py +0 -327
- pyglove/core/symbolic/schema_utils_test.py +0 -57
- pyglove/core/typing/class_schema_utils.py +0 -202
- pyglove/core/typing/class_schema_utils_test.py +0 -194
- pyglove-0.4.5.dev20240319.dist-info/RECORD +0 -185
- /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,1461 @@
|
|
1
|
+
# Copyright 2024 The PyGlove Authors
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
import inspect
|
15
|
+
from typing import Any
|
16
|
+
import unittest
|
17
|
+
|
18
|
+
from pyglove.core.views.html import base
|
19
|
+
from pyglove.core.views.html import tree_view
|
20
|
+
|
21
|
+
Html = base.Html
|
22
|
+
KeyPath = tree_view.KeyPath
|
23
|
+
KeyPathSet = tree_view.KeyPathSet
|
24
|
+
|
25
|
+
|
26
|
+
class TestCase(unittest.TestCase):
|
27
|
+
|
28
|
+
def setUp(self):
|
29
|
+
super().setUp()
|
30
|
+
self._view = tree_view.HtmlTreeView()
|
31
|
+
|
32
|
+
def assert_style(self, html, expected):
|
33
|
+
expected = inspect.cleandoc(expected).strip()
|
34
|
+
actual = html.style_section.strip()
|
35
|
+
if actual != expected:
|
36
|
+
print(actual)
|
37
|
+
self.assertEqual(actual.strip(), expected)
|
38
|
+
|
39
|
+
def assert_content(self, html, expected):
|
40
|
+
expected = inspect.cleandoc(expected).strip()
|
41
|
+
actual = html.content.strip()
|
42
|
+
if actual != expected:
|
43
|
+
print(actual)
|
44
|
+
self.assertEqual(actual.strip(), expected)
|
45
|
+
|
46
|
+
def assert_count(self, html, part, expected):
|
47
|
+
content = html.content.strip()
|
48
|
+
actual = content.count(part)
|
49
|
+
if actual != expected:
|
50
|
+
print(content)
|
51
|
+
self.assertEqual(actual, expected)
|
52
|
+
|
53
|
+
|
54
|
+
class TooltipTest(TestCase):
|
55
|
+
|
56
|
+
def test_style(self):
|
57
|
+
self.assert_style(
|
58
|
+
self._view.tooltip(
|
59
|
+
'This <hello><world></world></hello>.',
|
60
|
+
name='name',
|
61
|
+
),
|
62
|
+
"""
|
63
|
+
<style>
|
64
|
+
/* Tooltip styles. */
|
65
|
+
span.tooltip {
|
66
|
+
visibility: hidden;
|
67
|
+
white-space: pre-wrap;
|
68
|
+
font-weight: normal;
|
69
|
+
background-color: #484848;
|
70
|
+
color: #fff;
|
71
|
+
padding: 10px;
|
72
|
+
border-radius: 6px;
|
73
|
+
position: absolute;
|
74
|
+
z-index: 1;
|
75
|
+
}
|
76
|
+
span.tooltip:hover {
|
77
|
+
visibility: visible;
|
78
|
+
}
|
79
|
+
</style>
|
80
|
+
"""
|
81
|
+
)
|
82
|
+
|
83
|
+
def test_render(self):
|
84
|
+
self.assert_content(
|
85
|
+
self._view.tooltip(
|
86
|
+
'This <hello><world></world></hello>.',
|
87
|
+
name='name',
|
88
|
+
),
|
89
|
+
"""
|
90
|
+
<span class="tooltip">'This <hello><world></world></hello>.'</span>
|
91
|
+
"""
|
92
|
+
)
|
93
|
+
self.assert_content(
|
94
|
+
self._view.tooltip(
|
95
|
+
1,
|
96
|
+
content=Html.element('div', ['hello']),
|
97
|
+
css_classes=['int'],
|
98
|
+
name='name',
|
99
|
+
),
|
100
|
+
"""
|
101
|
+
<span class="tooltip int"><div>hello</div></span>
|
102
|
+
"""
|
103
|
+
)
|
104
|
+
|
105
|
+
|
106
|
+
class SummaryTest(TestCase):
|
107
|
+
|
108
|
+
def test_style(self):
|
109
|
+
self.assert_style(
|
110
|
+
self._view.summary(
|
111
|
+
1, enable_summary=True,
|
112
|
+
),
|
113
|
+
"""
|
114
|
+
<style>
|
115
|
+
/* Tooltip styles. */
|
116
|
+
span.tooltip {
|
117
|
+
visibility: hidden;
|
118
|
+
white-space: pre-wrap;
|
119
|
+
font-weight: normal;
|
120
|
+
background-color: #484848;
|
121
|
+
color: #fff;
|
122
|
+
padding: 10px;
|
123
|
+
border-radius: 6px;
|
124
|
+
position: absolute;
|
125
|
+
z-index: 1;
|
126
|
+
}
|
127
|
+
span.tooltip:hover {
|
128
|
+
visibility: visible;
|
129
|
+
}
|
130
|
+
/* Summary styles. */
|
131
|
+
details.pyglove summary {
|
132
|
+
font-weight: bold;
|
133
|
+
margin: -0.5em -0.5em 0;
|
134
|
+
padding: 0.5em;
|
135
|
+
}
|
136
|
+
.summary-name {
|
137
|
+
display: inline;
|
138
|
+
padding: 3px 5px 3px 5px;
|
139
|
+
margin: 0 5px;
|
140
|
+
border-radius: 3px;
|
141
|
+
}
|
142
|
+
.summary-title {
|
143
|
+
display: inline;
|
144
|
+
}
|
145
|
+
.summary-name + div.summary-title {
|
146
|
+
display: inline;
|
147
|
+
color: #aaa;
|
148
|
+
}
|
149
|
+
.summary-title:hover + span.tooltip {
|
150
|
+
visibility: visible;
|
151
|
+
}
|
152
|
+
.summary-name:hover > span.tooltip {
|
153
|
+
visibility: visible;
|
154
|
+
background-color: darkblue;
|
155
|
+
}
|
156
|
+
</style>
|
157
|
+
"""
|
158
|
+
)
|
159
|
+
|
160
|
+
def test_summary_title(self):
|
161
|
+
self.assert_content(
|
162
|
+
self._view.summary(
|
163
|
+
1, enable_summary=True, enable_summary_tooltip=False
|
164
|
+
),
|
165
|
+
"""
|
166
|
+
<summary><div class="summary-title">int</div></summary>
|
167
|
+
"""
|
168
|
+
)
|
169
|
+
self.assert_content(
|
170
|
+
self._view.summary(
|
171
|
+
int, enable_summary=True, enable_summary_tooltip=False
|
172
|
+
),
|
173
|
+
"""
|
174
|
+
<summary><div class="summary-title">type</div></summary>
|
175
|
+
"""
|
176
|
+
)
|
177
|
+
self.assert_content(
|
178
|
+
self._view.summary(
|
179
|
+
[0, 1], enable_summary=True, enable_summary_tooltip=False
|
180
|
+
),
|
181
|
+
"""
|
182
|
+
<summary><div class="summary-title">list(...)</div></summary>
|
183
|
+
"""
|
184
|
+
)
|
185
|
+
|
186
|
+
def test_enable_summary(self):
|
187
|
+
self.assertIsNone(
|
188
|
+
self._view.summary(1, enable_summary=None),
|
189
|
+
)
|
190
|
+
self.assertIsNone(
|
191
|
+
self._view.summary('foo', enable_summary=False),
|
192
|
+
)
|
193
|
+
self.assertIsNone(
|
194
|
+
self._view.summary('foo', enable_summary=None),
|
195
|
+
)
|
196
|
+
self.assert_content(
|
197
|
+
self._view.summary('foo', enable_summary=True),
|
198
|
+
"""
|
199
|
+
<summary><div class="summary-title">str</div><span class="tooltip">'foo'</span></summary>
|
200
|
+
"""
|
201
|
+
)
|
202
|
+
self.assert_content(
|
203
|
+
self._view.summary(
|
204
|
+
'foo', enable_summary=None, max_summary_len_for_str=1
|
205
|
+
),
|
206
|
+
"""
|
207
|
+
<summary><div class="summary-title">str</div><span class="tooltip">'foo'</span></summary>
|
208
|
+
"""
|
209
|
+
)
|
210
|
+
self.assertIsNone(
|
211
|
+
self._view.summary(
|
212
|
+
'foo', enable_summary=None, enable_summary_for_str=False
|
213
|
+
),
|
214
|
+
)
|
215
|
+
|
216
|
+
def test_css_styles(self):
|
217
|
+
self.assert_content(
|
218
|
+
self._view.summary(
|
219
|
+
'foo', name='x', css_classes=['bar'], enable_summary=True
|
220
|
+
),
|
221
|
+
"""
|
222
|
+
<summary><div class="summary-name bar">x<span class="tooltip bar"></span></div><div class="summary-title bar">str</div><span class="tooltip bar">'foo'</span></summary>
|
223
|
+
"""
|
224
|
+
)
|
225
|
+
|
226
|
+
def test_max_summary_len_for_str(self):
|
227
|
+
self.assert_content(
|
228
|
+
self._view.summary(
|
229
|
+
'abcdefg',
|
230
|
+
max_summary_len_for_str=5
|
231
|
+
),
|
232
|
+
"""
|
233
|
+
<summary><div class="summary-title">str</div><span class="tooltip">'abcdefg'</span></summary>
|
234
|
+
"""
|
235
|
+
)
|
236
|
+
|
237
|
+
def test_name(self):
|
238
|
+
self.assert_content(
|
239
|
+
self._view.summary('foo', name='x'),
|
240
|
+
"""
|
241
|
+
<summary><div class="summary-name">x<span class="tooltip"></span></div><div class="summary-title">str</div><span class="tooltip">'foo'</span></summary>
|
242
|
+
"""
|
243
|
+
)
|
244
|
+
|
245
|
+
def test_enable_key_tooltip(self):
|
246
|
+
self.assert_content(
|
247
|
+
self._view.summary(
|
248
|
+
'foo',
|
249
|
+
name='x',
|
250
|
+
root_path=KeyPath.parse('y.a.x'),
|
251
|
+
enable_summary_tooltip=False,
|
252
|
+
enable_key_tooltip=True
|
253
|
+
),
|
254
|
+
"""
|
255
|
+
<summary><div class="summary-name">x<span class="tooltip">y.a.x</span></div><div class="summary-title">str</div></summary>
|
256
|
+
"""
|
257
|
+
)
|
258
|
+
self.assert_content(
|
259
|
+
self._view.summary(
|
260
|
+
'foo',
|
261
|
+
name='x',
|
262
|
+
root_path=KeyPath.parse('y.a.x'),
|
263
|
+
enable_summary_tooltip=False,
|
264
|
+
enable_key_tooltip=False
|
265
|
+
),
|
266
|
+
"""
|
267
|
+
<summary><div class="summary-name">x</div><div class="summary-title">str</div></summary>
|
268
|
+
"""
|
269
|
+
)
|
270
|
+
|
271
|
+
def test_summary_color(self):
|
272
|
+
self.assert_content(
|
273
|
+
self._view.summary(
|
274
|
+
'foo',
|
275
|
+
name='x',
|
276
|
+
summary_color=('white', 'red'),
|
277
|
+
enable_summary_tooltip=False
|
278
|
+
),
|
279
|
+
"""
|
280
|
+
<summary><div class="summary-name" style="color:white;background-color:red;">x<span class="tooltip"></span></div><div class="summary-title">str</div></summary>
|
281
|
+
"""
|
282
|
+
)
|
283
|
+
|
284
|
+
def test_enable_summary_tooltip(self):
|
285
|
+
self.assert_content(
|
286
|
+
self._view.summary(
|
287
|
+
'foo', enable_summary=True, enable_summary_tooltip=True
|
288
|
+
),
|
289
|
+
"""
|
290
|
+
<summary><div class="summary-title">str</div><span class="tooltip">'foo'</span></summary>
|
291
|
+
"""
|
292
|
+
)
|
293
|
+
self.assert_content(
|
294
|
+
self._view.summary(
|
295
|
+
'foo', enable_summary=True, enable_summary_tooltip=False
|
296
|
+
),
|
297
|
+
"""
|
298
|
+
<summary><div class="summary-title">str</div></summary>
|
299
|
+
"""
|
300
|
+
)
|
301
|
+
|
302
|
+
|
303
|
+
class ContentTest(TestCase):
|
304
|
+
|
305
|
+
def test_style(self):
|
306
|
+
self.assert_style(
|
307
|
+
self._view.content(dict(x=1)),
|
308
|
+
"""
|
309
|
+
<style>
|
310
|
+
/* Tooltip styles. */
|
311
|
+
span.tooltip {
|
312
|
+
visibility: hidden;
|
313
|
+
white-space: pre-wrap;
|
314
|
+
font-weight: normal;
|
315
|
+
background-color: #484848;
|
316
|
+
color: #fff;
|
317
|
+
padding: 10px;
|
318
|
+
border-radius: 6px;
|
319
|
+
position: absolute;
|
320
|
+
z-index: 1;
|
321
|
+
}
|
322
|
+
span.tooltip:hover {
|
323
|
+
visibility: visible;
|
324
|
+
}
|
325
|
+
/* Summary styles. */
|
326
|
+
details.pyglove summary {
|
327
|
+
font-weight: bold;
|
328
|
+
margin: -0.5em -0.5em 0;
|
329
|
+
padding: 0.5em;
|
330
|
+
}
|
331
|
+
.summary-name {
|
332
|
+
display: inline;
|
333
|
+
padding: 3px 5px 3px 5px;
|
334
|
+
margin: 0 5px;
|
335
|
+
border-radius: 3px;
|
336
|
+
}
|
337
|
+
.summary-title {
|
338
|
+
display: inline;
|
339
|
+
}
|
340
|
+
.summary-name + div.summary-title {
|
341
|
+
display: inline;
|
342
|
+
color: #aaa;
|
343
|
+
}
|
344
|
+
.summary-title:hover + span.tooltip {
|
345
|
+
visibility: visible;
|
346
|
+
}
|
347
|
+
.summary-name:hover > span.tooltip {
|
348
|
+
visibility: visible;
|
349
|
+
background-color: darkblue;
|
350
|
+
}
|
351
|
+
/* Simple value styles. */
|
352
|
+
.simple-value {
|
353
|
+
color: blue;
|
354
|
+
display: inline-block;
|
355
|
+
white-space: pre-wrap;
|
356
|
+
padding: 0.2em;
|
357
|
+
margin-top: 0.15em;
|
358
|
+
}
|
359
|
+
.simple-value.str {
|
360
|
+
color: darkred;
|
361
|
+
font-style: italic;
|
362
|
+
}
|
363
|
+
.simple-value.int, .simple-value.float {
|
364
|
+
color: darkblue;
|
365
|
+
}
|
366
|
+
/* Value details styles. */
|
367
|
+
details.pyglove {
|
368
|
+
border: 1px solid #aaa;
|
369
|
+
border-radius: 4px;
|
370
|
+
padding: 0.5em 0.5em 0;
|
371
|
+
margin: 0.25em 0;
|
372
|
+
}
|
373
|
+
details.pyglove[open] {
|
374
|
+
padding: 0.5em 0.5em 0.5em;
|
375
|
+
}
|
376
|
+
.highlight {
|
377
|
+
background-color: Mark;
|
378
|
+
}
|
379
|
+
.lowlight {
|
380
|
+
opacity: 0.2;
|
381
|
+
}
|
382
|
+
/* Complex value styles. */
|
383
|
+
span.empty-container::before {
|
384
|
+
content: '(empty)';
|
385
|
+
font-style: italic;
|
386
|
+
margin-left: 0.5em;
|
387
|
+
color: #aaa;
|
388
|
+
}
|
389
|
+
</style>
|
390
|
+
"""
|
391
|
+
)
|
392
|
+
|
393
|
+
def test_simple_types(self):
|
394
|
+
self.assert_content(
|
395
|
+
self._view.content(1),
|
396
|
+
"""
|
397
|
+
<span class="simple-value int">1</span>
|
398
|
+
"""
|
399
|
+
)
|
400
|
+
self.assert_content(
|
401
|
+
self._view.content(1.5),
|
402
|
+
"""
|
403
|
+
<span class="simple-value float">1.5</span>
|
404
|
+
"""
|
405
|
+
)
|
406
|
+
self.assert_content(
|
407
|
+
self._view.content(True),
|
408
|
+
"""
|
409
|
+
<span class="simple-value bool">True</span>
|
410
|
+
"""
|
411
|
+
)
|
412
|
+
self.assert_content(
|
413
|
+
self._view.content(None),
|
414
|
+
"""
|
415
|
+
<span class="simple-value none-type">None</span>
|
416
|
+
"""
|
417
|
+
)
|
418
|
+
self.assert_content(
|
419
|
+
self._view.content('<foo>'),
|
420
|
+
"""
|
421
|
+
<span class="simple-value str">'<foo>'</span>
|
422
|
+
"""
|
423
|
+
)
|
424
|
+
self.assert_content(
|
425
|
+
self._view.content(
|
426
|
+
'<hello><world> \nto everyone.', max_summary_len_for_str=10
|
427
|
+
),
|
428
|
+
"""
|
429
|
+
<span class="simple-value str"><hello><world>
|
430
|
+
to everyone.</span>
|
431
|
+
"""
|
432
|
+
)
|
433
|
+
|
434
|
+
def test_list(self):
|
435
|
+
self.assert_content(
|
436
|
+
self._view.content([1, 2, 'abc']),
|
437
|
+
"""
|
438
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value int">2</span></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><span class="simple-value str">'abc'</span></td></tr></table></div>
|
439
|
+
"""
|
440
|
+
)
|
441
|
+
self.assert_content(
|
442
|
+
self._view.content([1, 2, 'abc'], key_style='label'),
|
443
|
+
"""
|
444
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value int">2</span></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><span class="simple-value str">'abc'</span></td></tr></table></div>
|
445
|
+
"""
|
446
|
+
)
|
447
|
+
self.assert_content(
|
448
|
+
self._view.content([]),
|
449
|
+
"""
|
450
|
+
<div class="complex-value list"><span class="empty-container"></span></div>
|
451
|
+
"""
|
452
|
+
)
|
453
|
+
|
454
|
+
def test_tuple(self):
|
455
|
+
self.assert_content(
|
456
|
+
self._view.content((1, True)),
|
457
|
+
"""
|
458
|
+
<div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value bool">True</span></td></tr></table></div>
|
459
|
+
"""
|
460
|
+
)
|
461
|
+
self.assert_content(
|
462
|
+
self._view.content((1, True), key_style='label'),
|
463
|
+
"""
|
464
|
+
<div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value bool">True</span></td></tr></table></div>
|
465
|
+
"""
|
466
|
+
)
|
467
|
+
self.assert_content(
|
468
|
+
self._view.content(()),
|
469
|
+
"""
|
470
|
+
<div class="complex-value tuple"><span class="empty-container"></span></div>
|
471
|
+
"""
|
472
|
+
)
|
473
|
+
|
474
|
+
def test_dict(self):
|
475
|
+
self.assert_content(
|
476
|
+
self._view.content(dict(x=1, y='foo')),
|
477
|
+
"""
|
478
|
+
<div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">x<span class="tooltip">x</span></div><div class="summary-title">int</div><span class="tooltip">1</span></summary><span class="simple-value int">1</span></details><details open class="pyglove str"><summary><div class="summary-name">y<span class="tooltip">y</span></div><div class="summary-title">str</div><span class="tooltip">'foo'</span></summary><span class="simple-value str">'foo'</span></details></div>
|
479
|
+
"""
|
480
|
+
)
|
481
|
+
self.assert_content(
|
482
|
+
self._view.content(dict(x=1, y='foo'), key_style='label'),
|
483
|
+
"""
|
484
|
+
<div class="complex-value dict"><table><tr><td><span class="object-key str">x</span><span class="tooltip">x</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">y</span></td><td><span class="simple-value str">'foo'</span></td></tr></table></div>
|
485
|
+
"""
|
486
|
+
)
|
487
|
+
self.assert_content(
|
488
|
+
self._view.content({}),
|
489
|
+
"""
|
490
|
+
<div class="complex-value dict"><span class="empty-container"></span></div>
|
491
|
+
"""
|
492
|
+
)
|
493
|
+
|
494
|
+
def test_custom_types(self):
|
495
|
+
|
496
|
+
class Foo:
|
497
|
+
def __str__(self):
|
498
|
+
return '<Foo></Foo>'
|
499
|
+
|
500
|
+
self.assert_content(
|
501
|
+
self._view.content(Foo()),
|
502
|
+
"""
|
503
|
+
<span class="simple-value foo"><Foo></Foo></span>
|
504
|
+
"""
|
505
|
+
)
|
506
|
+
|
507
|
+
def test_custom_key_value_render(self):
|
508
|
+
def render_key(view, key, **kwargs):
|
509
|
+
del view, kwargs
|
510
|
+
return Html.element('span', [f'custom {key}'])
|
511
|
+
|
512
|
+
def render_value(view, *, value, **kwargs):
|
513
|
+
del view, kwargs
|
514
|
+
return Html.element('span', [f'custom {value}'])
|
515
|
+
|
516
|
+
self.assert_content(
|
517
|
+
self._view.complex_value(
|
518
|
+
dict(x=1, y='foo'),
|
519
|
+
parent=None,
|
520
|
+
root_path=KeyPath(),
|
521
|
+
render_key_fn=render_key,
|
522
|
+
render_value_fn=render_value,
|
523
|
+
),
|
524
|
+
"""
|
525
|
+
<div class="complex-value none-type"><span>custom 1</span><span>custom foo</span></div>
|
526
|
+
"""
|
527
|
+
)
|
528
|
+
self.assert_content(
|
529
|
+
self._view.complex_value(
|
530
|
+
dict(x=1, y='foo'),
|
531
|
+
parent=None,
|
532
|
+
key_style='label',
|
533
|
+
root_path=KeyPath(),
|
534
|
+
render_key_fn=render_key,
|
535
|
+
render_value_fn=render_value,
|
536
|
+
),
|
537
|
+
"""
|
538
|
+
<div class="complex-value none-type"><table><tr><td><span>custom x</span></td><td><span>custom 1</span></td></tr><tr><td><span>custom y</span></td><td><span>custom foo</span></td></tr></table></div>
|
539
|
+
"""
|
540
|
+
)
|
541
|
+
|
542
|
+
def test_key_style_with_nesting(self):
|
543
|
+
|
544
|
+
class Foo:
|
545
|
+
def __str__(self):
|
546
|
+
return '<Foo></Foo>'
|
547
|
+
|
548
|
+
self.assert_content(
|
549
|
+
self._view.content(
|
550
|
+
[
|
551
|
+
dict(
|
552
|
+
x=[(1, 2)],
|
553
|
+
y=['b', Foo()],
|
554
|
+
),
|
555
|
+
1,
|
556
|
+
[1, dict(xx=1, yy='a')]
|
557
|
+
]
|
558
|
+
),
|
559
|
+
"""
|
560
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
561
|
+
'x': [(1, 2)],
|
562
|
+
'y': ['b', <Foo></Foo>]
|
563
|
+
}</span></summary><div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">x<span class="tooltip">[0].x</span></div><div class="summary-title">list(...)</div><span class="tooltip">[(1, 2)]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0]</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div><span class="tooltip">(1, 2)</span></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].x[0][1]</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details><details class="pyglove list"><summary><div class="summary-name">y<span class="tooltip">[0].y</span></div><div class="summary-title">list(...)</div><span class="tooltip">['b', <Foo></Foo>]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].y[0]</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].y[1]</span></td><td><details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div><span class="tooltip"><Foo></Foo></span></summary><span class="simple-value foo"><Foo></Foo></span></details></td></tr></table></div></details></div></details></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[1, {
|
564
|
+
'xx': 1,
|
565
|
+
'yy': 'a'
|
566
|
+
}]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[2][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[2][1]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
567
|
+
'xx': 1,
|
568
|
+
'yy': 'a'
|
569
|
+
}</span></summary><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">xx<span class="tooltip">[2][1].xx</span></div><div class="summary-title">int</div><span class="tooltip">1</span></summary><span class="simple-value int">1</span></details><details open class="pyglove str"><summary><div class="summary-name">yy<span class="tooltip">[2][1].yy</span></div><div class="summary-title">str</div><span class="tooltip">'a'</span></summary><span class="simple-value str">'a'</span></details></div></details></td></tr></table></div></details></td></tr></table></div>
|
570
|
+
"""
|
571
|
+
)
|
572
|
+
|
573
|
+
self.assert_content(
|
574
|
+
self._view.content(
|
575
|
+
[
|
576
|
+
dict(
|
577
|
+
x=[(1, 2)],
|
578
|
+
y=['b', Foo()],
|
579
|
+
),
|
580
|
+
1,
|
581
|
+
[1, dict(xx=1, yy='a')]
|
582
|
+
],
|
583
|
+
key_style='label',
|
584
|
+
),
|
585
|
+
"""
|
586
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
587
|
+
'x': [(1, 2)],
|
588
|
+
'y': ['b', <Foo></Foo>]
|
589
|
+
}</span></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">x</span><span class="tooltip">[0].x</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[(1, 2)]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0]</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div><span class="tooltip">(1, 2)</span></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].x[0][1]</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">[0].y</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">['b', <Foo></Foo>]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].y[0]</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].y[1]</span></td><td><details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div><span class="tooltip"><Foo></Foo></span></summary><span class="simple-value foo"><Foo></Foo></span></details></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[1, {
|
590
|
+
'xx': 1,
|
591
|
+
'yy': 'a'
|
592
|
+
}]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[2][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[2][1]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
593
|
+
'xx': 1,
|
594
|
+
'yy': 'a'
|
595
|
+
}</span></summary><div class="complex-value dict"><table><tr><td><span class="object-key str">xx</span><span class="tooltip">[2][1].xx</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key str">yy</span><span class="tooltip">[2][1].yy</span></td><td><span class="simple-value str">'a'</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div>
|
596
|
+
"""
|
597
|
+
)
|
598
|
+
|
599
|
+
def _key_style(k, v, p):
|
600
|
+
del v, p
|
601
|
+
if k and k.key in ('x', 'xx'):
|
602
|
+
return 'label'
|
603
|
+
return 'summary'
|
604
|
+
|
605
|
+
self.assert_content(
|
606
|
+
self._view.content(
|
607
|
+
[
|
608
|
+
dict(
|
609
|
+
x=[(1, 2)],
|
610
|
+
y=['b', Foo()],
|
611
|
+
),
|
612
|
+
1,
|
613
|
+
[1, dict(xx=1, yy='a')]
|
614
|
+
],
|
615
|
+
key_style=_key_style,
|
616
|
+
),
|
617
|
+
"""
|
618
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
619
|
+
'x': [(1, 2)],
|
620
|
+
'y': ['b', <Foo></Foo>]
|
621
|
+
}</span></summary><div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">y<span class="tooltip">[0].y</span></div><div class="summary-title">list(...)</div><span class="tooltip">['b', <Foo></Foo>]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].y[0]</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].y[1]</span></td><td><details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div><span class="tooltip"><Foo></Foo></span></summary><span class="simple-value foo"><Foo></Foo></span></details></td></tr></table></div></details><table><tr><td><span class="object-key str">x</span><span class="tooltip">[0].x</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[(1, 2)]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0]</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div><span class="tooltip">(1, 2)</span></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].x[0][1]</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[1, {
|
622
|
+
'xx': 1,
|
623
|
+
'yy': 'a'
|
624
|
+
}]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[2][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[2][1]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
625
|
+
'xx': 1,
|
626
|
+
'yy': 'a'
|
627
|
+
}</span></summary><div class="complex-value dict"><details open class="pyglove str"><summary><div class="summary-name">yy<span class="tooltip">[2][1].yy</span></div><div class="summary-title">str</div><span class="tooltip">'a'</span></summary><span class="simple-value str">'a'</span></details><table><tr><td><span class="object-key str">xx</span><span class="tooltip">[2][1].xx</span></td><td><span class="simple-value int">1</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div>
|
628
|
+
"""
|
629
|
+
)
|
630
|
+
|
631
|
+
def test_key_color(self):
|
632
|
+
self.assert_content(
|
633
|
+
self._view.content(
|
634
|
+
dict(
|
635
|
+
x=[(1, 2)],
|
636
|
+
y=['b', dict(y=1)],
|
637
|
+
),
|
638
|
+
key_color=('white', 'red'),
|
639
|
+
enable_summary_tooltip=False,
|
640
|
+
),
|
641
|
+
"""
|
642
|
+
<div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">x<span class="tooltip">x</span></div><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int" style="color:white;background-color:red;">0</span><span class="tooltip">x[0]</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int" style="color:white;background-color:red;">0</span><span class="tooltip">x[0][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int" style="color:white;background-color:red;">1</span><span class="tooltip">x[0][1]</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details><details class="pyglove list"><summary><div class="summary-name">y<span class="tooltip">y</span></div><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int" style="color:white;background-color:red;">0</span><span class="tooltip">y[0]</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int" style="color:white;background-color:red;">1</span><span class="tooltip">y[1]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">y<span class="tooltip">y[1].y</span></div><div class="summary-title">int</div></summary><span class="simple-value int">1</span></details></div></details></td></tr></table></div></details></div>
|
643
|
+
"""
|
644
|
+
)
|
645
|
+
self.assert_content(
|
646
|
+
self._view.content(
|
647
|
+
dict(
|
648
|
+
x=[(1, 2)],
|
649
|
+
y=['b', dict(y=1)],
|
650
|
+
),
|
651
|
+
key_style='label',
|
652
|
+
enable_summary_tooltip=False,
|
653
|
+
key_color=(
|
654
|
+
lambda k, v, p: ('white', 'red')
|
655
|
+
if k.key == 'y' else (None, None)
|
656
|
+
),
|
657
|
+
),
|
658
|
+
"""
|
659
|
+
<div class="complex-value dict"><table><tr><td><span class="object-key str">x</span><span class="tooltip">x</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">x[0]</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">x[0][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">x[0][1]</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">y</span><span class="tooltip">y</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">y[0]</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">y[1]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">y</span><span class="tooltip">y[1].y</span></td><td><span class="simple-value int">1</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div>
|
660
|
+
"""
|
661
|
+
)
|
662
|
+
|
663
|
+
def test_enable_disable_tooltip(self):
|
664
|
+
|
665
|
+
class Foo:
|
666
|
+
def __str__(self):
|
667
|
+
return '<Foo></Foo>'
|
668
|
+
|
669
|
+
value = [
|
670
|
+
dict(
|
671
|
+
x=[(1, 2)],
|
672
|
+
y=['b', Foo()],
|
673
|
+
),
|
674
|
+
1,
|
675
|
+
[1, dict(xx=1, yy='a')]
|
676
|
+
]
|
677
|
+
self.assert_content(
|
678
|
+
self._view.content(value, enable_summary_tooltip=False),
|
679
|
+
"""
|
680
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">x<span class="tooltip">[0].x</span></div><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0]</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].x[0][1]</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details><details class="pyglove list"><summary><div class="summary-name">y<span class="tooltip">[0].y</span></div><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].y[0]</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].y[1]</span></td><td><details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div></summary><span class="simple-value foo"><Foo></Foo></span></details></td></tr></table></div></details></div></details></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[2][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[2][1]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">xx<span class="tooltip">[2][1].xx</span></div><div class="summary-title">int</div></summary><span class="simple-value int">1</span></details><details open class="pyglove str"><summary><div class="summary-name">yy<span class="tooltip">[2][1].yy</span></div><div class="summary-title">str</div></summary><span class="simple-value str">'a'</span></details></div></details></td></tr></table></div></details></td></tr></table></div>
|
681
|
+
"""
|
682
|
+
)
|
683
|
+
self.assert_content(
|
684
|
+
self._view.content(value, enable_key_tooltip=False),
|
685
|
+
"""
|
686
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
687
|
+
'x': [(1, 2)],
|
688
|
+
'y': ['b', <Foo></Foo>]
|
689
|
+
}</span></summary><div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">x</div><div class="summary-title">list(...)</div><span class="tooltip">[(1, 2)]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div><span class="tooltip">(1, 2)</span></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details><details class="pyglove list"><summary><div class="summary-name">y</div><div class="summary-title">list(...)</div><span class="tooltip">['b', <Foo></Foo>]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span></td><td><details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div><span class="tooltip"><Foo></Foo></span></summary><span class="simple-value foo"><Foo></Foo></span></details></td></tr></table></div></details></div></details></td></tr><tr><td><span class="object-key int">1</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">2</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[1, {
|
690
|
+
'xx': 1,
|
691
|
+
'yy': 'a'
|
692
|
+
}]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
693
|
+
'xx': 1,
|
694
|
+
'yy': 'a'
|
695
|
+
}</span></summary><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">xx</div><div class="summary-title">int</div><span class="tooltip">1</span></summary><span class="simple-value int">1</span></details><details open class="pyglove str"><summary><div class="summary-name">yy</div><div class="summary-title">str</div><span class="tooltip">'a'</span></summary><span class="simple-value str">'a'</span></details></div></details></td></tr></table></div></details></td></tr></table></div>
|
696
|
+
"""
|
697
|
+
)
|
698
|
+
self.assert_content(
|
699
|
+
self._view.content(
|
700
|
+
value, enable_summary_tooltip=False, enable_key_tooltip=False
|
701
|
+
),
|
702
|
+
"""
|
703
|
+
<div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">x</div><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details><details class="pyglove list"><summary><div class="summary-name">y</div><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span></td><td><details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div></summary><span class="simple-value foo"><Foo></Foo></span></details></td></tr></table></div></details></div></details></td></tr><tr><td><span class="object-key int">1</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">2</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">xx</div><div class="summary-title">int</div></summary><span class="simple-value int">1</span></details><details open class="pyglove str"><summary><div class="summary-name">yy</div><div class="summary-title">str</div></summary><span class="simple-value str">'a'</span></details></div></details></td></tr></table></div></details></td></tr></table></div>
|
704
|
+
"""
|
705
|
+
)
|
706
|
+
|
707
|
+
def test_include_exclude_immediate_child_keys(self):
|
708
|
+
self.assert_count(
|
709
|
+
self._view.content(
|
710
|
+
dict(a='x', b=dict(e='y'), c='z', d='w', e='v', f='u'),
|
711
|
+
include_keys=['a', 'b', 'c', 'd'],
|
712
|
+
exclude_keys=['c', 'e'],
|
713
|
+
enable_summary_tooltip=False,
|
714
|
+
enable_key_tooltip=False,
|
715
|
+
key_style='label',
|
716
|
+
),
|
717
|
+
'object-key',
|
718
|
+
3 + 1 # 'a', 'b', 'd' at the first level and 'e' at the second level.
|
719
|
+
)
|
720
|
+
|
721
|
+
def test_include_nodes_in_subtree(self):
|
722
|
+
self.assert_count(
|
723
|
+
self._view.content(
|
724
|
+
dict(a='x', b=dict(e='y'), c='z', d='w', e='v', f='u'),
|
725
|
+
include_keys=(lambda k, v, p: k.key == 'e' or isinstance(v, dict)),
|
726
|
+
enable_summary_tooltip=False,
|
727
|
+
enable_key_tooltip=False,
|
728
|
+
key_style='label',
|
729
|
+
),
|
730
|
+
'object-key',
|
731
|
+
3 # 'b', 'b.e', 'e'.
|
732
|
+
)
|
733
|
+
|
734
|
+
def test_exclude_nodes_in_subtree(self):
|
735
|
+
self.assert_count(
|
736
|
+
self._view.content(
|
737
|
+
dict(a='x', b=dict(e='y'), c='z', d='w', e='v', f='u'),
|
738
|
+
exclude_keys=(lambda k, v, p: k.key == 'e'),
|
739
|
+
enable_summary_tooltip=False,
|
740
|
+
enable_key_tooltip=False,
|
741
|
+
key_style='label',
|
742
|
+
),
|
743
|
+
'object-key',
|
744
|
+
5 # 'a', 'b', 'c', 'd', 'f'.
|
745
|
+
)
|
746
|
+
|
747
|
+
def test_highlight_lowlight(self):
|
748
|
+
self.assert_content(
|
749
|
+
self._view.content(
|
750
|
+
dict(a=1, b=dict(e='y'), c=2, d='w', e=3, f='u'),
|
751
|
+
enable_summary_tooltip=False,
|
752
|
+
enable_key_tooltip=False,
|
753
|
+
highlight=(lambda k, v, p: isinstance(v, int)),
|
754
|
+
lowlight=(lambda k, v, p: isinstance(v, str)),
|
755
|
+
),
|
756
|
+
"""
|
757
|
+
<div class="complex-value dict"><div class="highlight"><details open class="pyglove int"><summary><div class="summary-name">a</div><div class="summary-title">int</div></summary><span class="simple-value int">1</span></details></div><details class="pyglove dict"><summary><div class="summary-name">b</div><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><div class="lowlight"><details open class="pyglove str"><summary><div class="summary-name">e</div><div class="summary-title">str</div></summary><span class="simple-value str">'y'</span></details></div></div></details><div class="highlight"><details open class="pyglove int"><summary><div class="summary-name">c</div><div class="summary-title">int</div></summary><span class="simple-value int">2</span></details></div><div class="lowlight"><details open class="pyglove str"><summary><div class="summary-name">d</div><div class="summary-title">str</div></summary><span class="simple-value str">'w'</span></details></div><div class="highlight"><details open class="pyglove int"><summary><div class="summary-name">e</div><div class="summary-title">int</div></summary><span class="simple-value int">3</span></details></div><div class="lowlight"><details open class="pyglove str"><summary><div class="summary-name">f</div><div class="summary-title">str</div></summary><span class="simple-value str">'u'</span></details></div></div>
|
758
|
+
"""
|
759
|
+
)
|
760
|
+
|
761
|
+
def test_collapse_level(self):
|
762
|
+
x = dict(
|
763
|
+
a=dict(
|
764
|
+
b=dict(
|
765
|
+
c=dict(
|
766
|
+
d=dict()
|
767
|
+
)
|
768
|
+
)
|
769
|
+
),
|
770
|
+
aa=dict(
|
771
|
+
bb=dict(
|
772
|
+
cc=dict(
|
773
|
+
dd=dict()
|
774
|
+
)
|
775
|
+
)
|
776
|
+
)
|
777
|
+
)
|
778
|
+
self.assert_count(
|
779
|
+
self._view.content(x, collapse_level=0),
|
780
|
+
'open',
|
781
|
+
0
|
782
|
+
)
|
783
|
+
# There is no summary section, so there is no root.
|
784
|
+
self.assert_count(
|
785
|
+
self._view.content(x, collapse_level=1),
|
786
|
+
'open',
|
787
|
+
0
|
788
|
+
)
|
789
|
+
self.assert_count(
|
790
|
+
self._view.content(x, collapse_level=2),
|
791
|
+
'open',
|
792
|
+
2
|
793
|
+
)
|
794
|
+
self.assert_count(
|
795
|
+
self._view.content(x, collapse_level=3),
|
796
|
+
'open',
|
797
|
+
4
|
798
|
+
)
|
799
|
+
self.assert_count(
|
800
|
+
self._view.content(x, collapse_level=4),
|
801
|
+
'open',
|
802
|
+
6
|
803
|
+
)
|
804
|
+
self.assert_count(
|
805
|
+
self._view.content(x, collapse_level=None),
|
806
|
+
'open',
|
807
|
+
8
|
808
|
+
)
|
809
|
+
|
810
|
+
def test_uncollapse(self):
|
811
|
+
x = dict(
|
812
|
+
a=dict(
|
813
|
+
b=dict(
|
814
|
+
c=dict(
|
815
|
+
d=dict()
|
816
|
+
)
|
817
|
+
)
|
818
|
+
),
|
819
|
+
aa=dict(
|
820
|
+
bb=dict(
|
821
|
+
cc=dict(
|
822
|
+
dd=dict()
|
823
|
+
)
|
824
|
+
)
|
825
|
+
)
|
826
|
+
)
|
827
|
+
self.assert_count(
|
828
|
+
self._view.content(x, uncollapse=['a.b.c']),
|
829
|
+
'open',
|
830
|
+
3
|
831
|
+
)
|
832
|
+
self.assert_count(
|
833
|
+
self._view.content(x, uncollapse=['aa.bb.cc.dd', 'a.b']),
|
834
|
+
'open',
|
835
|
+
6
|
836
|
+
)
|
837
|
+
# Use both collapse_level and uncollapse.
|
838
|
+
self.assert_count(
|
839
|
+
self._view.content(x, collapse_level=2, uncollapse=['aa.bb.cc']),
|
840
|
+
'open',
|
841
|
+
4
|
842
|
+
)
|
843
|
+
self.assert_count(
|
844
|
+
self._view.content(
|
845
|
+
x, collapse_level=0, uncollapse=lambda k, v, p: len(k) < 3
|
846
|
+
),
|
847
|
+
'open',
|
848
|
+
4
|
849
|
+
)
|
850
|
+
|
851
|
+
|
852
|
+
class RenderTest(TestCase):
|
853
|
+
|
854
|
+
def test_render_html_convertible(self):
|
855
|
+
class Foo(base.HtmlConvertible):
|
856
|
+
def to_html(self, **kwargs):
|
857
|
+
return base.Html('<span>foo</span>')
|
858
|
+
self.assert_content(base.to_html(Foo()), '<span>foo</span>')
|
859
|
+
|
860
|
+
def test_render(self):
|
861
|
+
class Foo:
|
862
|
+
def __str__(self):
|
863
|
+
return '<Foo></Foo>'
|
864
|
+
|
865
|
+
self.assert_content(
|
866
|
+
self._view.render(
|
867
|
+
[
|
868
|
+
dict(
|
869
|
+
x=[(1, 2)],
|
870
|
+
y=['b', Foo()],
|
871
|
+
),
|
872
|
+
1,
|
873
|
+
[1, dict(xx=1, yy='a')]
|
874
|
+
],
|
875
|
+
),
|
876
|
+
"""
|
877
|
+
<details open class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[
|
878
|
+
{
|
879
|
+
'x': [(1, 2)],
|
880
|
+
'y': ['b', <Foo></Foo>]
|
881
|
+
},
|
882
|
+
1,
|
883
|
+
[1, {
|
884
|
+
'xx': 1,
|
885
|
+
'yy': 'a'
|
886
|
+
}]
|
887
|
+
]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
888
|
+
'x': [(1, 2)],
|
889
|
+
'y': ['b', <Foo></Foo>]
|
890
|
+
}</span></summary><div class="complex-value dict"><details class="pyglove list"><summary><div class="summary-name">x<span class="tooltip">[0].x</span></div><div class="summary-title">list(...)</div><span class="tooltip">[(1, 2)]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0]</span></td><td><details class="pyglove tuple"><summary><div class="summary-title">tuple(...)</div><span class="tooltip">(1, 2)</span></summary><div class="complex-value tuple"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].x[0][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].x[0][1]</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details><details class="pyglove list"><summary><div class="summary-name">y<span class="tooltip">[0].y</span></div><div class="summary-title">list(...)</div><span class="tooltip">['b', <Foo></Foo>]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[0].y[0]</span></td><td><span class="simple-value str">'b'</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[0].y[1]</span></td><td><details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div><span class="tooltip"><Foo></Foo></span></summary><span class="simple-value foo"><Foo></Foo></span></details></td></tr></table></div></details></div></details></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><details class="pyglove list"><summary><div class="summary-title">list(...)</div><span class="tooltip">[1, {
|
891
|
+
'xx': 1,
|
892
|
+
'yy': 'a'
|
893
|
+
}]</span></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span><span class="tooltip">[2][0]</span></td><td><span class="simple-value int">1</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[2][1]</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
894
|
+
'xx': 1,
|
895
|
+
'yy': 'a'
|
896
|
+
}</span></summary><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">xx<span class="tooltip">[2][1].xx</span></div><div class="summary-title">int</div><span class="tooltip">1</span></summary><span class="simple-value int">1</span></details><details open class="pyglove str"><summary><div class="summary-name">yy<span class="tooltip">[2][1].yy</span></div><div class="summary-title">str</div><span class="tooltip">'a'</span></summary><span class="simple-value str">'a'</span></details></div></details></td></tr></table></div></details></td></tr></table></div></details>
|
897
|
+
"""
|
898
|
+
)
|
899
|
+
|
900
|
+
def test_debug(self):
|
901
|
+
self.assertIn(
|
902
|
+
inspect.cleandoc(
|
903
|
+
"""
|
904
|
+
.debug-info-trigger {
|
905
|
+
display: inline-flex;
|
906
|
+
cursor: pointer;
|
907
|
+
font-size: 0.6em;
|
908
|
+
background-color: red;
|
909
|
+
color: white;
|
910
|
+
padding: 5px;
|
911
|
+
border-radius: 3px;
|
912
|
+
margin: 5px 0 5px 0;
|
913
|
+
}
|
914
|
+
.debug-info-trigger:hover + span.tooltip {
|
915
|
+
visibility: visible;
|
916
|
+
}
|
917
|
+
"""
|
918
|
+
),
|
919
|
+
self._view.render(dict(x=dict(y=1)), debug=True).style_section,
|
920
|
+
)
|
921
|
+
self.assert_content(
|
922
|
+
self._view.render(dict(x=1), debug=True),
|
923
|
+
"""
|
924
|
+
<details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div><span class="tooltip">{
|
925
|
+
'x': 1
|
926
|
+
}</span></summary><div><span class="debug-info-trigger">DEBUG</span><span class="tooltip debug-info">{
|
927
|
+
'css_classes': None,
|
928
|
+
'collapse_level': 1,
|
929
|
+
'uncollapse': KeyPathSet(),
|
930
|
+
'extra_flags': {},
|
931
|
+
'child_config': {},
|
932
|
+
'key_style': 'summary',
|
933
|
+
'key_color': None,
|
934
|
+
'include_keys': None,
|
935
|
+
'exclude_keys': None,
|
936
|
+
'summary_color': None,
|
937
|
+
'enable_summary': None,
|
938
|
+
'enable_summary_for_str': True,
|
939
|
+
'max_summary_len_for_str': 80,
|
940
|
+
'enable_summary_tooltip': True,
|
941
|
+
'enable_key_tooltip': True
|
942
|
+
}</span></div><div class="complex-value dict"><details open class="pyglove int"><summary><div class="summary-name">x<span class="tooltip">x</span></div><div class="summary-title">int</div><span class="tooltip">1</span></summary><div><span class="debug-info-trigger">DEBUG</span><span class="tooltip debug-info">{
|
943
|
+
'css_classes': None,
|
944
|
+
'collapse_level': 0,
|
945
|
+
'uncollapse': KeyPathSet(),
|
946
|
+
'extra_flags': {},
|
947
|
+
'child_config': {},
|
948
|
+
'key_style': 'summary',
|
949
|
+
'key_color': None,
|
950
|
+
'include_keys': None,
|
951
|
+
'exclude_keys': None,
|
952
|
+
'summary_color': None,
|
953
|
+
'enable_summary': None,
|
954
|
+
'enable_summary_for_str': True,
|
955
|
+
'max_summary_len_for_str': 80,
|
956
|
+
'enable_summary_tooltip': True,
|
957
|
+
'enable_key_tooltip': True
|
958
|
+
}</span></div><span class="simple-value int">1</span></details></div></details>
|
959
|
+
"""
|
960
|
+
)
|
961
|
+
|
962
|
+
|
963
|
+
class ExtensionTest(TestCase):
|
964
|
+
|
965
|
+
def test_no_overrides(self):
|
966
|
+
|
967
|
+
class Foo(tree_view.HtmlTreeView.Extension):
|
968
|
+
|
969
|
+
def __str__(self):
|
970
|
+
return 'Foo()'
|
971
|
+
|
972
|
+
self.assert_content(
|
973
|
+
self._view.summary(
|
974
|
+
Foo(),
|
975
|
+
enable_summary=True,
|
976
|
+
max_summary_len_for_str=10,
|
977
|
+
enable_summary_tooltip=True,
|
978
|
+
),
|
979
|
+
"""
|
980
|
+
<summary><div class="summary-title">Foo(...)</div><span class="tooltip">Foo()</span></summary>
|
981
|
+
"""
|
982
|
+
)
|
983
|
+
self.assert_content(
|
984
|
+
self._view.content(
|
985
|
+
Foo(),
|
986
|
+
),
|
987
|
+
"""
|
988
|
+
<span class="simple-value foo">Foo()</span>
|
989
|
+
"""
|
990
|
+
)
|
991
|
+
|
992
|
+
def test_config_override(self):
|
993
|
+
|
994
|
+
class Foo(tree_view.HtmlTreeView.Extension):
|
995
|
+
|
996
|
+
def __str__(self):
|
997
|
+
return 'Foo()'
|
998
|
+
|
999
|
+
@classmethod
|
1000
|
+
def _html_tree_view_css_styles(cls) -> list[str]:
|
1001
|
+
return [
|
1002
|
+
"""
|
1003
|
+
/* Foo style */
|
1004
|
+
"""
|
1005
|
+
]
|
1006
|
+
|
1007
|
+
@classmethod
|
1008
|
+
def _html_tree_view_config(cls) -> dict[str, Any]:
|
1009
|
+
return dict(
|
1010
|
+
css_classes=['foo', 'bar'],
|
1011
|
+
include_keys=['x', 'y', 'z', 'w'],
|
1012
|
+
exclude_keys=['z'],
|
1013
|
+
key_style='label',
|
1014
|
+
key_color=('white', 'red'),
|
1015
|
+
collapse_level=2,
|
1016
|
+
uncollapse=KeyPathSet(['x.a'], include_intermediate=True),
|
1017
|
+
child_config={
|
1018
|
+
'x': dict(
|
1019
|
+
summary_color=('white', 'blue'),
|
1020
|
+
key_style='label',
|
1021
|
+
key_color=('white', 'blue'),
|
1022
|
+
collapse_level=1,
|
1023
|
+
),
|
1024
|
+
'y': dict(
|
1025
|
+
uncollapse=KeyPathSet(['e']),
|
1026
|
+
)
|
1027
|
+
}
|
1028
|
+
)
|
1029
|
+
|
1030
|
+
def _html_tree_view_content(
|
1031
|
+
self,
|
1032
|
+
*,
|
1033
|
+
view: tree_view.HtmlTreeView,
|
1034
|
+
parent: Any,
|
1035
|
+
root_path: KeyPath,
|
1036
|
+
**kwargs) -> base.Html:
|
1037
|
+
return view.complex_value(
|
1038
|
+
kv=dict(
|
1039
|
+
x=dict(a=dict(foo=2)),
|
1040
|
+
y=dict(b=dict(bar=3), e=dict(srt=6)),
|
1041
|
+
z=dict(c=dict(baz=4)),
|
1042
|
+
w=dict(d=dict(qux=5)),
|
1043
|
+
),
|
1044
|
+
parent=self,
|
1045
|
+
root_path=root_path,
|
1046
|
+
**kwargs
|
1047
|
+
)
|
1048
|
+
|
1049
|
+
self.assertIn(
|
1050
|
+
'/* Foo style */',
|
1051
|
+
self._view.render(
|
1052
|
+
Foo(),
|
1053
|
+
enable_summary_tooltip=False,
|
1054
|
+
enable_key_tooltip=False,
|
1055
|
+
collapse_level=0,
|
1056
|
+
).styles.content,
|
1057
|
+
)
|
1058
|
+
self.assert_content(
|
1059
|
+
self._view.render(
|
1060
|
+
[Foo()],
|
1061
|
+
enable_summary_tooltip=False,
|
1062
|
+
enable_key_tooltip=False,
|
1063
|
+
collapse_level=0,
|
1064
|
+
),
|
1065
|
+
"""
|
1066
|
+
<details class="pyglove list"><summary><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><details open class="pyglove foo bar"><summary><div class="summary-title foo bar">Foo(...)</div></summary><div class="complex-value foo"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">x</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">a</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">foo</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">y</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">b</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">bar</span></td><td><span class="simple-value int">3</span></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">e</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">srt</span></td><td><span class="simple-value int">6</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">w</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">d</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">qux</span></td><td><span class="simple-value int">5</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details>
|
1067
|
+
"""
|
1068
|
+
)
|
1069
|
+
self.assert_content(
|
1070
|
+
self._view.render(
|
1071
|
+
[Foo()],
|
1072
|
+
enable_summary_tooltip=False,
|
1073
|
+
enable_key_tooltip=False,
|
1074
|
+
collapse_level=1,
|
1075
|
+
),
|
1076
|
+
"""
|
1077
|
+
<details open class="pyglove list"><summary><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><details open class="pyglove foo bar"><summary><div class="summary-title foo bar">Foo(...)</div></summary><div class="complex-value foo"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">x</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">a</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">foo</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">y</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">b</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">bar</span></td><td><span class="simple-value int">3</span></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">e</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">srt</span></td><td><span class="simple-value int">6</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">w</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">d</span></td><td><details class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">qux</span></td><td><span class="simple-value int">5</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details>
|
1078
|
+
"""
|
1079
|
+
)
|
1080
|
+
self.assert_content(
|
1081
|
+
self._view.render(
|
1082
|
+
[Foo()],
|
1083
|
+
enable_summary_tooltip=False,
|
1084
|
+
enable_key_tooltip=False,
|
1085
|
+
collapse_level=None,
|
1086
|
+
),
|
1087
|
+
"""
|
1088
|
+
<details open class="pyglove list"><summary><div class="summary-title">list(...)</div></summary><div class="complex-value list"><table><tr><td><span class="object-key int">0</span></td><td><details open class="pyglove foo bar"><summary><div class="summary-title foo bar">Foo(...)</div></summary><div class="complex-value foo"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">x</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">a</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:blue;">foo</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">y</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">b</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">bar</span></td><td><span class="simple-value int">3</span></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">e</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">srt</span></td><td><span class="simple-value int">6</span></td></tr></table></div></details></td></tr></table></div></details></td></tr><tr><td><span class="object-key str" style="color:white;background-color:red;">w</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">d</span></td><td><details open class="pyglove dict"><summary><div class="summary-title">dict(...)</div></summary><div class="complex-value dict"><table><tr><td><span class="object-key str" style="color:white;background-color:red;">qux</span></td><td><span class="simple-value int">5</span></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details></td></tr></table></div></details>
|
1089
|
+
"""
|
1090
|
+
)
|
1091
|
+
|
1092
|
+
def test_behavior_overrides(self):
|
1093
|
+
|
1094
|
+
class Foo(tree_view.HtmlTreeView.Extension):
|
1095
|
+
|
1096
|
+
def _html_tree_view_summary(
|
1097
|
+
self,
|
1098
|
+
*,
|
1099
|
+
view: tree_view.HtmlTreeView,
|
1100
|
+
**kwargs
|
1101
|
+
):
|
1102
|
+
kwargs.pop('title', None)
|
1103
|
+
return view.summary(
|
1104
|
+
self,
|
1105
|
+
title='MyFoo',
|
1106
|
+
**kwargs
|
1107
|
+
)
|
1108
|
+
|
1109
|
+
def _html_tree_view_content(
|
1110
|
+
self,
|
1111
|
+
**kwargs
|
1112
|
+
):
|
1113
|
+
del kwargs
|
1114
|
+
return 'Content of MyFoo'
|
1115
|
+
|
1116
|
+
self.assert_content(
|
1117
|
+
self._view.render(
|
1118
|
+
Foo(),
|
1119
|
+
enable_summary_tooltip=False,
|
1120
|
+
enable_key_tooltip=False,
|
1121
|
+
),
|
1122
|
+
"""
|
1123
|
+
<details open class="pyglove foo"><summary><div class="summary-title">MyFoo</div></summary>Content of MyFoo</details>
|
1124
|
+
"""
|
1125
|
+
)
|
1126
|
+
self.assert_content(
|
1127
|
+
self._view.render(
|
1128
|
+
Foo(),
|
1129
|
+
enable_summary=False,
|
1130
|
+
),
|
1131
|
+
"""
|
1132
|
+
Content of MyFoo
|
1133
|
+
"""
|
1134
|
+
)
|
1135
|
+
|
1136
|
+
|
1137
|
+
class OverrideKwargsTest(TestCase):
|
1138
|
+
|
1139
|
+
def test_override_collapse_level(self):
|
1140
|
+
def assert_collapse_level(
|
1141
|
+
call_kwargs, overriden_kwargs, expected_collapse_level
|
1142
|
+
):
|
1143
|
+
self.assertEqual(
|
1144
|
+
tree_view.HtmlTreeView.get_kwargs(
|
1145
|
+
call_kwargs,
|
1146
|
+
overriden_kwargs,
|
1147
|
+
KeyPath(''),
|
1148
|
+
).get('collapse_level', -1),
|
1149
|
+
expected_collapse_level,
|
1150
|
+
)
|
1151
|
+
assert_collapse_level(
|
1152
|
+
dict(),
|
1153
|
+
dict(),
|
1154
|
+
-1,
|
1155
|
+
)
|
1156
|
+
assert_collapse_level(
|
1157
|
+
dict(collapse_level=1),
|
1158
|
+
dict(),
|
1159
|
+
1,
|
1160
|
+
)
|
1161
|
+
assert_collapse_level(
|
1162
|
+
dict(collapse_level=1),
|
1163
|
+
dict(collapse_level=None),
|
1164
|
+
None,
|
1165
|
+
)
|
1166
|
+
assert_collapse_level(
|
1167
|
+
dict(collapse_level=1),
|
1168
|
+
dict(collapse_level=2),
|
1169
|
+
2,
|
1170
|
+
)
|
1171
|
+
assert_collapse_level(
|
1172
|
+
dict(collapse_level=2),
|
1173
|
+
dict(collapse_level=1),
|
1174
|
+
2,
|
1175
|
+
)
|
1176
|
+
|
1177
|
+
def test_override_uncollapse(self):
|
1178
|
+
def assert_uncollapse(
|
1179
|
+
call_kwargs,
|
1180
|
+
overriden_kwargs,
|
1181
|
+
expected_uncollapse,
|
1182
|
+
root_path=KeyPath(),
|
1183
|
+
):
|
1184
|
+
self.assertEqual(
|
1185
|
+
tree_view.HtmlTreeView.get_kwargs(
|
1186
|
+
call_kwargs,
|
1187
|
+
overriden_kwargs,
|
1188
|
+
root_path,
|
1189
|
+
).get('uncollapse', None),
|
1190
|
+
expected_uncollapse
|
1191
|
+
)
|
1192
|
+
assert_uncollapse(
|
1193
|
+
dict(uncollapse=None),
|
1194
|
+
dict(),
|
1195
|
+
None,
|
1196
|
+
)
|
1197
|
+
assert_uncollapse(
|
1198
|
+
dict(),
|
1199
|
+
dict(uncollapse=None),
|
1200
|
+
KeyPathSet(),
|
1201
|
+
)
|
1202
|
+
assert_uncollapse(
|
1203
|
+
dict(uncollapse=KeyPathSet(['a.b'])),
|
1204
|
+
dict(),
|
1205
|
+
KeyPathSet(['a.b']),
|
1206
|
+
)
|
1207
|
+
assert_uncollapse(
|
1208
|
+
dict(uncollapse=KeyPathSet(['a.b.c'])),
|
1209
|
+
dict(uncollapse=KeyPathSet(['b'])),
|
1210
|
+
KeyPathSet(['a.b.c', 'a.b']),
|
1211
|
+
root_path=KeyPath('a'),
|
1212
|
+
)
|
1213
|
+
assert_uncollapse(
|
1214
|
+
dict(uncollapse=[]),
|
1215
|
+
dict(uncollapse=KeyPathSet(['b'])),
|
1216
|
+
KeyPathSet(['a.b']),
|
1217
|
+
root_path=KeyPath('a'),
|
1218
|
+
)
|
1219
|
+
assert_uncollapse(
|
1220
|
+
dict(uncollapse=KeyPathSet(['a.b.c'])),
|
1221
|
+
dict(uncollapse=KeyPathSet(['b'])),
|
1222
|
+
KeyPathSet(['a.b.c', 'a.b']),
|
1223
|
+
root_path=KeyPath('a'),
|
1224
|
+
)
|
1225
|
+
|
1226
|
+
def test_override_kwargs(self):
|
1227
|
+
def assert_child_config(
|
1228
|
+
call_kwargs,
|
1229
|
+
overriden_kwargs,
|
1230
|
+
expected_child_config,
|
1231
|
+
root_path=KeyPath(''),
|
1232
|
+
):
|
1233
|
+
self.maxDiff = None
|
1234
|
+
actual = tree_view.HtmlTreeView.get_kwargs(
|
1235
|
+
call_kwargs,
|
1236
|
+
overriden_kwargs,
|
1237
|
+
root_path,
|
1238
|
+
)
|
1239
|
+
if actual != expected_child_config:
|
1240
|
+
print(actual)
|
1241
|
+
self.assertEqual(actual, expected_child_config)
|
1242
|
+
|
1243
|
+
assert_child_config(
|
1244
|
+
dict(
|
1245
|
+
child_config=dict(
|
1246
|
+
x=dict(
|
1247
|
+
enable_summary=True
|
1248
|
+
),
|
1249
|
+
)
|
1250
|
+
),
|
1251
|
+
dict(
|
1252
|
+
child_config=dict(
|
1253
|
+
x=dict(
|
1254
|
+
enable_summary_tooltip=False
|
1255
|
+
),
|
1256
|
+
y=dict(
|
1257
|
+
collapse_level=None
|
1258
|
+
),
|
1259
|
+
)
|
1260
|
+
),
|
1261
|
+
dict(
|
1262
|
+
child_config=dict(
|
1263
|
+
x=dict(
|
1264
|
+
enable_summary=True,
|
1265
|
+
enable_summary_tooltip=False,
|
1266
|
+
),
|
1267
|
+
y=dict(
|
1268
|
+
collapse_level=None
|
1269
|
+
),
|
1270
|
+
),
|
1271
|
+
),
|
1272
|
+
)
|
1273
|
+
|
1274
|
+
def test_get_child_kwargs(self):
|
1275
|
+
def assert_child_kwargs(
|
1276
|
+
call_kwargs,
|
1277
|
+
child_key,
|
1278
|
+
root_path,
|
1279
|
+
expected_child_kwargs,
|
1280
|
+
):
|
1281
|
+
self.maxDiff = None
|
1282
|
+
actual = tree_view.HtmlTreeView.get_child_kwargs(
|
1283
|
+
call_kwargs,
|
1284
|
+
call_kwargs.pop('child_config', {}),
|
1285
|
+
child_key,
|
1286
|
+
root_path,
|
1287
|
+
)
|
1288
|
+
if actual != expected_child_kwargs:
|
1289
|
+
print(actual)
|
1290
|
+
self.assertEqual(actual, expected_child_kwargs)
|
1291
|
+
|
1292
|
+
assert_child_kwargs(
|
1293
|
+
call_kwargs=dict(
|
1294
|
+
enable_summary=False,
|
1295
|
+
collapse_level=1,
|
1296
|
+
uncollapse=KeyPathSet(['a.y']),
|
1297
|
+
child_config=dict(
|
1298
|
+
x=dict(
|
1299
|
+
enable_summary=True,
|
1300
|
+
uncollapse=KeyPathSet(['b']),
|
1301
|
+
child_config=dict(
|
1302
|
+
y=dict(
|
1303
|
+
collapse_level=2
|
1304
|
+
),
|
1305
|
+
),
|
1306
|
+
),
|
1307
|
+
)
|
1308
|
+
),
|
1309
|
+
child_key='x',
|
1310
|
+
root_path=KeyPath(['a']),
|
1311
|
+
expected_child_kwargs=dict(
|
1312
|
+
enable_summary=True,
|
1313
|
+
collapse_level=1,
|
1314
|
+
uncollapse=KeyPathSet(['a.y', 'a.x.b']),
|
1315
|
+
child_config=dict(
|
1316
|
+
y=dict(
|
1317
|
+
collapse_level=2
|
1318
|
+
),
|
1319
|
+
),
|
1320
|
+
),
|
1321
|
+
)
|
1322
|
+
|
1323
|
+
|
1324
|
+
class HelperTest(TestCase):
|
1325
|
+
|
1326
|
+
def test_get_collapse_level(self):
|
1327
|
+
self.assertIsNone(
|
1328
|
+
tree_view.HtmlTreeView.get_collapse_level(
|
1329
|
+
None,
|
1330
|
+
None
|
1331
|
+
),
|
1332
|
+
)
|
1333
|
+
self.assertIsNone(
|
1334
|
+
tree_view.HtmlTreeView.get_collapse_level(
|
1335
|
+
1,
|
1336
|
+
None
|
1337
|
+
),
|
1338
|
+
)
|
1339
|
+
self.assertIsNone(
|
1340
|
+
tree_view.HtmlTreeView.get_collapse_level(
|
1341
|
+
None,
|
1342
|
+
1
|
1343
|
+
),
|
1344
|
+
)
|
1345
|
+
self.assertEqual(
|
1346
|
+
tree_view.HtmlTreeView.get_collapse_level(
|
1347
|
+
2,
|
1348
|
+
3
|
1349
|
+
),
|
1350
|
+
3
|
1351
|
+
)
|
1352
|
+
self.assertEqual(
|
1353
|
+
tree_view.HtmlTreeView.get_collapse_level(
|
1354
|
+
(3, -1),
|
1355
|
+
0
|
1356
|
+
),
|
1357
|
+
2
|
1358
|
+
)
|
1359
|
+
self.assertEqual(
|
1360
|
+
tree_view.HtmlTreeView.get_collapse_level(
|
1361
|
+
0,
|
1362
|
+
(2, 1)
|
1363
|
+
),
|
1364
|
+
3
|
1365
|
+
)
|
1366
|
+
|
1367
|
+
def test_get_color(self):
|
1368
|
+
self.assertEqual(
|
1369
|
+
tree_view.HtmlTreeView.get_color(None, KeyPath('a.b.c'), 1, None),
|
1370
|
+
(None, None)
|
1371
|
+
)
|
1372
|
+
self.assertEqual(
|
1373
|
+
tree_view.HtmlTreeView.get_color(
|
1374
|
+
('blue', None), KeyPath('a.b.c'), 1, None
|
1375
|
+
),
|
1376
|
+
('blue', None)
|
1377
|
+
)
|
1378
|
+
self.assertEqual(
|
1379
|
+
tree_view.HtmlTreeView.get_color(
|
1380
|
+
lambda k, v, p: ('white', 'black'), KeyPath('a.b.c'), 1, None),
|
1381
|
+
('white', 'black')
|
1382
|
+
)
|
1383
|
+
|
1384
|
+
def test_merge_uncollapse(self):
|
1385
|
+
self.assertEqual(
|
1386
|
+
tree_view.HtmlTreeView.merge_uncollapse(
|
1387
|
+
None,
|
1388
|
+
None,
|
1389
|
+
child_path=KeyPath.parse('a.b'),
|
1390
|
+
),
|
1391
|
+
KeyPathSet()
|
1392
|
+
)
|
1393
|
+
self.assertEqual(
|
1394
|
+
tree_view.HtmlTreeView.merge_uncollapse(
|
1395
|
+
KeyPathSet(['a.b']),
|
1396
|
+
None,
|
1397
|
+
child_path=KeyPath.parse('x'),
|
1398
|
+
),
|
1399
|
+
KeyPathSet(['a.b'])
|
1400
|
+
)
|
1401
|
+
path_fn = lambda k, v, p: True
|
1402
|
+
self.assertIs(
|
1403
|
+
tree_view.HtmlTreeView.merge_uncollapse(
|
1404
|
+
path_fn,
|
1405
|
+
None,
|
1406
|
+
child_path=KeyPath.parse('x'),
|
1407
|
+
),
|
1408
|
+
path_fn
|
1409
|
+
)
|
1410
|
+
self.assertEqual(
|
1411
|
+
tree_view.HtmlTreeView.merge_uncollapse(
|
1412
|
+
KeyPathSet(),
|
1413
|
+
KeyPathSet(['d']),
|
1414
|
+
child_path=KeyPath.parse('a.b'),
|
1415
|
+
),
|
1416
|
+
KeyPathSet(['a.b.d']),
|
1417
|
+
)
|
1418
|
+
self.assertEqual(
|
1419
|
+
tree_view.HtmlTreeView.merge_uncollapse(
|
1420
|
+
KeyPathSet(['a.b.c']),
|
1421
|
+
KeyPathSet(['d']),
|
1422
|
+
child_path=KeyPath.parse('a.b'),
|
1423
|
+
),
|
1424
|
+
KeyPathSet(['a.b.c', 'a.b.d']),
|
1425
|
+
)
|
1426
|
+
|
1427
|
+
def test_get_passthrough_kwargs(self):
|
1428
|
+
key_filter = (lambda k, v, p: k == 'foo')
|
1429
|
+
self.assertEqual(
|
1430
|
+
tree_view.HtmlTreeView.get_passthrough_kwargs(
|
1431
|
+
name='foo',
|
1432
|
+
value=1,
|
1433
|
+
root_path=KeyPath(),
|
1434
|
+
enable_summary=False,
|
1435
|
+
include_keys=key_filter,
|
1436
|
+
),
|
1437
|
+
{
|
1438
|
+
'enable_summary': False,
|
1439
|
+
'include_keys': key_filter,
|
1440
|
+
},
|
1441
|
+
)
|
1442
|
+
|
1443
|
+
self.assertEqual(
|
1444
|
+
tree_view.HtmlTreeView.get_passthrough_kwargs(
|
1445
|
+
name='foo',
|
1446
|
+
value=1,
|
1447
|
+
root_path=KeyPath(),
|
1448
|
+
enable_summary=False,
|
1449
|
+
include_keys=['a'],
|
1450
|
+
extra_flags=dict(x=1),
|
1451
|
+
exclude_keys='a',
|
1452
|
+
remove=['extra_flags']
|
1453
|
+
),
|
1454
|
+
{
|
1455
|
+
'enable_summary': False,
|
1456
|
+
},
|
1457
|
+
)
|
1458
|
+
|
1459
|
+
|
1460
|
+
if __name__ == '__main__':
|
1461
|
+
unittest.main()
|