pyglove 0.4.5.dev202410170809__py3-none-any.whl → 0.4.5.dev202410190807__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 CHANGED
@@ -302,6 +302,7 @@ timeit = object_utils.timeit
302
302
 
303
303
  from pyglove.core import views
304
304
  view = views.view
305
+ view_options = views.view_options
305
306
  View = views.View
306
307
  Html = views.Html
307
308
  to_html = views.to_html
@@ -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
- hide_frozen: bool = html.HtmlView.PresetArgValue(True),
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
- hide_frozen=hide_frozen, hide_default_values=hide_default_values,
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="summary_title">Foo(...)</div></summary><div class="complex_value foo"><table><tr><td><span class="object_key str">x</span></td><td><div><span class="simple_value int">1</span></div></td></tr><tr><td><span class="object_key str">y</span></td><td><div><span class="simple_value str">&#x27;foo&#x27;</span></div></td></tr></table></div></details>
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">&#x27;foo&#x27;</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
- hide_frozen=True,
125
- hide_default_values=True
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="summary_title">Foo(...)</div></summary><div class="complex_value foo"><table><tr><td><span class="object_key str">x</span></td><td><div><span class="simple_value int">1</span></div></td></tr></table></div></details>
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
- use_inferred=False
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="summary_title">Dict(...)</div></summary><div class="complex_value dict"><table><tr><td><span class="object_key str">y</span></td><td><div><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></div></td></tr></table></div></details>
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
- use_inferred=True
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="summary_title">Dict(...)</div></summary><div class="complex_value dict"><table><tr><td><span class="object_key str">y</span></td><td><div><span class="simple_value int">2</span></div></td></tr></table></div></details>
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__':
@@ -13,7 +13,7 @@
13
13
  # limitations under the License.
14
14
  """Symbolic differences."""
15
15
 
16
- from typing import Any, Callable, List, Optional, Tuple, Union
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 = html.HtmlView.PresetArgValue(40),
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
- css_class=['diff_empty']
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 = html.Html.element(
212
- 'div',
213
- [
214
- view.content(
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
- # Render left value.
225
- lambda: html.Html.element( # pylint: disable=g-long-ternary
226
- 'div',
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
- # Render right value.
235
- lambda: html.Html.element( # pylint: disable=g-long-ternary
236
- 'div',
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
- css_class=['diff_value']
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
- k, parent=v, root_path=child_path,
266
- css_class=None if bool(v) else ['no_diff_key'],
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(v, root_path=child_path, **kwargs),
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
- css_class=[
282
- 'complex_value', view.css_class_name(self.left)
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 _html_style(self) -> List[str]:
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 .summary_title::after {
292
+ .has-diff.summary-title::after {
292
293
  content: ' (diff)';
293
294
  color: #aaa;
294
295
  }
295
- .diff .summary_title {
296
+ .has-diff.summary-title {
296
297
  background-color: yellow;
297
298
  }
298
- .diff table td {
299
- padding: 4px;
300
- }
301
- .diff_value {
302
- display: inline-block;
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
- .no_diff_key {
306
- opacity: 0.4;
305
+ .no-diff {
306
+ opacity: 0.6;
307
307
  }
308
- .diff_left.diff_right::after {
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
- .diff_empty::before {
315
- content: '(empty)';
316
- font-style: italic;
317
- margin-left: 0.5em;
318
- color: #aaa;
314
+ .diff-empty::before {
315
+ content: '(empty)';
316
+ font-style: italic;
317
+ margin-left: 0.5em;
318
+ color: #aaa;
319
319
  }
320
- .diff_value .diff_left::before {
320
+ .diff-left.summary-title::before, .diff-left.simple-value::before{
321
321
  content: '🇱';
322
322
  }
323
- .diff_value .diff_left > .simple_value {
323
+ .diff-left {
324
324
  background-color: #ffcccc;
325
325
  }
326
- .diff_value .diff_left > details {
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
- .diff_value .diff_right > .simple_value {
333
- background-color: #ccffcc;
334
- }
335
- .diff_value .diff_right > details {
329
+ .diff-right {
336
330
  background-color: #ccffcc;
337
331
  }
338
332
  """