pyglove 0.4.5.dev202410170809__py3-none-any.whl → 0.4.5.dev202410180346__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyglove/core/__init__.py +1 -0
- pyglove/core/symbolic/base.py +10 -10
- pyglove/core/symbolic/base_test.py +47 -8
- pyglove/core/symbolic/diff.py +60 -66
- pyglove/core/symbolic/diff_test.py +33 -98
- pyglove/core/symbolic/ref.py +17 -3
- pyglove/core/symbolic/ref_test.py +9 -110
- pyglove/core/views/__init__.py +1 -0
- pyglove/core/views/base.py +45 -151
- pyglove/core/views/base_test.py +14 -49
- pyglove/core/views/html/base.py +19 -18
- pyglove/core/views/html/base_test.py +10 -8
- pyglove/core/views/html/tree_view.py +911 -561
- pyglove/core/views/html/tree_view_test.py +743 -164
- {pyglove-0.4.5.dev202410170809.dist-info → pyglove-0.4.5.dev202410180346.dist-info}/METADATA +1 -1
- {pyglove-0.4.5.dev202410170809.dist-info → pyglove-0.4.5.dev202410180346.dist-info}/RECORD +19 -19
- {pyglove-0.4.5.dev202410170809.dist-info → pyglove-0.4.5.dev202410180346.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev202410170809.dist-info → pyglove-0.4.5.dev202410180346.dist-info}/WHEEL +0 -0
- {pyglove-0.4.5.dev202410170809.dist-info → pyglove-0.4.5.dev202410180346.dist-info}/top_level.txt +0 -0
pyglove/core/__init__.py
CHANGED
pyglove/core/symbolic/base.py
CHANGED
@@ -949,21 +949,22 @@ class Symbolic(
|
|
949
949
|
"""Serializes current object into a JSON string."""
|
950
950
|
return to_json_str(self, json_indent=json_indent, **kwargs)
|
951
951
|
|
952
|
-
# pytype: disable=annotation-type-mismatch
|
953
952
|
def _html_tree_view_content(
|
954
953
|
self,
|
955
954
|
*,
|
956
955
|
view: html.HtmlTreeView,
|
957
|
-
name: Optional[str],
|
958
|
-
parent: Any,
|
959
|
-
root_path: object_utils.KeyPath,
|
960
|
-
|
961
|
-
hide_default_values: bool = html.HtmlView.PresetArgValue(False),
|
962
|
-
use_inferred: bool = html.HtmlView.PresetArgValue(True),
|
956
|
+
name: Optional[str] = None,
|
957
|
+
parent: Any = None,
|
958
|
+
root_path: Optional[object_utils.KeyPath] = None,
|
959
|
+
extra_flags: Optional[Dict[str, Any]],
|
963
960
|
**kwargs,
|
964
961
|
) -> html.Html:
|
965
|
-
# pytype: enable=annotation-type-mismatch
|
966
962
|
"""Returns the content HTML for a symbolic object.."""
|
963
|
+
extra_flags = extra_flags or {}
|
964
|
+
hide_frozen = extra_flags.get('hide_frozen', True)
|
965
|
+
hide_default_values = extra_flags.get('hide_default_values', False)
|
966
|
+
use_inferred = extra_flags.get('use_inferred', False)
|
967
|
+
|
967
968
|
kv = {}
|
968
969
|
for k, v in self.sym_items():
|
969
970
|
# Apply frozen filter.
|
@@ -981,8 +982,7 @@ class Symbolic(
|
|
981
982
|
kv[k] = v
|
982
983
|
return view.complex_value(
|
983
984
|
kv, name=name, parent=self, root_path=root_path,
|
984
|
-
|
985
|
-
use_inferred=use_inferred, **kwargs
|
985
|
+
extra_flags=extra_flags, **kwargs
|
986
986
|
)
|
987
987
|
|
988
988
|
@classmethod
|
@@ -20,6 +20,7 @@ import unittest
|
|
20
20
|
|
21
21
|
from pyglove.core import object_utils
|
22
22
|
from pyglove.core import typing as pg_typing
|
23
|
+
from pyglove.core import views
|
23
24
|
from pyglove.core.symbolic import base
|
24
25
|
from pyglove.core.symbolic.dict import Dict
|
25
26
|
from pyglove.core.symbolic.inferred import ValueFromParentChain
|
@@ -112,7 +113,7 @@ class HtmlTreeViewExtensionTest(unittest.TestCase):
|
|
112
113
|
enable_key_tooltip=False
|
113
114
|
),
|
114
115
|
"""
|
115
|
-
<details open class="pyglove foo"><summary><div class="
|
116
|
+
<details open class="pyglove foo"><summary><div class="summary-title">Foo(...)</div></summary><div class="complex-value foo"><details open class="pyglove int"><summary><div class="summary-name">x</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">y</div><div class="summary-title">str</div></summary><span class="simple-value str">'foo'</span></details></div></details>
|
116
117
|
"""
|
117
118
|
)
|
118
119
|
# Hide frozen and default values.
|
@@ -121,11 +122,28 @@ class HtmlTreeViewExtensionTest(unittest.TestCase):
|
|
121
122
|
enable_summary_tooltip=False,
|
122
123
|
enable_key_tooltip=False,
|
123
124
|
collapse_level=0,
|
124
|
-
|
125
|
-
|
125
|
+
key_style='label',
|
126
|
+
extra_flags=dict(
|
127
|
+
hide_frozen=True,
|
128
|
+
hide_default_values=True
|
129
|
+
)
|
126
130
|
),
|
127
131
|
"""
|
128
|
-
<details class="pyglove foo"><summary><div class="
|
132
|
+
<details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div></summary><div class="complex-value foo"><table><tr><td><span class="object-key str">x</span></td><td><span class="simple-value int">1</span></td></tr></table></div></details>
|
133
|
+
"""
|
134
|
+
)
|
135
|
+
self.assert_content(
|
136
|
+
Foo(x=1, y='foo').to_html(
|
137
|
+
enable_summary_tooltip=False,
|
138
|
+
enable_key_tooltip=False,
|
139
|
+
collapse_level=0,
|
140
|
+
extra_flags=dict(
|
141
|
+
hide_frozen=True,
|
142
|
+
hide_default_values=True
|
143
|
+
)
|
144
|
+
),
|
145
|
+
"""
|
146
|
+
<details class="pyglove foo"><summary><div class="summary-title">Foo(...)</div></summary><div class="complex-value foo"><details open class="pyglove int"><summary><div class="summary-name">x</div><div class="summary-title">int</div></summary><span class="simple-value int">1</span></details></div></details>
|
129
147
|
"""
|
130
148
|
)
|
131
149
|
# Use inferred values.
|
@@ -134,22 +152,43 @@ class HtmlTreeViewExtensionTest(unittest.TestCase):
|
|
134
152
|
x.x.to_html(
|
135
153
|
enable_summary_tooltip=False,
|
136
154
|
enable_key_tooltip=False,
|
137
|
-
|
155
|
+
key_style='label',
|
156
|
+
extra_flags=dict(
|
157
|
+
use_inferred=False
|
158
|
+
)
|
138
159
|
),
|
139
160
|
"""
|
140
|
-
<details open class="pyglove dict"><summary><div class="
|
161
|
+
<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">y</span></td><td><details class="pyglove value-from-parent-chain"><summary><div class="summary-title">ValueFromParentChain(...)</div></summary><div class="complex-value value-from-parent-chain"><span class="empty-container"></span></div></details></td></tr></table></div></details>
|
141
162
|
"""
|
142
163
|
)
|
143
164
|
self.assert_content(
|
144
165
|
x.x.to_html(
|
145
166
|
enable_summary_tooltip=False,
|
146
167
|
enable_key_tooltip=False,
|
147
|
-
|
168
|
+
key_style='label',
|
169
|
+
extra_flags=dict(
|
170
|
+
use_inferred=True
|
171
|
+
)
|
148
172
|
),
|
149
173
|
"""
|
150
|
-
<details open class="pyglove dict"><summary><div class="
|
174
|
+
<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">y</span></td><td><span class="simple-value int">2</span></td></tr></table></div></details>
|
151
175
|
"""
|
152
176
|
)
|
177
|
+
# Test collapse level.
|
178
|
+
v = Foo(1, Foo(2, Foo(3, Foo(4))))
|
179
|
+
with views.view_options(key_style='label'):
|
180
|
+
self.assertEqual(
|
181
|
+
v.to_html(collapse_level=0).content.count('open'), 0
|
182
|
+
)
|
183
|
+
self.assertEqual(
|
184
|
+
v.to_html(collapse_level=1).content.count('open'), 1
|
185
|
+
)
|
186
|
+
self.assertEqual(
|
187
|
+
v.to_html(collapse_level=2).content.count('open'), 2
|
188
|
+
)
|
189
|
+
self.assertEqual(
|
190
|
+
v.to_html(collapse_level=None).content.count('open'), 4
|
191
|
+
)
|
153
192
|
|
154
193
|
|
155
194
|
if __name__ == '__main__':
|
pyglove/core/symbolic/diff.py
CHANGED
@@ -13,7 +13,7 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
"""Symbolic differences."""
|
15
15
|
|
16
|
-
from typing import Any, Callable,
|
16
|
+
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
17
17
|
|
18
18
|
from pyglove.core import object_utils
|
19
19
|
from pyglove.core import typing as pg_typing
|
@@ -150,8 +150,9 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
150
150
|
self,
|
151
151
|
*,
|
152
152
|
view: html.HtmlTreeView,
|
153
|
+
css_classes: Optional[Sequence[str]] = None,
|
153
154
|
title: Optional[str] = None,
|
154
|
-
max_summary_len_for_str: int =
|
155
|
+
max_summary_len_for_str: int = 80,
|
155
156
|
**kwargs,
|
156
157
|
) -> Optional[html.Html]:
|
157
158
|
# pytype: enable=annotation-type-mismatch
|
@@ -165,12 +166,14 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
165
166
|
return view.summary(
|
166
167
|
self,
|
167
168
|
title=title or 'Diff',
|
169
|
+
css_classes=css_classes,
|
168
170
|
max_summary_len_for_str=max_summary_len_for_str,
|
169
171
|
**kwargs
|
170
172
|
)
|
171
173
|
return view.summary(
|
172
174
|
self.value,
|
173
175
|
title=title,
|
176
|
+
css_classes=css_classes,
|
174
177
|
max_summary_len_for_str=max_summary_len_for_str,
|
175
178
|
**kwargs
|
176
179
|
)
|
@@ -186,6 +189,7 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
186
189
|
return view.summary(
|
187
190
|
self,
|
188
191
|
title=title or diff_title,
|
192
|
+
css_classes=css_classes,
|
189
193
|
max_summary_len_for_str=max_summary_len_for_str,
|
190
194
|
**kwargs
|
191
195
|
)
|
@@ -196,6 +200,7 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
196
200
|
view: html.HtmlTreeView,
|
197
201
|
parent: Any,
|
198
202
|
root_path: object_utils.KeyPath,
|
203
|
+
css_classes: Optional[Sequence[str]] = None,
|
199
204
|
**kwargs
|
200
205
|
) -> html.Html:
|
201
206
|
if not bool(self):
|
@@ -203,46 +208,30 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
203
208
|
root = html.Html.element(
|
204
209
|
'span',
|
205
210
|
# CSS class already defined in HtmlTreeView.
|
206
|
-
|
211
|
+
css_classes=['diff-empty']
|
207
212
|
)
|
208
213
|
else:
|
209
214
|
# When there is no diff, but the same value needs to be displayed
|
210
215
|
# we simply return the value.
|
211
|
-
root =
|
212
|
-
|
213
|
-
[
|
214
|
-
|
215
|
-
self.value, parent=parent, root_path=root_path, **kwargs,
|
216
|
-
)
|
217
|
-
],
|
218
|
-
css_class=['diff_left', 'diff_right']
|
216
|
+
root = view.content(
|
217
|
+
self.value, parent=parent, root_path=root_path,
|
218
|
+
css_classes=['no-diff', view.css_class_name(self.value)],
|
219
|
+
**kwargs,
|
219
220
|
)
|
220
221
|
elif self.is_leaf:
|
221
222
|
root = html.Html.element(
|
222
223
|
'div',
|
223
224
|
[
|
224
|
-
#
|
225
|
-
|
226
|
-
'
|
227
|
-
[
|
228
|
-
view.render(
|
229
|
-
self.left, root_path=root_path + 'left', **kwargs
|
230
|
-
)
|
231
|
-
],
|
232
|
-
css_class=['diff_left'],
|
225
|
+
view.render( # pylint: disable=g-long-ternary
|
226
|
+
self.left, root_path=root_path + 'left',
|
227
|
+
css_classes=['diff-left'], **kwargs
|
233
228
|
) if self.left != Diff.MISSING else None,
|
234
|
-
#
|
235
|
-
|
236
|
-
'
|
237
|
-
|
238
|
-
view.render(
|
239
|
-
self.right, root_path=root_path + 'right', **kwargs
|
240
|
-
)
|
241
|
-
],
|
242
|
-
css_class=['diff_right'],
|
243
|
-
) if self.right != Diff.MISSING else None,
|
229
|
+
view.render( # pylint: disable=g-long-ternary
|
230
|
+
self.right, root_path=root_path + 'right',
|
231
|
+
css_classes=['diff-right'], **kwargs
|
232
|
+
) if self.right != Diff.MISSING else None,
|
244
233
|
],
|
245
|
-
|
234
|
+
css_classes=['diff-value']
|
246
235
|
)
|
247
236
|
else:
|
248
237
|
assert isinstance(self.left, type)
|
@@ -257,20 +246,21 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
257
246
|
for k, v in self.children.items():
|
258
247
|
k = key_fn(k)
|
259
248
|
child_path = root_path + k
|
260
|
-
|
249
|
+
has_diff = bool(v)
|
261
250
|
s.write('<tr><td>')
|
262
251
|
# Print Key.
|
263
252
|
s.write(
|
264
253
|
view.object_key(
|
265
|
-
|
266
|
-
|
267
|
-
**kwargs
|
254
|
+
child_path, value=v, parent=self,
|
255
|
+
css_classes=None if has_diff else ['no-diff'],
|
268
256
|
),
|
269
257
|
)
|
270
258
|
# Print Value.
|
271
259
|
s.write(
|
272
260
|
'</td><td>',
|
273
|
-
view.render(
|
261
|
+
view.render(
|
262
|
+
v, root_path=child_path, **kwargs
|
263
|
+
),
|
274
264
|
'</td></tr>'
|
275
265
|
)
|
276
266
|
root = html.Html.element(
|
@@ -278,61 +268,65 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
278
268
|
[
|
279
269
|
'<table>', s, '</table>'
|
280
270
|
],
|
281
|
-
|
282
|
-
'
|
271
|
+
css_classes=[
|
272
|
+
'complex-value', view.css_class_name(self.left), css_classes,
|
283
273
|
]
|
284
274
|
)
|
285
275
|
return root
|
286
276
|
|
287
|
-
def
|
288
|
-
return
|
277
|
+
def _html_tree_view_config(self) -> dict[str, Any]:
|
278
|
+
return html.HtmlTreeView.get_kwargs(
|
279
|
+
super()._html_tree_view_config(),
|
280
|
+
dict(
|
281
|
+
css_classes=[
|
282
|
+
'has-diff' if bool(self) else 'no-diff'
|
283
|
+
]
|
284
|
+
)
|
285
|
+
)
|
286
|
+
|
287
|
+
@classmethod
|
288
|
+
def _html_tree_view_css_styles(cls) -> list[str]:
|
289
|
+
return super()._html_tree_view_css_styles() + [
|
289
290
|
"""
|
290
291
|
/* Diff styles. */
|
291
|
-
.diff
|
292
|
+
.has-diff.summary-title::after {
|
292
293
|
content: ' (diff)';
|
293
294
|
color: #aaa;
|
294
295
|
}
|
295
|
-
.diff
|
296
|
+
.has-diff.summary-title {
|
296
297
|
background-color: yellow;
|
297
298
|
}
|
298
|
-
.diff
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
align-items: center;
|
299
|
+
.no-diff.summary-title::after {
|
300
|
+
content: ' (no diff)';
|
301
|
+
font-style: italic;
|
302
|
+
font-weight: normal;
|
303
|
+
color: #aaa;
|
304
304
|
}
|
305
|
-
.
|
306
|
-
opacity: 0.
|
305
|
+
.no-diff {
|
306
|
+
opacity: 0.6;
|
307
307
|
}
|
308
|
-
.
|
308
|
+
.no-diff.simple_value::after {
|
309
309
|
content: '(no diff)';
|
310
310
|
margin-left: 0.5em;
|
311
311
|
color: #aaa;
|
312
312
|
font-style: italic;
|
313
313
|
}
|
314
|
-
.
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
314
|
+
.diff-empty::before {
|
315
|
+
content: '(empty)';
|
316
|
+
font-style: italic;
|
317
|
+
margin-left: 0.5em;
|
318
|
+
color: #aaa;
|
319
319
|
}
|
320
|
-
.
|
320
|
+
.diff-left.summary-title::before, .diff-left.simple-value::before{
|
321
321
|
content: '🇱';
|
322
322
|
}
|
323
|
-
.
|
323
|
+
.diff-left {
|
324
324
|
background-color: #ffcccc;
|
325
325
|
}
|
326
|
-
.
|
327
|
-
background-color: #ffcccc;
|
328
|
-
}
|
329
|
-
.diff_value .diff_right::before {
|
326
|
+
.diff-right.summary-title::before, .diff-right.simple-value::before{
|
330
327
|
content: '🇷';
|
331
328
|
}
|
332
|
-
.
|
333
|
-
background-color: #ccffcc;
|
334
|
-
}
|
335
|
-
.diff_value .diff_right > details {
|
329
|
+
.diff-right {
|
336
330
|
background-color: #ccffcc;
|
337
331
|
}
|
338
332
|
"""
|