pyglove 0.4.5.dev20240318__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.dev20240318.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.dev20240318.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.dev20240318.dist-info/RECORD +0 -185
- /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
- {pyglove-0.4.5.dev20240318.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev20240318.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/top_level.txt +0 -0
pyglove/core/symbolic/diff.py
CHANGED
@@ -13,17 +13,18 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
"""Symbolic differences."""
|
15
15
|
|
16
|
-
from typing import Any, Callable, Tuple, Union
|
16
|
+
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
17
17
|
|
18
|
-
from pyglove.core import object_utils
|
19
18
|
from pyglove.core import typing as pg_typing
|
19
|
+
from pyglove.core import utils
|
20
20
|
from pyglove.core.symbolic import base
|
21
21
|
from pyglove.core.symbolic import list as pg_list
|
22
22
|
from pyglove.core.symbolic import object as pg_object
|
23
23
|
from pyglove.core.symbolic.pure_symbolic import PureSymbolic
|
24
|
+
from pyglove.core.views.html import tree_view
|
24
25
|
|
25
26
|
|
26
|
-
class Diff(PureSymbolic, pg_object.Object):
|
27
|
+
class Diff(PureSymbolic, pg_object.Object, tree_view.HtmlTreeView.Extension):
|
27
28
|
"""A value diff between two objects: a 'left' object and a 'right' object.
|
28
29
|
|
29
30
|
If one of them is missing, it may be represented by pg.Diff.MISSING
|
@@ -111,8 +112,7 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
111
112
|
return 'No diff'
|
112
113
|
# When there is no diff, but the same value needs to be displayed
|
113
114
|
# we simply return the value.
|
114
|
-
return
|
115
|
-
self.value, compact, verbose, root_indent, **kwargs)
|
115
|
+
return utils.format(self.value, compact, verbose, root_indent, **kwargs)
|
116
116
|
if self.is_leaf:
|
117
117
|
exclude_keys = kwargs.pop('exclude_keys', None)
|
118
118
|
exclude_keys = exclude_keys or set()
|
@@ -128,7 +128,7 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
128
128
|
verbose=verbose,
|
129
129
|
root_indent=root_indent,
|
130
130
|
cls_name='',
|
131
|
-
bracket_type=
|
131
|
+
bracket_type=utils.BracketType.SQUARE,
|
132
132
|
**kwargs,
|
133
133
|
)
|
134
134
|
if self.left is self.right:
|
@@ -140,10 +140,198 @@ class Diff(PureSymbolic, pg_object.Object):
|
|
140
140
|
verbose=verbose,
|
141
141
|
root_indent=root_indent,
|
142
142
|
cls_name=cls_name,
|
143
|
-
bracket_type=
|
143
|
+
bracket_type=utils.BracketType.ROUND,
|
144
144
|
**kwargs,
|
145
145
|
)
|
146
146
|
|
147
|
+
# pytype: disable=annotation-type-mismatch
|
148
|
+
def _html_tree_view_summary(
|
149
|
+
self,
|
150
|
+
*,
|
151
|
+
view: tree_view.HtmlTreeView,
|
152
|
+
css_classes: Optional[Sequence[str]] = None,
|
153
|
+
title: Optional[str] = None,
|
154
|
+
max_summary_len_for_str: int = 80,
|
155
|
+
**kwargs,
|
156
|
+
) -> Optional[tree_view.Html]:
|
157
|
+
# pytype: enable=annotation-type-mismatch
|
158
|
+
if not bool(self):
|
159
|
+
v = self.value
|
160
|
+
if (isinstance(v, (int, float, bool, type(None)))
|
161
|
+
or (isinstance(v, str) and len(v) <= max_summary_len_for_str)):
|
162
|
+
return None
|
163
|
+
|
164
|
+
if v == Diff.MISSING:
|
165
|
+
return view.summary(
|
166
|
+
self,
|
167
|
+
title=title or 'Diff',
|
168
|
+
css_classes=css_classes,
|
169
|
+
max_summary_len_for_str=max_summary_len_for_str,
|
170
|
+
**kwargs
|
171
|
+
)
|
172
|
+
return view.summary(
|
173
|
+
self.value,
|
174
|
+
title=title,
|
175
|
+
css_classes=css_classes,
|
176
|
+
max_summary_len_for_str=max_summary_len_for_str,
|
177
|
+
**kwargs
|
178
|
+
)
|
179
|
+
elif self.is_leaf:
|
180
|
+
return None
|
181
|
+
else:
|
182
|
+
assert isinstance(self.left, type), self.left
|
183
|
+
assert isinstance(self.right, type), self.right
|
184
|
+
if self.left is self.right:
|
185
|
+
diff_title = self.left.__name__
|
186
|
+
else:
|
187
|
+
diff_title = f'{self.left.__name__} | {self.right.__name__}'
|
188
|
+
return view.summary(
|
189
|
+
self,
|
190
|
+
title=title or diff_title,
|
191
|
+
css_classes=css_classes,
|
192
|
+
max_summary_len_for_str=max_summary_len_for_str,
|
193
|
+
**kwargs
|
194
|
+
)
|
195
|
+
|
196
|
+
def _html_tree_view_content(
|
197
|
+
self,
|
198
|
+
*,
|
199
|
+
view: tree_view.HtmlTreeView,
|
200
|
+
parent: Any = None,
|
201
|
+
root_path: Optional[utils.KeyPath] = None,
|
202
|
+
css_classes: Optional[Sequence[str]] = None,
|
203
|
+
**kwargs,
|
204
|
+
) -> tree_view.Html:
|
205
|
+
root_path = root_path or utils.KeyPath()
|
206
|
+
if not bool(self):
|
207
|
+
if self.value == Diff.MISSING:
|
208
|
+
root = tree_view.Html.element(
|
209
|
+
'span',
|
210
|
+
# CSS class already defined in HtmlTreeView.
|
211
|
+
css_classes=['diff-empty']
|
212
|
+
)
|
213
|
+
else:
|
214
|
+
# When there is no diff, but the same value needs to be displayed
|
215
|
+
# we simply return the value.
|
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,
|
220
|
+
)
|
221
|
+
elif self.is_leaf:
|
222
|
+
root = tree_view.Html.element(
|
223
|
+
'div',
|
224
|
+
[
|
225
|
+
view.render( # pylint: disable=g-long-ternary
|
226
|
+
self.left, root_path=root_path + 'left',
|
227
|
+
css_classes=['diff-left'], **kwargs
|
228
|
+
) if self.left != 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,
|
233
|
+
],
|
234
|
+
css_classes=['diff-value']
|
235
|
+
)
|
236
|
+
else:
|
237
|
+
assert isinstance(self.left, type)
|
238
|
+
assert isinstance(self.right, type)
|
239
|
+
|
240
|
+
if issubclass(self.left, list):
|
241
|
+
key_fn = int
|
242
|
+
else:
|
243
|
+
key_fn = lambda k: k
|
244
|
+
|
245
|
+
s = tree_view.Html()
|
246
|
+
for k, v in self.children.items():
|
247
|
+
k = key_fn(k)
|
248
|
+
child_path = root_path + k
|
249
|
+
has_diff = bool(v)
|
250
|
+
s.write('<tr><td>')
|
251
|
+
# Print Key.
|
252
|
+
s.write(
|
253
|
+
view.object_key(
|
254
|
+
child_path, value=v, parent=self,
|
255
|
+
css_classes=None if has_diff else ['no-diff'],
|
256
|
+
),
|
257
|
+
)
|
258
|
+
# Print Value.
|
259
|
+
s.write(
|
260
|
+
'</td><td>',
|
261
|
+
view.render(
|
262
|
+
v, root_path=child_path, **kwargs
|
263
|
+
),
|
264
|
+
'</td></tr>'
|
265
|
+
)
|
266
|
+
root = tree_view.Html.element(
|
267
|
+
'div',
|
268
|
+
[
|
269
|
+
'<table>', s, '</table>'
|
270
|
+
],
|
271
|
+
css_classes=[
|
272
|
+
'complex-value', view.css_class_name(self.left), css_classes,
|
273
|
+
]
|
274
|
+
)
|
275
|
+
return root
|
276
|
+
|
277
|
+
def _html_tree_view_config(self) -> dict[str, Any]:
|
278
|
+
return tree_view.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() + [
|
290
|
+
"""
|
291
|
+
/* Diff styles. */
|
292
|
+
.has-diff.summary-title::after {
|
293
|
+
content: ' (diff)';
|
294
|
+
color: #aaa;
|
295
|
+
}
|
296
|
+
.has-diff.summary-title {
|
297
|
+
background-color: yellow;
|
298
|
+
}
|
299
|
+
.no-diff.summary-title::after {
|
300
|
+
content: ' (no diff)';
|
301
|
+
font-style: italic;
|
302
|
+
font-weight: normal;
|
303
|
+
color: #aaa;
|
304
|
+
}
|
305
|
+
.no-diff {
|
306
|
+
opacity: 0.6;
|
307
|
+
}
|
308
|
+
.no-diff.simple_value::after {
|
309
|
+
content: '(no diff)';
|
310
|
+
margin-left: 0.5em;
|
311
|
+
color: #aaa;
|
312
|
+
font-style: italic;
|
313
|
+
}
|
314
|
+
.diff-empty::before {
|
315
|
+
content: '(empty)';
|
316
|
+
font-style: italic;
|
317
|
+
margin-left: 0.5em;
|
318
|
+
color: #aaa;
|
319
|
+
}
|
320
|
+
.diff-left.summary-title::before, .diff-left.simple-value::before{
|
321
|
+
content: '🇱';
|
322
|
+
}
|
323
|
+
.diff-left {
|
324
|
+
background-color: #ffcccc;
|
325
|
+
}
|
326
|
+
.diff-right.summary-title::before, .diff-right.simple-value::before{
|
327
|
+
content: '🇷';
|
328
|
+
}
|
329
|
+
.diff-right {
|
330
|
+
background-color: #ccffcc;
|
331
|
+
}
|
332
|
+
"""
|
333
|
+
]
|
334
|
+
|
147
335
|
|
148
336
|
# NOTE(daiyip): we add the symbolic attribute to Diff after its declaration
|
149
337
|
# since we need to access Diff.MISSING as the default value for `left` and
|
@@ -164,7 +352,8 @@ def diff(
|
|
164
352
|
right: Any,
|
165
353
|
flatten: bool = False,
|
166
354
|
collapse: Union[bool, str, Callable[[Any, Any], bool]] = 'same_type',
|
167
|
-
mode: str = 'diff'
|
355
|
+
mode: str = 'diff',
|
356
|
+
) -> utils.Nestable[Diff]:
|
168
357
|
"""Inspect the symbolic diff between two objects.
|
169
358
|
|
170
359
|
For example::
|
@@ -290,7 +479,7 @@ def diff(
|
|
290
479
|
assert isinstance(container, base.Symbolic)
|
291
480
|
return container.sym_hasattr, container.sym_getattr, container.sym_items
|
292
481
|
|
293
|
-
def _diff(x, y) -> Tuple[
|
482
|
+
def _diff(x, y) -> Tuple[utils.Nestable[Diff], bool]:
|
294
483
|
if x is y or x == y:
|
295
484
|
return (Diff(x, y), False)
|
296
485
|
if not _should_collapse(x, y):
|
@@ -344,5 +533,5 @@ def diff(
|
|
344
533
|
if not has_diff and mode == 'diff':
|
345
534
|
diff_value = Diff()
|
346
535
|
if flatten:
|
347
|
-
diff_value =
|
536
|
+
diff_value = utils.flatten(diff_value)
|
348
537
|
return diff_value
|
@@ -13,6 +13,8 @@
|
|
13
13
|
# limitations under the License.
|
14
14
|
"""Tests for pyglove.diff."""
|
15
15
|
|
16
|
+
import inspect
|
17
|
+
from typing import Any
|
16
18
|
import unittest
|
17
19
|
|
18
20
|
from pyglove.core import typing as pg_typing
|
@@ -337,6 +339,230 @@ class DiffTest(unittest.TestCase):
|
|
337
339
|
'_type': Diff(B, C),
|
338
340
|
})
|
339
341
|
|
342
|
+
def test_to_html(self):
|
343
|
+
|
344
|
+
class Foo(Object):
|
345
|
+
x: Any
|
346
|
+
y: Any
|
347
|
+
|
348
|
+
class Bar(Foo):
|
349
|
+
pass
|
350
|
+
|
351
|
+
def assert_style(html, expected):
|
352
|
+
expected = inspect.cleandoc(expected).strip()
|
353
|
+
actual = html.style_section.strip()
|
354
|
+
if expected not in actual:
|
355
|
+
print(actual)
|
356
|
+
self.assertIn(expected, actual)
|
357
|
+
|
358
|
+
def assert_content(html, expected):
|
359
|
+
expected = inspect.cleandoc(expected).strip()
|
360
|
+
actual = html.content.strip()
|
361
|
+
if actual != expected:
|
362
|
+
print(actual)
|
363
|
+
self.assertEqual(actual.strip(), expected)
|
364
|
+
|
365
|
+
assert_style(
|
366
|
+
pg_diff(1, 1).to_html(),
|
367
|
+
"""
|
368
|
+
/* Diff styles. */
|
369
|
+
.has-diff.summary-title::after {
|
370
|
+
content: ' (diff)';
|
371
|
+
color: #aaa;
|
372
|
+
}
|
373
|
+
.has-diff.summary-title {
|
374
|
+
background-color: yellow;
|
375
|
+
}
|
376
|
+
.no-diff.summary-title::after {
|
377
|
+
content: ' (no diff)';
|
378
|
+
font-style: italic;
|
379
|
+
font-weight: normal;
|
380
|
+
color: #aaa;
|
381
|
+
}
|
382
|
+
.no-diff {
|
383
|
+
opacity: 0.6;
|
384
|
+
}
|
385
|
+
.no-diff.simple_value::after {
|
386
|
+
content: '(no diff)';
|
387
|
+
margin-left: 0.5em;
|
388
|
+
color: #aaa;
|
389
|
+
font-style: italic;
|
390
|
+
}
|
391
|
+
.diff-empty::before {
|
392
|
+
content: '(empty)';
|
393
|
+
font-style: italic;
|
394
|
+
margin-left: 0.5em;
|
395
|
+
color: #aaa;
|
396
|
+
}
|
397
|
+
.diff-left.summary-title::before, .diff-left.simple-value::before{
|
398
|
+
content: '🇱';
|
399
|
+
}
|
400
|
+
.diff-left {
|
401
|
+
background-color: #ffcccc;
|
402
|
+
}
|
403
|
+
.diff-right.summary-title::before, .diff-right.simple-value::before{
|
404
|
+
content: '🇷';
|
405
|
+
}
|
406
|
+
.diff-right {
|
407
|
+
background-color: #ccffcc;
|
408
|
+
}
|
409
|
+
"""
|
410
|
+
)
|
411
|
+
|
412
|
+
# No diff leaf value (diff only)
|
413
|
+
assert_content(
|
414
|
+
pg_diff(1, 1).to_html(),
|
415
|
+
"""
|
416
|
+
<details open class="pyglove diff no-diff"><summary><div class="summary-title no-diff">Diff</div><span class="tooltip no-diff">No diff</span></summary><span class="diff-empty"></span></details>
|
417
|
+
"""
|
418
|
+
)
|
419
|
+
|
420
|
+
# No diff leaf value (keep both)
|
421
|
+
assert_content(
|
422
|
+
pg_diff(1, 1, mode='both').to_html(),
|
423
|
+
"""
|
424
|
+
<span class="simple-value int no-diff">1</span>
|
425
|
+
"""
|
426
|
+
)
|
427
|
+
# No diff complex value (diff only)
|
428
|
+
assert_content(
|
429
|
+
pg_diff(
|
430
|
+
Foo(x=1, y=[Foo(x=2, y=3)]),
|
431
|
+
Foo(x=1, y=[Foo(x=2, y=3)])
|
432
|
+
).to_html(
|
433
|
+
enable_summary_tooltip=False,
|
434
|
+
enable_key_tooltip=False,
|
435
|
+
),
|
436
|
+
"""
|
437
|
+
<details open class="pyglove diff no-diff"><summary><div class="summary-title no-diff">Diff</div></summary><span class="diff-empty"></span></details>
|
438
|
+
"""
|
439
|
+
)
|
440
|
+
# No diff complex value.
|
441
|
+
assert_content(
|
442
|
+
pg_diff(
|
443
|
+
Foo(x=1, y=[Foo(x=2, y=3)]),
|
444
|
+
Foo(x=1, y=[Foo(x=2, y=3)]), mode='both'
|
445
|
+
).to_html(
|
446
|
+
enable_summary_tooltip=False,
|
447
|
+
enable_key_tooltip=False,
|
448
|
+
),
|
449
|
+
"""
|
450
|
+
<details open class="pyglove diff no-diff"><summary><div class="summary-title no-diff">Foo(...)</div></summary><div class="complex-value foo no-diff"><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 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><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">2</span></details><details open class="pyglove int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">3</span></details></div></details></td></tr></table></div></details></div></details>
|
451
|
+
"""
|
452
|
+
)
|
453
|
+
|
454
|
+
# Diff on simple value.
|
455
|
+
assert_content(
|
456
|
+
pg_diff(1, 2).to_html(),
|
457
|
+
"""
|
458
|
+
<div class="diff-value"><span class="simple-value int diff-left">1</span><span class="simple-value int diff-right">2</span></div>
|
459
|
+
"""
|
460
|
+
)
|
461
|
+
|
462
|
+
# Diff on list.
|
463
|
+
assert_content(
|
464
|
+
pg_diff([0, 1, 2], [0, 2], mode='both').to_html(
|
465
|
+
enable_summary_tooltip=False,
|
466
|
+
enable_key_tooltip=False,
|
467
|
+
),
|
468
|
+
"""
|
469
|
+
<details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">List</div></summary><div class="complex-value list-class"><table><tr><td><span class="object-key int no-diff">0</span><span class="tooltip">[0]</span></td><td><span class="simple-value int no-diff">0</span></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><div class="diff-value"><span class="simple-value int diff-left">1</span><span class="simple-value int diff-right">2</span></div></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><div class="diff-value"><span class="simple-value int diff-left">2</span></div></td></tr></table></div></details>
|
470
|
+
"""
|
471
|
+
)
|
472
|
+
|
473
|
+
# Diff on dict.
|
474
|
+
assert_content(
|
475
|
+
pg_diff(dict(x=1, y=2, z=3), dict(x=1, y=3, w=4), mode='both').to_html(
|
476
|
+
enable_summary_tooltip=False,
|
477
|
+
enable_key_tooltip=False,
|
478
|
+
),
|
479
|
+
"""
|
480
|
+
<details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">dict</div></summary><div class="complex-value dict-class"><table><tr><td><span class="object-key str no-diff">x</span><span class="tooltip">x</span></td><td><span class="simple-value int no-diff">1</span></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">y</span></td><td><div class="diff-value"><span class="simple-value int diff-left">2</span><span class="simple-value int diff-right">3</span></div></td></tr><tr><td><span class="object-key str">z</span><span class="tooltip">z</span></td><td><div class="diff-value"><span class="simple-value int diff-left">3</span></div></td></tr><tr><td><span class="object-key str">w</span><span class="tooltip">w</span></td><td><div class="diff-value"><span class="simple-value int diff-right">4</span></div></td></tr></table></div></details>
|
481
|
+
"""
|
482
|
+
)
|
483
|
+
|
484
|
+
# Diff on symbolic objects of the same type.
|
485
|
+
assert_content(
|
486
|
+
pg_diff(
|
487
|
+
Foo(x=2, y=Foo(x=3, y=3)),
|
488
|
+
Foo(x=1, y=Foo(x=2, y=3)),
|
489
|
+
mode='both',
|
490
|
+
).to_html(
|
491
|
+
enable_summary_tooltip=False,
|
492
|
+
enable_key_tooltip=False,
|
493
|
+
),
|
494
|
+
"""
|
495
|
+
<details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">Foo</div></summary><div class="complex-value foo-class"><table><tr><td><span class="object-key str">x</span><span class="tooltip">x</span></td><td><div class="diff-value"><span class="simple-value int diff-left">2</span><span class="simple-value int diff-right">1</span></div></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">y</span></td><td><details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">Foo</div></summary><div class="complex-value foo-class"><table><tr><td><span class="object-key str">x</span><span class="tooltip">y.x</span></td><td><div class="diff-value"><span class="simple-value int diff-left">3</span><span class="simple-value int diff-right">2</span></div></td></tr><tr><td><span class="object-key str no-diff">y</span><span class="tooltip">y.y</span></td><td><span class="simple-value int no-diff">3</span></td></tr></table></div></details></td></tr></table></div></details>
|
496
|
+
"""
|
497
|
+
)
|
498
|
+
|
499
|
+
# Diff on symbolic objects of different types.
|
500
|
+
assert_content(
|
501
|
+
pg_diff(
|
502
|
+
Foo(x=2, y=Foo(x=3, y=3)),
|
503
|
+
Bar(x=2, y=Foo(x=3, y=3)),
|
504
|
+
mode='both',
|
505
|
+
).to_html(
|
506
|
+
enable_summary_tooltip=False,
|
507
|
+
enable_key_tooltip=False,
|
508
|
+
),
|
509
|
+
"""
|
510
|
+
<div class="diff-value"><details open class="pyglove foo diff-left"><summary><div class="summary-title diff-left">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">2</span></details><details class="pyglove foo"><summary><div class="summary-name">y</div><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">3</span></details><details open class="pyglove int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">3</span></details></div></details></div></details><details open class="pyglove bar diff-right"><summary><div class="summary-title diff-right">Bar(...)</div></summary><div class="complex-value bar"><details open class="pyglove int"><summary><div class="summary-name">x</div><div class="summary-title">int</div></summary><span class="simple-value int">2</span></details><details class="pyglove foo"><summary><div class="summary-name">y</div><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">3</span></details><details open class="pyglove int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">3</span></details></div></details></div></details></div>
|
511
|
+
"""
|
512
|
+
)
|
513
|
+
|
514
|
+
# Different types but same values, with value collapsing.
|
515
|
+
assert_content(
|
516
|
+
pg_diff(
|
517
|
+
Foo(x=2, y=Foo(x=3, y=3)),
|
518
|
+
Bar(x=2, y=Bar(x=3, y=3)),
|
519
|
+
mode='both', collapse=True,
|
520
|
+
).to_html(
|
521
|
+
enable_summary_tooltip=False,
|
522
|
+
enable_key_tooltip=False,
|
523
|
+
),
|
524
|
+
"""
|
525
|
+
<details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">Foo | Bar</div></summary><div class="complex-value foo-class"><table><tr><td><span class="object-key str no-diff">x</span><span class="tooltip">x</span></td><td><span class="simple-value int no-diff">2</span></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">y</span></td><td><details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">Foo | Bar</div></summary><div class="complex-value foo-class"><table><tr><td><span class="object-key str no-diff">x</span><span class="tooltip">y.x</span></td><td><span class="simple-value int no-diff">3</span></td></tr><tr><td><span class="object-key str no-diff">y</span><span class="tooltip">y.y</span></td><td><span class="simple-value int no-diff">3</span></td></tr></table></div></details></td></tr></table></div></details>
|
526
|
+
"""
|
527
|
+
)
|
528
|
+
|
529
|
+
# Different types and different values, with value collapsing.
|
530
|
+
assert_content(
|
531
|
+
pg_diff(
|
532
|
+
Foo(x=2, y=Foo(x=3, y=3)),
|
533
|
+
Bar(x=3, y=Bar(x=2, y=3)),
|
534
|
+
mode='both', collapse=True,
|
535
|
+
).to_html(
|
536
|
+
enable_summary_tooltip=False,
|
537
|
+
enable_key_tooltip=False,
|
538
|
+
),
|
539
|
+
"""
|
540
|
+
<details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">Foo | Bar</div></summary><div class="complex-value foo-class"><table><tr><td><span class="object-key str">x</span><span class="tooltip">x</span></td><td><div class="diff-value"><span class="simple-value int diff-left">2</span><span class="simple-value int diff-right">3</span></div></td></tr><tr><td><span class="object-key str">y</span><span class="tooltip">y</span></td><td><details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">Foo | Bar</div></summary><div class="complex-value foo-class"><table><tr><td><span class="object-key str">x</span><span class="tooltip">y.x</span></td><td><div class="diff-value"><span class="simple-value int diff-left">3</span><span class="simple-value int diff-right">2</span></div></td></tr><tr><td><span class="object-key str no-diff">y</span><span class="tooltip">y.y</span></td><td><span class="simple-value int no-diff">3</span></td></tr></table></div></details></td></tr></table></div></details>
|
541
|
+
"""
|
542
|
+
)
|
543
|
+
|
544
|
+
# Diff with uncollapsing UI.
|
545
|
+
assert_content(
|
546
|
+
pg_diff(
|
547
|
+
[
|
548
|
+
Foo(1, 2), Foo(1, 2), None,
|
549
|
+
Foo(x=1, y=Foo(2, 3)), [dict(x=1, y=2)]
|
550
|
+
],
|
551
|
+
[
|
552
|
+
Foo(1, 2), Bar(1, 2), dict(x=1),
|
553
|
+
[1, 2], Foo(x=2, y=Foo(2, 4)), [dict(x=3)]
|
554
|
+
],
|
555
|
+
mode='both'
|
556
|
+
).to_html(
|
557
|
+
enable_summary_tooltip=False,
|
558
|
+
enable_key_tooltip=False,
|
559
|
+
uncollapse=['[0]', '[1].right', '[3].left.y'],
|
560
|
+
),
|
561
|
+
"""
|
562
|
+
<details open class="pyglove diff has-diff"><summary><div class="summary-title has-diff">List</div></summary><div class="complex-value list-class"><table><tr><td><span class="object-key int no-diff">0</span><span class="tooltip">[0]</span></td><td><details open class="pyglove diff no-diff"><summary><div class="summary-title no-diff">Foo(...)</div></summary><div class="complex-value foo no-diff"><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 int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">2</span></details></div></details></td></tr><tr><td><span class="object-key int">1</span><span class="tooltip">[1]</span></td><td><div class="diff-value"><details open class="pyglove foo diff-left"><summary><div class="summary-title diff-left">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 int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">2</span></details></div></details><details open class="pyglove bar diff-right"><summary><div class="summary-title diff-right">Bar(...)</div></summary><div class="complex-value bar"><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 int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">2</span></details></div></details></div></td></tr><tr><td><span class="object-key int">2</span><span class="tooltip">[2]</span></td><td><div class="diff-value"><span class="simple-value none-type diff-left">None</span><details open class="pyglove dict diff-right"><summary><div class="summary-title diff-right">Dict(...)</div></summary><div class="complex-value dict"><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></div></td></tr><tr><td><span class="object-key int">3</span><span class="tooltip">[3]</span></td><td><div class="diff-value"><details open class="pyglove foo diff-left"><summary><div class="summary-title diff-left">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 foo"><summary><div class="summary-name">y</div><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">2</span></details><details open class="pyglove int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">3</span></details></div></details></div></details><details open class="pyglove list diff-right"><summary><div class="summary-title diff-right">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><span class="simple-value int">2</span></td></tr></table></div></details></div></td></tr><tr><td><span class="object-key int">4</span><span class="tooltip">[4]</span></td><td><div class="diff-value"><details open class="pyglove list diff-left"><summary><div class="summary-title diff-left">List(...)</div></summary><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 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 int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">2</span></details></div></details></td></tr></table></div></details><details open class="pyglove foo diff-right"><summary><div class="summary-title diff-right">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">2</span></details><details class="pyglove foo"><summary><div class="summary-name">y</div><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">2</span></details><details open class="pyglove int"><summary><div class="summary-name">y</div><div class="summary-title">int</div></summary><span class="simple-value int">4</span></details></div></details></div></details></div></td></tr><tr><td><span class="object-key int">5</span><span class="tooltip">[5]</span></td><td><div class="diff-value"><details open class="pyglove list diff-right"><summary><div class="summary-title diff-right">List(...)</div></summary><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 open class="pyglove int"><summary><div class="summary-name">x</div><div class="summary-title">int</div></summary><span class="simple-value int">3</span></details></div></details></td></tr></table></div></details></div></td></tr></table></div></details>
|
563
|
+
"""
|
564
|
+
)
|
565
|
+
|
340
566
|
|
341
567
|
if __name__ == '__main__':
|
342
568
|
unittest.main()
|
pyglove/core/symbolic/flags.py
CHANGED