pyglove 0.4.5.dev202412100720__py3-none-any.whl → 0.4.5.dev202501250807__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.
Files changed (118) hide show
  1. pyglove/core/__init__.py +40 -21
  2. pyglove/core/coding/__init__.py +42 -0
  3. pyglove/core/coding/errors.py +111 -0
  4. pyglove/core/coding/errors_test.py +98 -0
  5. pyglove/core/coding/execution.py +312 -0
  6. pyglove/core/coding/execution_test.py +333 -0
  7. pyglove/core/{object_utils/codegen.py → coding/function_generation.py} +10 -4
  8. pyglove/core/{object_utils/codegen_test.py → coding/function_generation_test.py} +5 -7
  9. pyglove/core/coding/parsing.py +153 -0
  10. pyglove/core/coding/parsing_test.py +150 -0
  11. pyglove/core/coding/permissions.py +100 -0
  12. pyglove/core/coding/permissions_test.py +93 -0
  13. pyglove/core/geno/base.py +53 -38
  14. pyglove/core/geno/base_test.py +2 -4
  15. pyglove/core/geno/categorical.py +36 -27
  16. pyglove/core/geno/custom.py +18 -15
  17. pyglove/core/geno/numerical.py +19 -16
  18. pyglove/core/geno/space.py +3 -4
  19. pyglove/core/hyper/base.py +6 -6
  20. pyglove/core/hyper/categorical.py +91 -52
  21. pyglove/core/hyper/custom.py +7 -7
  22. pyglove/core/hyper/custom_test.py +9 -10
  23. pyglove/core/hyper/derived.py +30 -22
  24. pyglove/core/hyper/derived_test.py +3 -5
  25. pyglove/core/hyper/dynamic_evaluation.py +3 -4
  26. pyglove/core/hyper/evolvable.py +57 -46
  27. pyglove/core/hyper/numerical.py +48 -24
  28. pyglove/core/hyper/numerical_test.py +9 -9
  29. pyglove/core/hyper/object_template.py +58 -46
  30. pyglove/core/logging_test.py +0 -2
  31. pyglove/core/patching/object_factory.py +4 -4
  32. pyglove/core/patching/pattern_based.py +4 -4
  33. pyglove/core/patching/rule_based.py +4 -3
  34. pyglove/core/symbolic/__init__.py +4 -0
  35. pyglove/core/symbolic/base.py +200 -136
  36. pyglove/core/symbolic/base_test.py +17 -19
  37. pyglove/core/symbolic/boilerplate.py +4 -5
  38. pyglove/core/symbolic/class_wrapper.py +10 -14
  39. pyglove/core/symbolic/class_wrapper_test.py +2 -2
  40. pyglove/core/symbolic/compounding.py +2 -2
  41. pyglove/core/symbolic/compounding_test.py +2 -4
  42. pyglove/core/symbolic/contextual_object.py +288 -0
  43. pyglove/core/symbolic/contextual_object_test.py +327 -0
  44. pyglove/core/symbolic/dict.py +115 -87
  45. pyglove/core/symbolic/dict_test.py +188 -131
  46. pyglove/core/symbolic/diff.py +12 -12
  47. pyglove/core/symbolic/flags.py +1 -1
  48. pyglove/core/symbolic/functor.py +16 -15
  49. pyglove/core/symbolic/functor_test.py +2 -4
  50. pyglove/core/symbolic/inferred.py +2 -2
  51. pyglove/core/symbolic/list.py +70 -47
  52. pyglove/core/symbolic/list_test.py +117 -98
  53. pyglove/core/symbolic/object.py +59 -58
  54. pyglove/core/symbolic/object_test.py +143 -90
  55. pyglove/core/symbolic/origin.py +5 -7
  56. pyglove/core/symbolic/pure_symbolic.py +4 -3
  57. pyglove/core/symbolic/ref.py +33 -16
  58. pyglove/core/symbolic/ref_test.py +17 -0
  59. pyglove/core/tuning/local_backend.py +2 -2
  60. pyglove/core/tuning/protocols.py +3 -3
  61. pyglove/core/typing/annotation_conversion.py +8 -3
  62. pyglove/core/typing/annotation_conversion_test.py +8 -0
  63. pyglove/core/typing/callable_ext.py +11 -13
  64. pyglove/core/typing/callable_signature.py +22 -19
  65. pyglove/core/typing/callable_signature_test.py +3 -5
  66. pyglove/core/typing/class_schema.py +93 -54
  67. pyglove/core/typing/class_schema_test.py +4 -5
  68. pyglove/core/typing/custom_typing.py +5 -4
  69. pyglove/core/typing/key_specs.py +5 -7
  70. pyglove/core/typing/key_specs_test.py +4 -4
  71. pyglove/core/typing/type_conversion.py +4 -5
  72. pyglove/core/typing/type_conversion_test.py +12 -12
  73. pyglove/core/typing/typed_missing.py +6 -7
  74. pyglove/core/typing/typed_missing_test.py +7 -8
  75. pyglove/core/typing/value_specs.py +287 -144
  76. pyglove/core/typing/value_specs_test.py +148 -25
  77. pyglove/core/utils/__init__.py +172 -0
  78. pyglove/core/{object_utils → utils}/common_traits.py +2 -2
  79. pyglove/core/{object_utils → utils}/common_traits_test.py +1 -3
  80. pyglove/core/utils/contextual.py +147 -0
  81. pyglove/core/utils/contextual_test.py +88 -0
  82. pyglove/core/{object_utils → utils}/docstr_utils_test.py +1 -3
  83. pyglove/core/{object_utils → utils}/error_utils.py +3 -3
  84. pyglove/core/{object_utils → utils}/error_utils_test.py +1 -1
  85. pyglove/core/{object_utils → utils}/formatting.py +1 -1
  86. pyglove/core/{object_utils → utils}/formatting_test.py +1 -2
  87. pyglove/core/{object_utils → utils}/hierarchical.py +23 -25
  88. pyglove/core/{object_utils → utils}/hierarchical_test.py +3 -5
  89. pyglove/core/{object_utils → utils}/json_conversion.py +1 -1
  90. pyglove/core/{object_utils → utils}/json_conversion_test.py +1 -3
  91. pyglove/core/{object_utils → utils}/missing.py +2 -2
  92. pyglove/core/{object_utils → utils}/missing_test.py +2 -4
  93. pyglove/core/utils/text_color.py +128 -0
  94. pyglove/core/utils/text_color_test.py +94 -0
  95. pyglove/core/{object_utils → utils}/thread_local_test.py +1 -3
  96. pyglove/core/{object_utils → utils}/timing.py +21 -10
  97. pyglove/core/{object_utils → utils}/timing_test.py +14 -12
  98. pyglove/core/{object_utils → utils}/value_location.py +2 -2
  99. pyglove/core/{object_utils → utils}/value_location_test.py +2 -4
  100. pyglove/core/views/base.py +25 -29
  101. pyglove/core/views/html/base.py +14 -15
  102. pyglove/core/views/html/controls/base.py +5 -5
  103. pyglove/core/views/html/controls/label.py +1 -1
  104. pyglove/core/views/html/controls/label_test.py +6 -6
  105. pyglove/core/views/html/controls/progress_bar.py +3 -5
  106. pyglove/core/views/html/controls/progress_bar_test.py +2 -2
  107. pyglove/core/views/html/controls/tab.py +80 -2
  108. pyglove/core/views/html/controls/tab_test.py +34 -1
  109. pyglove/core/views/html/tree_view.py +39 -37
  110. {pyglove-0.4.5.dev202412100720.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/METADATA +17 -3
  111. pyglove-0.4.5.dev202501250807.dist-info/RECORD +218 -0
  112. {pyglove-0.4.5.dev202412100720.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/WHEEL +1 -1
  113. pyglove/core/object_utils/__init__.py +0 -164
  114. pyglove-0.4.5.dev202412100720.dist-info/RECORD +0 -203
  115. /pyglove/core/{object_utils → utils}/docstr_utils.py +0 -0
  116. /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
  117. {pyglove-0.4.5.dev202412100720.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/LICENSE +0 -0
  118. {pyglove-0.4.5.dev202412100720.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/top_level.txt +0 -0
@@ -22,14 +22,14 @@ import types
22
22
  import typing
23
23
  from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
24
24
 
25
- from pyglove.core import object_utils
26
25
  from pyglove.core import typing as pg_typing
26
+ from pyglove.core import utils
27
27
  from pyglove.core.symbolic import base
28
28
  from pyglove.core.symbolic import flags
29
29
  from pyglove.core.symbolic import object as pg_object
30
30
 
31
31
 
32
- class Functor(pg_object.Object, object_utils.Functor):
32
+ class Functor(pg_object.Object, utils.Functor):
33
33
  """Symbolic functions (Functors).
34
34
 
35
35
  A symbolic function is a symbolic class with a ``__call__`` method, whose
@@ -124,7 +124,7 @@ class Functor(pg_object.Object, object_utils.Functor):
124
124
  if not hasattr(cls, '__orig_init__'):
125
125
  setattr(cls, '__orig_init__', cls.__init__)
126
126
 
127
- @object_utils.explicit_method_override
127
+ @utils.explicit_method_override
128
128
  @functools.wraps(pseudo_init)
129
129
  def _init(self, *args, **kwargs):
130
130
  self.__class__.__orig_init__(self, *args, **kwargs)
@@ -148,14 +148,15 @@ class Functor(pg_object.Object, object_utils.Functor):
148
148
  return instance()
149
149
  return instance
150
150
 
151
- @object_utils.explicit_method_override
151
+ @utils.explicit_method_override
152
152
  def __init__(
153
153
  self,
154
154
  *args,
155
- root_path: Optional[object_utils.KeyPath] = None,
155
+ root_path: Optional[utils.KeyPath] = None,
156
156
  override_args: bool = False,
157
157
  ignore_extra_args: bool = False,
158
- **kwargs):
158
+ **kwargs,
159
+ ):
159
160
  """Constructor.
160
161
 
161
162
  Args:
@@ -182,8 +183,8 @@ class Functor(pg_object.Object, object_utils.Functor):
182
183
  varargs = list(args[len(signature.args) :])
183
184
  args = args[: len(signature.args)]
184
185
  else:
185
- arg_phrase = object_utils.auto_plural(len(signature.args), 'argument')
186
- was_phrase = object_utils.auto_plural(len(args), 'was', 'were')
186
+ arg_phrase = utils.auto_plural(len(signature.args), 'argument')
187
+ was_phrase = utils.auto_plural(len(args), 'was', 'were')
187
188
  raise TypeError(
188
189
  f'{signature.id}() takes {len(signature.args)} '
189
190
  f'positional {arg_phrase} but {len(args)} {was_phrase} given.'
@@ -257,8 +258,7 @@ class Functor(pg_object.Object, object_utils.Functor):
257
258
  # pylint: enable=protected-access
258
259
  return typing.cast(Functor, other)
259
260
 
260
- def _on_change(
261
- self, field_updates: Dict[object_utils.KeyPath, base.FieldUpdate]):
261
+ def _on_change(self, field_updates: Dict[utils.KeyPath, base.FieldUpdate]):
262
262
  """Custom handling field change to update bound args."""
263
263
  for relative_path, update in field_updates.items():
264
264
  assert relative_path
@@ -406,8 +406,8 @@ class Functor(pg_object.Object, object_utils.Functor):
406
406
  if ignore_extra_args:
407
407
  args = args[: len(signature.args)]
408
408
  else:
409
- arg_phrase = object_utils.auto_plural(len(signature.args), 'argument')
410
- was_phrase = object_utils.auto_plural(len(args), 'was', 'were')
409
+ arg_phrase = utils.auto_plural(len(signature.args), 'argument')
410
+ was_phrase = utils.auto_plural(len(args), 'was', 'were')
411
411
  raise TypeError(
412
412
  f'{signature.id}() takes {len(signature.args)} '
413
413
  f'positional {arg_phrase} but {len(args)} {was_phrase} given.'
@@ -483,9 +483,10 @@ class Functor(pg_object.Object, object_utils.Functor):
483
483
  missing_required_arg_names.append(arg.name)
484
484
 
485
485
  if missing_required_arg_names:
486
- arg_phrase = object_utils.auto_plural(
487
- len(missing_required_arg_names), 'argument')
488
- args_str = object_utils.comma_delimited_str(missing_required_arg_names)
486
+ arg_phrase = utils.auto_plural(
487
+ len(missing_required_arg_names), 'argument'
488
+ )
489
+ args_str = utils.comma_delimited_str(missing_required_arg_names)
489
490
  raise TypeError(
490
491
  f'{signature.id}() missing {len(missing_required_arg_names)} '
491
492
  f'required positional {arg_phrase}: {args_str}.'
@@ -11,15 +11,13 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- """Tests for pyglove.Functor."""
15
-
16
14
  import inspect
17
15
  import io
18
16
  import typing
19
17
  import unittest
20
18
 
21
- from pyglove.core import object_utils
22
19
  from pyglove.core import typing as pg_typing
20
+ from pyglove.core import utils
23
21
  from pyglove.core.symbolic import flags
24
22
  from pyglove.core.symbolic.base import from_json_str as pg_from_json_str
25
23
  from pyglove.core.symbolic.dict import Dict
@@ -31,7 +29,7 @@ from pyglove.core.symbolic.object import members as pg_members
31
29
  from pyglove.core.symbolic.object import Object
32
30
 
33
31
 
34
- MISSING_VALUE = object_utils.MISSING_VALUE
32
+ MISSING_VALUE = utils.MISSING_VALUE
35
33
 
36
34
 
37
35
  class FunctorTest(unittest.TestCase):
@@ -14,8 +14,8 @@
14
14
  """Common inferential values."""
15
15
 
16
16
  from typing import Any, Tuple
17
- from pyglove.core import object_utils
18
17
  from pyglove.core import typing as pg_typing
18
+ from pyglove.core import utils
19
19
  from pyglove.core.symbolic import base
20
20
  from pyglove.core.symbolic.object import Object
21
21
 
@@ -65,7 +65,7 @@ class ValueFromParentChain(InferredValue):
65
65
  if v == pg_typing.MISSING_VALUE:
66
66
  if parent is None:
67
67
  raise AttributeError(
68
- object_utils.message_on_path(
68
+ utils.message_on_path(
69
69
  (
70
70
  f'`{self.inference_key}` is not found under its context '
71
71
  '(along its symbolic parent chain).'
@@ -18,8 +18,8 @@ import math
18
18
  import numbers
19
19
  import typing
20
20
  from typing import Any, Callable, Dict, Iterable, Iterator, Optional, Tuple, Union
21
- from pyglove.core import object_utils
22
21
  from pyglove.core import typing as pg_typing
22
+ from pyglove.core import utils
23
23
  from pyglove.core.symbolic import base
24
24
  from pyglove.core.symbolic import flags
25
25
 
@@ -74,13 +74,16 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
74
74
  """
75
75
 
76
76
  @classmethod
77
- def partial(cls,
78
- items: Optional[Iterable[Any]] = None,
79
- *,
80
- value_spec: Optional[pg_typing.List] = None,
81
- onchange_callback: Optional[Callable[
82
- [Dict[object_utils.KeyPath, base.FieldUpdate]], None]] = None,
83
- **kwargs) -> 'List':
77
+ def partial(
78
+ cls,
79
+ items: Optional[Iterable[Any]] = None,
80
+ *,
81
+ value_spec: Optional[pg_typing.List] = None,
82
+ onchange_callback: Optional[
83
+ Callable[[Dict[utils.KeyPath, base.FieldUpdate]], None]
84
+ ] = None,
85
+ **kwargs,
86
+ ) -> 'List':
84
87
  """Class method that creates a partial List object."""
85
88
  return cls(items,
86
89
  value_spec=value_spec,
@@ -89,13 +92,15 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
89
92
  **kwargs)
90
93
 
91
94
  @classmethod
92
- def from_json(cls,
93
- json_value: Any,
94
- *,
95
- value_spec: Optional[pg_typing.List] = None,
96
- allow_partial: bool = False,
97
- root_path: Optional[object_utils.KeyPath] = None,
98
- **kwargs) -> 'List':
95
+ def from_json(
96
+ cls,
97
+ json_value: Any,
98
+ *,
99
+ value_spec: Optional[pg_typing.List] = None,
100
+ allow_partial: bool = False,
101
+ root_path: Optional[utils.KeyPath] = None,
102
+ **kwargs,
103
+ ) -> 'List':
99
104
  """Class method that load an symbolic List from a JSON value.
100
105
 
101
106
  Example::
@@ -136,10 +141,11 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
136
141
  [
137
142
  base.from_json(
138
143
  v,
139
- root_path=object_utils.KeyPath(i, root_path),
144
+ root_path=utils.KeyPath(i, root_path),
140
145
  allow_partial=allow_partial,
141
- **kwargs
142
- ) for i, v in enumerate(json_value)
146
+ **kwargs,
147
+ )
148
+ for i, v in enumerate(json_value)
143
149
  ],
144
150
  value_spec=value_spec,
145
151
  root_path=root_path,
@@ -151,12 +157,14 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
151
157
  items: Optional[Iterable[Any]] = None,
152
158
  *,
153
159
  value_spec: Optional[pg_typing.List] = None,
154
- onchange_callback: Optional[Callable[
155
- [Dict[object_utils.KeyPath, base.FieldUpdate]], None]] = None,
160
+ onchange_callback: Optional[
161
+ Callable[[Dict[utils.KeyPath, base.FieldUpdate]], None]
162
+ ] = None,
156
163
  allow_partial: bool = False,
157
164
  accessor_writable: bool = True,
158
165
  sealed: bool = False,
159
- root_path: Optional[object_utils.KeyPath] = None):
166
+ root_path: Optional[utils.KeyPath] = None,
167
+ ):
160
168
  """Constructor.
161
169
 
162
170
  Args:
@@ -337,8 +345,8 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
337
345
  return missing
338
346
 
339
347
  def _sym_rebind(
340
- self, path_value_pairs: typing.Dict[object_utils.KeyPath, Any]
341
- ) -> typing.List[base.FieldUpdate]:
348
+ self, path_value_pairs: typing.Dict[utils.KeyPath, Any]
349
+ ) -> typing.List[base.FieldUpdate]:
342
350
  """Subclass specific rebind implementation."""
343
351
  updates = []
344
352
 
@@ -378,14 +386,13 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
378
386
  return self
379
387
 
380
388
  def _update_children_paths(
381
- self,
382
- old_path: object_utils.KeyPath,
383
- new_path: object_utils.KeyPath) -> None:
389
+ self, old_path: utils.KeyPath, new_path: utils.KeyPath
390
+ ) -> None:
384
391
  """Update children paths according to root_path of current node."""
385
392
  del old_path
386
393
  for idx, item in self.sym_items():
387
394
  if isinstance(item, base.TopologyAware):
388
- item.sym_setpath(object_utils.KeyPath(idx, new_path))
395
+ item.sym_setpath(utils.KeyPath(idx, new_path))
389
396
 
390
397
  def _set_item_without_permission_check( # pytype: disable=signature-mismatch # overriding-parameter-type-checks
391
398
  self, key: int, value: Any) -> Optional[base.FieldUpdate]:
@@ -432,13 +439,15 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
432
439
  value = base.from_json(
433
440
  value,
434
441
  allow_partial=allow_partial,
435
- root_path=object_utils.KeyPath(idx, self.sym_path))
442
+ root_path=utils.KeyPath(idx, self.sym_path),
443
+ )
436
444
  if self._value_spec and flags.is_type_check_enabled():
437
445
  value = self._value_spec.element.apply(
438
446
  value,
439
447
  allow_partial=allow_partial,
440
448
  transform_fn=base.symbolic_transform_fn(self._allow_partial),
441
- root_path=object_utils.KeyPath(idx, self.sym_path))
449
+ root_path=utils.KeyPath(idx, self.sym_path),
450
+ )
442
451
  return self._relocate_if_symbolic(idx, value)
443
452
 
444
453
  @property
@@ -446,8 +455,7 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
446
455
  """Returns True if current list subscribes field updates."""
447
456
  return self._onchange_callback is not None
448
457
 
449
- def _on_change(self,
450
- field_updates: Dict[object_utils.KeyPath, base.FieldUpdate]):
458
+ def _on_change(self, field_updates: Dict[utils.KeyPath, base.FieldUpdate]):
451
459
  """On change event of List."""
452
460
  # Do nothing for now to handle changes of List.
453
461
 
@@ -463,7 +471,7 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
463
471
  # Update paths for children.
464
472
  for idx, item in self.sym_items():
465
473
  if isinstance(item, base.TopologyAware) and item.sym_path.key != idx:
466
- item.sym_setpath(object_utils.KeyPath(idx, self.sym_path))
474
+ item.sym_setpath(utils.KeyPath(idx, self.sym_path))
467
475
 
468
476
  if self._onchange_callback is not None:
469
477
  self._onchange_callback(field_updates)
@@ -723,11 +731,12 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
723
731
 
724
732
  def custom_apply(
725
733
  self,
726
- path: object_utils.KeyPath,
734
+ path: utils.KeyPath,
727
735
  value_spec: pg_typing.ValueSpec,
728
736
  allow_partial: bool,
729
737
  child_transform: Optional[
730
- Callable[[object_utils.KeyPath, pg_typing.Field, Any], Any]] = None
738
+ Callable[[utils.KeyPath, pg_typing.Field, Any], Any]
739
+ ] = None,
731
740
  ) -> Tuple[bool, 'List']:
732
741
  """Implement pg.typing.CustomTyping interface.
733
742
 
@@ -746,9 +755,12 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
746
755
  if self._value_spec:
747
756
  if value_spec and not value_spec.is_compatible(self._value_spec):
748
757
  raise ValueError(
749
- object_utils.message_on_path(
758
+ utils.message_on_path(
750
759
  f'List (spec={self._value_spec!r}) cannot be assigned to an '
751
- f'incompatible field (spec={value_spec!r}).', path))
760
+ f'incompatible field (spec={value_spec!r}).',
761
+ path,
762
+ )
763
+ )
752
764
  if self._allow_partial == allow_partial:
753
765
  proceed_with_standard_apply = False
754
766
  else:
@@ -758,9 +770,8 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
758
770
  return (proceed_with_standard_apply, self)
759
771
 
760
772
  def sym_jsonify(
761
- self,
762
- use_inferred: bool = False,
763
- **kwargs) -> object_utils.JSONValueType:
773
+ self, use_inferred: bool = False, **kwargs
774
+ ) -> utils.JSONValueType:
764
775
  """Converts current list to a list of plain Python objects."""
765
776
  def json_item(idx):
766
777
  v = self.sym_getattr(idx)
@@ -778,7 +789,7 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
778
789
  python_format: bool = False,
779
790
  use_inferred: bool = False,
780
791
  cls_name: Optional[str] = None,
781
- bracket_type: object_utils.BracketType = object_utils.BracketType.SQUARE,
792
+ bracket_type: utils.BracketType = utils.BracketType.SQUARE,
782
793
  **kwargs,
783
794
  ) -> str:
784
795
  """Formats this List."""
@@ -787,16 +798,22 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
787
798
  return ' ' * 2 * indent + text
788
799
 
789
800
  cls_name = cls_name or ''
790
- open_bracket, close_bracket = object_utils.bracket_chars(bracket_type)
801
+ open_bracket, close_bracket = utils.bracket_chars(bracket_type)
791
802
  s = [f'{cls_name}{open_bracket}']
792
803
  if compact:
793
804
  kv_strs = []
794
805
  for idx, elem in self.sym_items():
795
806
  if use_inferred and isinstance(elem, base.Inferential):
796
807
  elem = self.sym_inferred(idx, default=elem)
797
- v_str = object_utils.format(
798
- elem, compact, verbose, root_indent + 1,
799
- python_format=python_format, use_inferred=use_inferred, **kwargs)
808
+ v_str = utils.format(
809
+ elem,
810
+ compact,
811
+ verbose,
812
+ root_indent + 1,
813
+ python_format=python_format,
814
+ use_inferred=use_inferred,
815
+ **kwargs,
816
+ )
800
817
  if python_format:
801
818
  kv_strs.append(v_str)
802
819
  else:
@@ -812,9 +829,15 @@ class List(list, base.Symbolic, pg_typing.CustomTyping):
812
829
  s.append('\n')
813
830
  else:
814
831
  s.append(',\n')
815
- v_str = object_utils.format(
816
- elem, compact, verbose, root_indent + 1,
817
- python_format=python_format, use_inferred=use_inferred, **kwargs)
832
+ v_str = utils.format(
833
+ elem,
834
+ compact,
835
+ verbose,
836
+ root_indent + 1,
837
+ python_format=python_format,
838
+ use_inferred=use_inferred,
839
+ **kwargs,
840
+ )
818
841
  if python_format:
819
842
  s.append(_indent(v_str, root_indent + 1))
820
843
  else:
@@ -20,8 +20,8 @@ import pickle
20
20
  from typing import Any
21
21
  import unittest
22
22
 
23
- from pyglove.core import object_utils
24
23
  from pyglove.core import typing as pg_typing
24
+ from pyglove.core import utils
25
25
  from pyglove.core.symbolic import base
26
26
  from pyglove.core.symbolic import flags
27
27
  from pyglove.core.symbolic import inferred
@@ -34,7 +34,7 @@ from pyglove.core.symbolic.pure_symbolic import NonDeterministic
34
34
  from pyglove.core.symbolic.pure_symbolic import PureSymbolic
35
35
 
36
36
 
37
- MISSING_VALUE = object_utils.MISSING_VALUE
37
+ MISSING_VALUE = utils.MISSING_VALUE
38
38
 
39
39
 
40
40
  class ListTest(unittest.TestCase):
@@ -685,7 +685,7 @@ class ListTest(unittest.TestCase):
685
685
  self.assertTrue(sl.sym_has('[0].x'))
686
686
  self.assertTrue(sl.sym_has('[0].x[0]'))
687
687
  self.assertTrue(sl.sym_has('[0].x[0].y'))
688
- self.assertTrue(sl.sym_has(object_utils.KeyPath.parse('[0].x[0].y')))
688
+ self.assertTrue(sl.sym_has(utils.KeyPath.parse('[0].x[0].y')))
689
689
 
690
690
  def test_sym_get(self):
691
691
  sl = List([dict(x=[dict(y=1)])])
@@ -1100,7 +1100,7 @@ class ListTest(unittest.TestCase):
1100
1100
  self.assertEqual(sl[1].sym_path, '[1]')
1101
1101
  self.assertEqual(sl[1][0].b.sym_path, '[1][0].b')
1102
1102
 
1103
- sl.sym_setpath(object_utils.KeyPath('a'))
1103
+ sl.sym_setpath(utils.KeyPath('a'))
1104
1104
  self.assertEqual(sl.sym_path, 'a')
1105
1105
  self.assertEqual(sl[0].sym_path, 'a[0]')
1106
1106
  self.assertEqual(sl[0].a.sym_path, 'a[0].a')
@@ -1412,96 +1412,112 @@ class RebindTest(unittest.TestCase):
1412
1412
  '[3]': 'foo', # Unchanged.
1413
1413
  '[4]': Insertion('bar')
1414
1414
  })
1415
- self.assertEqual(updates, [
1416
- { # Notification to `sl[2][0]`.
1417
- 'p': base.FieldUpdate(
1418
- object_utils.KeyPath.parse('[2][0].p'),
1419
- target=sl[2][0],
1420
- field=None,
1421
- old_value=1,
1422
- new_value=MISSING_VALUE),
1423
- 'q': base.FieldUpdate(
1424
- object_utils.KeyPath.parse('[2][0].q'),
1425
- target=sl[2][0],
1426
- field=None,
1427
- old_value=MISSING_VALUE,
1428
- new_value=2),
1429
- },
1430
- { # Notification to `sl.c`.
1431
- '[0].p': base.FieldUpdate(
1432
- object_utils.KeyPath.parse('[2][0].p'),
1433
- target=sl[2][0],
1434
- field=None,
1435
- old_value=1,
1436
- new_value=MISSING_VALUE),
1437
- '[0].q': base.FieldUpdate(
1438
- object_utils.KeyPath.parse('[2][0].q'),
1439
- target=sl[2][0],
1440
- field=None,
1441
- old_value=MISSING_VALUE,
1442
- new_value=2),
1443
- },
1444
- { # Notification to `sl[1].y`.
1445
- 'z': base.FieldUpdate(
1446
- object_utils.KeyPath.parse('[1].y.z'),
1447
- target=sl[1].y,
1448
- field=None,
1449
- old_value=MISSING_VALUE,
1450
- new_value=1),
1451
- },
1452
- { # Notification to `sl.b`.
1453
- 'x': base.FieldUpdate(
1454
- object_utils.KeyPath.parse('[1].x'),
1455
- target=sl[1],
1456
- field=None,
1457
- old_value=1,
1458
- new_value=2),
1459
- 'y.z': base.FieldUpdate(
1460
- object_utils.KeyPath.parse('[1].y.z'),
1461
- target=sl[1].y,
1462
- field=None,
1463
- old_value=MISSING_VALUE,
1464
- new_value=1),
1465
- },
1466
- { # Notification to `sl`.
1467
- '[0]': base.FieldUpdate(
1468
- object_utils.KeyPath.parse('[0]'),
1469
- target=sl,
1470
- field=None,
1471
- old_value=1,
1472
- new_value=2),
1473
- '[1].x': base.FieldUpdate(
1474
- object_utils.KeyPath.parse('[1].x'),
1475
- target=sl[1],
1476
- field=None,
1477
- old_value=1,
1478
- new_value=2),
1479
- '[1].y.z': base.FieldUpdate(
1480
- object_utils.KeyPath.parse('[1].y.z'),
1481
- target=sl[1].y,
1482
- field=None,
1483
- old_value=MISSING_VALUE,
1484
- new_value=1),
1485
- '[2][0].p': base.FieldUpdate(
1486
- object_utils.KeyPath.parse('[2][0].p'),
1487
- target=sl[2][0],
1488
- field=None,
1489
- old_value=1,
1490
- new_value=MISSING_VALUE),
1491
- '[2][0].q': base.FieldUpdate(
1492
- object_utils.KeyPath.parse('[2][0].q'),
1493
- target=sl[2][0],
1494
- field=None,
1495
- old_value=MISSING_VALUE,
1496
- new_value=2),
1497
- '[4]': base.FieldUpdate(
1498
- object_utils.KeyPath.parse('[4]'),
1499
- target=sl,
1500
- field=None,
1501
- old_value=MISSING_VALUE,
1502
- new_value='bar')
1503
- }
1504
- ])
1415
+ self.assertEqual(
1416
+ updates,
1417
+ [
1418
+ { # Notification to `sl[2][0]`.
1419
+ 'p': base.FieldUpdate(
1420
+ utils.KeyPath.parse('[2][0].p'),
1421
+ target=sl[2][0],
1422
+ field=None,
1423
+ old_value=1,
1424
+ new_value=MISSING_VALUE,
1425
+ ),
1426
+ 'q': base.FieldUpdate(
1427
+ utils.KeyPath.parse('[2][0].q'),
1428
+ target=sl[2][0],
1429
+ field=None,
1430
+ old_value=MISSING_VALUE,
1431
+ new_value=2,
1432
+ ),
1433
+ },
1434
+ { # Notification to `sl.c`.
1435
+ '[0].p': base.FieldUpdate(
1436
+ utils.KeyPath.parse('[2][0].p'),
1437
+ target=sl[2][0],
1438
+ field=None,
1439
+ old_value=1,
1440
+ new_value=MISSING_VALUE,
1441
+ ),
1442
+ '[0].q': base.FieldUpdate(
1443
+ utils.KeyPath.parse('[2][0].q'),
1444
+ target=sl[2][0],
1445
+ field=None,
1446
+ old_value=MISSING_VALUE,
1447
+ new_value=2,
1448
+ ),
1449
+ },
1450
+ { # Notification to `sl[1].y`.
1451
+ 'z': base.FieldUpdate(
1452
+ utils.KeyPath.parse('[1].y.z'),
1453
+ target=sl[1].y,
1454
+ field=None,
1455
+ old_value=MISSING_VALUE,
1456
+ new_value=1,
1457
+ ),
1458
+ },
1459
+ { # Notification to `sl.b`.
1460
+ 'x': base.FieldUpdate(
1461
+ utils.KeyPath.parse('[1].x'),
1462
+ target=sl[1],
1463
+ field=None,
1464
+ old_value=1,
1465
+ new_value=2,
1466
+ ),
1467
+ 'y.z': base.FieldUpdate(
1468
+ utils.KeyPath.parse('[1].y.z'),
1469
+ target=sl[1].y,
1470
+ field=None,
1471
+ old_value=MISSING_VALUE,
1472
+ new_value=1,
1473
+ ),
1474
+ },
1475
+ { # Notification to `sl`.
1476
+ '[0]': base.FieldUpdate(
1477
+ utils.KeyPath.parse('[0]'),
1478
+ target=sl,
1479
+ field=None,
1480
+ old_value=1,
1481
+ new_value=2,
1482
+ ),
1483
+ '[1].x': base.FieldUpdate(
1484
+ utils.KeyPath.parse('[1].x'),
1485
+ target=sl[1],
1486
+ field=None,
1487
+ old_value=1,
1488
+ new_value=2,
1489
+ ),
1490
+ '[1].y.z': base.FieldUpdate(
1491
+ utils.KeyPath.parse('[1].y.z'),
1492
+ target=sl[1].y,
1493
+ field=None,
1494
+ old_value=MISSING_VALUE,
1495
+ new_value=1,
1496
+ ),
1497
+ '[2][0].p': base.FieldUpdate(
1498
+ utils.KeyPath.parse('[2][0].p'),
1499
+ target=sl[2][0],
1500
+ field=None,
1501
+ old_value=1,
1502
+ new_value=MISSING_VALUE,
1503
+ ),
1504
+ '[2][0].q': base.FieldUpdate(
1505
+ utils.KeyPath.parse('[2][0].q'),
1506
+ target=sl[2][0],
1507
+ field=None,
1508
+ old_value=MISSING_VALUE,
1509
+ new_value=2,
1510
+ ),
1511
+ '[4]': base.FieldUpdate(
1512
+ utils.KeyPath.parse('[4]'),
1513
+ target=sl,
1514
+ field=None,
1515
+ old_value=MISSING_VALUE,
1516
+ new_value='bar',
1517
+ ),
1518
+ },
1519
+ ],
1520
+ )
1505
1521
 
1506
1522
  def test_rebind_with_fn(self):
1507
1523
  sl = List([0, dict(x=1, y='foo', z=[2, 3, 4])])
@@ -1716,7 +1732,7 @@ class FormatTest(unittest.TestCase):
1716
1732
 
1717
1733
  def test_compact_python_format(self):
1718
1734
  self.assertEqual(
1719
- object_utils.format(
1735
+ utils.format(
1720
1736
  self._list, compact=True, python_format=True, markdown=True
1721
1737
  ),
1722
1738
  "`[{'a1': 1, 'a2': {'b1': {'c1': [{'d1': MISSING_VALUE, "
@@ -1726,9 +1742,12 @@ class FormatTest(unittest.TestCase):
1726
1742
 
1727
1743
  def test_noncompact_python_format(self):
1728
1744
  self.assertEqual(
1729
- object_utils.format(
1730
- self._list, compact=False, verbose=False,
1731
- python_format=True, markdown=True
1745
+ utils.format(
1746
+ self._list,
1747
+ compact=False,
1748
+ verbose=False,
1749
+ python_format=True,
1750
+ markdown=True,
1732
1751
  ),
1733
1752
  inspect.cleandoc("""
1734
1753
  ```