pyglove 0.4.5.dev202501050808__py3-none-any.whl → 0.4.5.dev202501060809__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 (91) hide show
  1. pyglove/core/__init__.py +24 -21
  2. pyglove/core/geno/base.py +53 -38
  3. pyglove/core/geno/base_test.py +2 -4
  4. pyglove/core/geno/categorical.py +36 -27
  5. pyglove/core/geno/custom.py +18 -15
  6. pyglove/core/geno/numerical.py +19 -16
  7. pyglove/core/geno/space.py +3 -4
  8. pyglove/core/hyper/base.py +6 -6
  9. pyglove/core/hyper/categorical.py +91 -52
  10. pyglove/core/hyper/custom.py +7 -7
  11. pyglove/core/hyper/custom_test.py +9 -10
  12. pyglove/core/hyper/derived.py +30 -22
  13. pyglove/core/hyper/derived_test.py +2 -4
  14. pyglove/core/hyper/dynamic_evaluation.py +3 -4
  15. pyglove/core/hyper/evolvable.py +57 -46
  16. pyglove/core/hyper/numerical.py +48 -24
  17. pyglove/core/hyper/numerical_test.py +9 -9
  18. pyglove/core/hyper/object_template.py +58 -46
  19. pyglove/core/logging_test.py +0 -2
  20. pyglove/core/patching/object_factory.py +4 -4
  21. pyglove/core/patching/pattern_based.py +4 -4
  22. pyglove/core/patching/rule_based.py +4 -3
  23. pyglove/core/symbolic/base.py +167 -131
  24. pyglove/core/symbolic/base_test.py +17 -19
  25. pyglove/core/symbolic/boilerplate.py +4 -5
  26. pyglove/core/symbolic/class_wrapper.py +9 -9
  27. pyglove/core/symbolic/compounding.py +2 -2
  28. pyglove/core/symbolic/compounding_test.py +2 -4
  29. pyglove/core/symbolic/dict.py +70 -54
  30. pyglove/core/symbolic/dict_test.py +117 -100
  31. pyglove/core/symbolic/diff.py +12 -12
  32. pyglove/core/symbolic/flags.py +1 -1
  33. pyglove/core/symbolic/functor.py +16 -15
  34. pyglove/core/symbolic/functor_test.py +2 -4
  35. pyglove/core/symbolic/inferred.py +2 -2
  36. pyglove/core/symbolic/list.py +70 -47
  37. pyglove/core/symbolic/list_test.py +117 -98
  38. pyglove/core/symbolic/object.py +42 -40
  39. pyglove/core/symbolic/object_test.py +95 -88
  40. pyglove/core/symbolic/origin.py +5 -7
  41. pyglove/core/symbolic/pure_symbolic.py +4 -3
  42. pyglove/core/symbolic/ref.py +12 -8
  43. pyglove/core/tuning/local_backend.py +2 -2
  44. pyglove/core/tuning/protocols.py +3 -3
  45. pyglove/core/typing/annotation_conversion.py +3 -3
  46. pyglove/core/typing/callable_ext.py +11 -13
  47. pyglove/core/typing/callable_signature.py +19 -18
  48. pyglove/core/typing/callable_signature_test.py +3 -5
  49. pyglove/core/typing/class_schema.py +48 -44
  50. pyglove/core/typing/class_schema_test.py +3 -5
  51. pyglove/core/typing/custom_typing.py +5 -4
  52. pyglove/core/typing/key_specs.py +5 -7
  53. pyglove/core/typing/key_specs_test.py +4 -4
  54. pyglove/core/typing/type_conversion.py +4 -5
  55. pyglove/core/typing/type_conversion_test.py +12 -12
  56. pyglove/core/typing/typed_missing.py +6 -7
  57. pyglove/core/typing/typed_missing_test.py +7 -8
  58. pyglove/core/typing/value_specs.py +210 -141
  59. pyglove/core/typing/value_specs_test.py +12 -13
  60. pyglove/core/utils/__init__.py +159 -0
  61. pyglove/core/{object_utils → utils}/common_traits_test.py +1 -3
  62. pyglove/core/{object_utils → utils}/docstr_utils_test.py +1 -3
  63. pyglove/core/{object_utils → utils}/error_utils.py +3 -3
  64. pyglove/core/{object_utils → utils}/error_utils_test.py +1 -1
  65. pyglove/core/{object_utils → utils}/formatting.py +1 -1
  66. pyglove/core/{object_utils → utils}/formatting_test.py +1 -2
  67. pyglove/core/{object_utils → utils}/hierarchical.py +23 -25
  68. pyglove/core/{object_utils → utils}/hierarchical_test.py +3 -5
  69. pyglove/core/{object_utils → utils}/json_conversion_test.py +1 -3
  70. pyglove/core/{object_utils → utils}/missing.py +2 -2
  71. pyglove/core/{object_utils → utils}/missing_test.py +2 -4
  72. pyglove/core/{object_utils → utils}/thread_local_test.py +1 -3
  73. pyglove/core/{object_utils → utils}/timing.py +3 -3
  74. pyglove/core/{object_utils → utils}/timing_test.py +2 -3
  75. pyglove/core/{object_utils → utils}/value_location.py +2 -2
  76. pyglove/core/{object_utils → utils}/value_location_test.py +2 -4
  77. pyglove/core/views/base.py +25 -29
  78. pyglove/core/views/html/base.py +14 -15
  79. pyglove/core/views/html/controls/base.py +5 -5
  80. pyglove/core/views/html/controls/progress_bar.py +3 -5
  81. pyglove/core/views/html/tree_view.py +37 -35
  82. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/METADATA +1 -1
  83. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/RECORD +90 -90
  84. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/WHEEL +1 -1
  85. pyglove/core/object_utils/__init__.py +0 -161
  86. /pyglove/core/{object_utils → utils}/common_traits.py +0 -0
  87. /pyglove/core/{object_utils → utils}/docstr_utils.py +0 -0
  88. /pyglove/core/{object_utils → utils}/json_conversion.py +0 -0
  89. /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
  90. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/LICENSE +0 -0
  91. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/top_level.txt +0 -0
@@ -20,8 +20,8 @@ import typing
20
20
  from typing import Any, Dict, Iterator, List, Optional, Sequence, Union
21
21
 
22
22
  from pyglove.core import coding
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 dict as pg_dict
27
27
  from pyglove.core.symbolic import flags
@@ -116,7 +116,7 @@ class ObjectMeta(abc.ABCMeta):
116
116
 
117
117
  # Register class with 'type' property.
118
118
  for key in serialization_keys:
119
- object_utils.JSONConvertible.register(
119
+ utils.JSONConvertible.register(
120
120
  key, cls, flags.is_repeated_class_registration_allowed()
121
121
  )
122
122
 
@@ -309,7 +309,7 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
309
309
  Args:
310
310
  user_cls: The source class that calls this class method.
311
311
  """
312
- object_utils.ensure_explicit_method_override(
312
+ utils.ensure_explicit_method_override(
313
313
  cls.__init__,
314
314
  (
315
315
  '`pg.Object.__init__` is a PyGlove managed method. For setting up '
@@ -317,7 +317,8 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
317
317
  '`_on_init()`. If you do have a need to override `__init__` and '
318
318
  'know the implications, please decorate your overridden method '
319
319
  'with `@pg.explicit_method_override`.'
320
- ))
320
+ ),
321
+ )
321
322
 
322
323
  # Set `__serialization_key__` before JSONConvertible.__init_subclass__
323
324
  # is called.
@@ -363,11 +364,11 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
363
364
  """Normalizes the schema before applying it."""
364
365
 
365
366
  schema.set_name(cls.__type_name__)
366
- docstr = object_utils.docstr(cls)
367
+ docstr = utils.docstr(cls)
367
368
  if docstr:
368
369
  schema.set_description(docstr.description)
369
370
 
370
- def _formalize_field(path: object_utils.KeyPath, node: Any) -> bool:
371
+ def _formalize_field(path: utils.KeyPath, node: Any) -> bool:
371
372
  """Formalize field."""
372
373
  if isinstance(node, pg_typing.Field):
373
374
  field = node
@@ -385,27 +386,29 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
385
386
  if isinstance(field.value, pg_typing.Dict):
386
387
  if field.value.schema is not None:
387
388
  field.value.schema.set_name(f'{schema.name}.{path.path}')
388
- object_utils.traverse(field.value.schema.fields, _formalize_field,
389
- None, path)
389
+ utils.traverse(
390
+ field.value.schema.fields, _formalize_field, None, path
391
+ )
390
392
  elif isinstance(field.value, pg_typing.List):
391
- _formalize_field(object_utils.KeyPath(0, path), field.value.element)
393
+ _formalize_field(utils.KeyPath(0, path), field.value.element)
392
394
  elif isinstance(field.value, pg_typing.Tuple):
393
395
  for i, elem in enumerate(field.value.elements):
394
- _formalize_field(object_utils.KeyPath(i, path), elem)
396
+ _formalize_field(utils.KeyPath(i, path), elem)
395
397
  elif isinstance(field.value, pg_typing.Union):
396
398
  for i, c in enumerate(field.value.candidates):
397
399
  _formalize_field(
398
- object_utils.KeyPath(i, path),
399
- pg_typing.Field(field.key, c, 'Union sub-type.'))
400
+ utils.KeyPath(i, path),
401
+ pg_typing.Field(field.key, c, 'Union sub-type.'),
402
+ )
400
403
  return True
401
404
 
402
- object_utils.traverse(schema.fields, _formalize_field)
405
+ utils.traverse(schema.fields, _formalize_field)
403
406
  return schema
404
407
 
405
408
  @classmethod
406
409
  def _finalize_init_arg_list(cls) -> List[str]:
407
410
  """Finalizes init_arg_list based on schema."""
408
- # Update `init_arg_list`` based on the updated schema.
411
+ # Update `init_arg_list`` based on the updated schema.
409
412
  init_arg_list = cls.__schema__.metadata.get('init_arg_list', None)
410
413
  if init_arg_list is None:
411
414
  # Inherit from the first non-empty base if they have the same signature.
@@ -476,7 +479,7 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
476
479
  # Create a new `__init__` that passes through all the arguments to
477
480
  # in `pg.Object.__init__`. This is needed for each class to use different
478
481
  # signature.
479
- @object_utils.explicit_method_override
482
+ @utils.explicit_method_override
480
483
  @functools.wraps(pseudo_init)
481
484
  def _init(self, *args, **kwargs):
482
485
  # We pass through the arguments to `Object.__init__` instead of
@@ -539,8 +542,8 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
539
542
  json_value: Any,
540
543
  *,
541
544
  allow_partial: bool = False,
542
- root_path: Optional[object_utils.KeyPath] = None,
543
- **kwargs
545
+ root_path: Optional[utils.KeyPath] = None,
546
+ **kwargs,
544
547
  ) -> 'Object':
545
548
  """Class method that load an symbolic Object from a JSON value.
546
549
 
@@ -588,15 +591,16 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
588
591
  for k, v in json_value.items()
589
592
  })
590
593
 
591
- @object_utils.explicit_method_override
594
+ @utils.explicit_method_override
592
595
  def __init__(
593
596
  self,
594
597
  *args,
595
598
  allow_partial: bool = False,
596
599
  sealed: Optional[bool] = None,
597
- root_path: Optional[object_utils.KeyPath] = None,
600
+ root_path: Optional[utils.KeyPath] = None,
598
601
  explicit_init: bool = False,
599
- **kwargs):
602
+ **kwargs,
603
+ ):
600
604
  """Create an Object instance.
601
605
 
602
606
  Args:
@@ -638,8 +642,8 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
638
642
  # Fill field_args and init_args from **kwargs.
639
643
  _, unmatched_keys = self.__class__.__schema__.resolve(list(kwargs.keys()))
640
644
  if unmatched_keys:
641
- arg_phrase = object_utils.auto_plural(len(unmatched_keys), 'argument')
642
- keys_str = object_utils.comma_delimited_str(unmatched_keys)
645
+ arg_phrase = utils.auto_plural(len(unmatched_keys), 'argument')
646
+ keys_str = utils.comma_delimited_str(unmatched_keys)
643
647
  raise TypeError(
644
648
  f'{self.__class__.__name__}.__init__() got unexpected '
645
649
  f'keyword {arg_phrase}: {keys_str}')
@@ -659,8 +663,8 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
659
663
  field_args[vararg_name] = list(args[num_named_args:])
660
664
  args = args[:num_named_args]
661
665
  elif len(args) > len(init_arg_names):
662
- arg_phrase = object_utils.auto_plural(len(init_arg_names), 'argument')
663
- was_phrase = object_utils.auto_plural(len(args), 'was', 'were')
666
+ arg_phrase = utils.auto_plural(len(init_arg_names), 'argument')
667
+ was_phrase = utils.auto_plural(len(args), 'was', 'were')
664
668
  raise TypeError(
665
669
  f'{self.__class__.__name__}.__init__() takes '
666
670
  f'{len(init_arg_names)} positional {arg_phrase} but {len(args)} '
@@ -672,7 +676,7 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
672
676
 
673
677
  for k, v in kwargs.items():
674
678
  if k in field_args:
675
- values_str = object_utils.comma_delimited_str([field_args[k], v])
679
+ values_str = utils.comma_delimited_str([field_args[k], v])
676
680
  raise TypeError(
677
681
  f'{self.__class__.__name__}.__init__() got multiple values for '
678
682
  f'argument \'{k}\': {values_str}.')
@@ -687,8 +691,8 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
687
691
  and field.key not in field_args):
688
692
  missing_args.append(str(field.key))
689
693
  if missing_args:
690
- arg_phrase = object_utils.auto_plural(len(missing_args), 'argument')
691
- keys_str = object_utils.comma_delimited_str(missing_args)
694
+ arg_phrase = utils.auto_plural(len(missing_args), 'argument')
695
+ keys_str = utils.comma_delimited_str(missing_args)
692
696
  raise TypeError(
693
697
  f'{self.__class__.__name__}.__init__() missing {len(missing_args)} '
694
698
  f'required {arg_phrase}: {keys_str}.')
@@ -738,8 +742,7 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
738
742
  and during __init__.
739
743
  """
740
744
 
741
- def _on_change(self,
742
- field_updates: Dict[object_utils.KeyPath, base.FieldUpdate]):
745
+ def _on_change(self, field_updates: Dict[utils.KeyPath, base.FieldUpdate]):
743
746
  """Event that is triggered when field values in the subtree are updated.
744
747
 
745
748
  This event will be called
@@ -759,8 +762,7 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
759
762
  del field_updates
760
763
  return self._on_bound()
761
764
 
762
- def _on_path_change(
763
- self, old_path: object_utils.KeyPath, new_path: object_utils.KeyPath):
765
+ def _on_path_change(self, old_path: utils.KeyPath, new_path: utils.KeyPath):
764
766
  """Event that is triggered after the symbolic path changes."""
765
767
  del old_path, new_path
766
768
 
@@ -839,8 +841,8 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
839
841
  return self._sym_attributes.sym_getattr(key)
840
842
 
841
843
  def _sym_rebind(
842
- self, path_value_pairs: Dict[object_utils.KeyPath, Any]
843
- ) -> List[base.FieldUpdate]:
844
+ self, path_value_pairs: Dict[utils.KeyPath, Any]
845
+ ) -> List[base.FieldUpdate]:
844
846
  """Rebind current object using object-form members."""
845
847
  if base.treats_as_sealed(self):
846
848
  raise base.WritePermissionError(
@@ -879,9 +881,8 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
879
881
  return self
880
882
 
881
883
  def _update_children_paths(
882
- self,
883
- old_path: object_utils.KeyPath,
884
- new_path: object_utils.KeyPath) -> None:
884
+ self, old_path: utils.KeyPath, new_path: utils.KeyPath
885
+ ) -> None:
885
886
  """Update children paths according to root_path of current node."""
886
887
  self._sym_attributes.sym_setpath(new_path)
887
888
  self._on_path_change(old_path, new_path)
@@ -965,10 +966,10 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
965
966
  return self.sym_hash()
966
967
  return super().__hash__()
967
968
 
968
- def sym_jsonify(self, **kwargs) -> object_utils.JSONValueType:
969
+ def sym_jsonify(self, **kwargs) -> utils.JSONValueType:
969
970
  """Converts current object to a dict of plain Python objects."""
970
971
  json_dict = {
971
- object_utils.JSONConvertible.TYPE_NAME_KEY: (
972
+ utils.JSONConvertible.TYPE_NAME_KEY: (
972
973
  self.__class__.__serialization_key__
973
974
  )
974
975
  }
@@ -987,8 +988,9 @@ class Object(base.Symbolic, metaclass=ObjectMeta):
987
988
  root_indent,
988
989
  cls_name=self.__class__.__name__,
989
990
  key_as_attribute=True,
990
- bracket_type=object_utils.BracketType.ROUND,
991
- **kwargs)
991
+ bracket_type=utils.BracketType.ROUND,
992
+ **kwargs,
993
+ )
992
994
 
993
995
 
994
996
  base.Symbolic.ObjectType = Object
@@ -11,8 +11,6 @@
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.Object."""
15
-
16
14
  import copy
17
15
  import inspect
18
16
  import io
@@ -23,8 +21,8 @@ import typing
23
21
  from typing import Any
24
22
  import unittest
25
23
 
26
- from pyglove.core import object_utils
27
24
  from pyglove.core import typing as pg_typing
25
+ from pyglove.core import utils
28
26
  from pyglove.core.symbolic import base
29
27
  from pyglove.core.symbolic import flags
30
28
  from pyglove.core.symbolic import inferred
@@ -42,7 +40,7 @@ from pyglove.core.symbolic.pure_symbolic import PureSymbolic
42
40
  from pyglove.core.views.html import tree_view # pylint: disable=unused-import
43
41
 
44
42
 
45
- MISSING_VALUE = object_utils.MISSING_VALUE
43
+ MISSING_VALUE = utils.MISSING_VALUE
46
44
 
47
45
 
48
46
  class ObjectMetaTest(unittest.TestCase):
@@ -205,7 +203,7 @@ class ObjectTest(unittest.TestCase):
205
203
  ])
206
204
  class A(Object):
207
205
 
208
- @object_utils.explicit_method_override
206
+ @utils.explicit_method_override
209
207
  def __init__(self, x):
210
208
  super().__init__(int(x))
211
209
 
@@ -214,7 +212,7 @@ class ObjectTest(unittest.TestCase):
214
212
 
215
213
  class B(A):
216
214
 
217
- @object_utils.explicit_method_override
215
+ @utils.explicit_method_override
218
216
  def __init__(self, x): # pylint: disable=super-init-not-called
219
217
  # Forgot to call super().__init__ will trigger error.
220
218
  self.x = x
@@ -802,8 +800,8 @@ class ObjectTest(unittest.TestCase):
802
800
  a = A(A(dict(y=A(1))))
803
801
  self.assertTrue(a.sym_has('x'))
804
802
  self.assertTrue(a.sym_has('x.x'))
805
- self.assertTrue(a.sym_has(object_utils.KeyPath.parse('x.x.y')))
806
- self.assertTrue(a.sym_has(object_utils.KeyPath.parse('x.x.y.x')))
803
+ self.assertTrue(a.sym_has(utils.KeyPath.parse('x.x.y')))
804
+ self.assertTrue(a.sym_has(utils.KeyPath.parse('x.x.y.x')))
807
805
  self.assertFalse(a.sym_has('y')) # `y` is not a symbolic field.
808
806
 
809
807
  def test_sym_get(self):
@@ -828,10 +826,10 @@ class ObjectTest(unittest.TestCase):
828
826
  self.assertIs(a.sym_get('x'), a.x)
829
827
  self.assertIs(a.sym_get('p'), a.sym_getattr('p'))
830
828
  self.assertIs(a.sym_get('x.x'), a.x.x)
831
- self.assertIs(a.sym_get(object_utils.KeyPath.parse('x.x.y')), a.x.x.y)
832
- self.assertIs(a.sym_get(object_utils.KeyPath.parse('x.x.y.x')), a.x.x.y.x)
829
+ self.assertIs(a.sym_get(utils.KeyPath.parse('x.x.y')), a.x.x.y)
830
+ self.assertIs(a.sym_get(utils.KeyPath.parse('x.x.y.x')), a.x.x.y.x)
833
831
  self.assertIs(
834
- a.sym_get(object_utils.KeyPath.parse('x.x.y.p')),
832
+ a.sym_get(utils.KeyPath.parse('x.x.y.p')),
835
833
  a.x.x.y.sym_getattr('p'),
836
834
  )
837
835
  self.assertIsNone(a.sym_get('x.x.y.q', use_inferred=True))
@@ -1595,7 +1593,7 @@ class ObjectTest(unittest.TestCase):
1595
1593
  self.assertEqual(a.x.x.x.sym_path, 'x.x.x')
1596
1594
  self.assertEqual(a.x.x.x[0].sym_path, 'x.x.x[0]')
1597
1595
 
1598
- a.sym_setpath(object_utils.KeyPath('a'))
1596
+ a.sym_setpath(utils.KeyPath('a'))
1599
1597
  self.assertEqual(a.sym_path, 'a')
1600
1598
  self.assertEqual(a.x.sym_path, 'a.x')
1601
1599
  self.assertEqual(a.x.x.sym_path, 'a.x.x')
@@ -2075,7 +2073,7 @@ class InitSignatureTest(unittest.TestCase):
2075
2073
  class C(B):
2076
2074
  """Custom __init__."""
2077
2075
 
2078
- @object_utils.explicit_method_override
2076
+ @utils.explicit_method_override
2079
2077
  def __init__(self, a, b):
2080
2078
  super().__init__(b, x=a)
2081
2079
 
@@ -2450,44 +2448,51 @@ class EventsTest(unittest.TestCase):
2450
2448
  [
2451
2449
  # Set default value from outer space (parent List) for field d1.
2452
2450
  {
2453
- 'd1':
2454
- base.FieldUpdate(
2455
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d1'),
2456
- target=sd.a2.b1.c1[0],
2457
- field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2458
- old_value=MISSING_VALUE,
2459
- new_value='foo')
2451
+ 'd1': base.FieldUpdate(
2452
+ path=utils.KeyPath.parse('a2.b1.c1[0].d1'),
2453
+ target=sd.a2.b1.c1[0],
2454
+ field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2455
+ old_value=MISSING_VALUE,
2456
+ new_value='foo',
2457
+ )
2460
2458
  },
2461
2459
  # Set default value from outer space (parent List) for field d2.
2462
2460
  {
2463
- 'd2':
2464
- base.FieldUpdate(
2465
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d2'),
2466
- target=sd.a2.b1.c1[0],
2467
- field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2468
- old_value=MISSING_VALUE,
2469
- new_value=True)
2470
- }
2471
- ])
2461
+ 'd2': base.FieldUpdate(
2462
+ path=utils.KeyPath.parse('a2.b1.c1[0].d2'),
2463
+ target=sd.a2.b1.c1[0],
2464
+ field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2465
+ old_value=MISSING_VALUE,
2466
+ new_value=True,
2467
+ )
2468
+ },
2469
+ ],
2470
+ )
2472
2471
 
2473
2472
  # list get updated after bind with parent structures.
2474
- self.assertEqual(list_updates, [{
2475
- '[0].d1':
2476
- base.FieldUpdate(
2477
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d1'),
2478
- target=sd.a2.b1.c1[0],
2479
- field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2480
- old_value=MISSING_VALUE,
2481
- new_value='foo')
2482
- }, {
2483
- '[0].d2':
2484
- base.FieldUpdate(
2485
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d2'),
2486
- target=sd.a2.b1.c1[0],
2487
- field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2488
- old_value=MISSING_VALUE,
2489
- new_value=True)
2490
- }])
2473
+ self.assertEqual(
2474
+ list_updates,
2475
+ [
2476
+ {
2477
+ '[0].d1': base.FieldUpdate(
2478
+ path=utils.KeyPath.parse('a2.b1.c1[0].d1'),
2479
+ target=sd.a2.b1.c1[0],
2480
+ field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2481
+ old_value=MISSING_VALUE,
2482
+ new_value='foo',
2483
+ )
2484
+ },
2485
+ {
2486
+ '[0].d2': base.FieldUpdate(
2487
+ path=utils.KeyPath.parse('a2.b1.c1[0].d2'),
2488
+ target=sd.a2.b1.c1[0],
2489
+ field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2490
+ old_value=MISSING_VALUE,
2491
+ new_value=True,
2492
+ )
2493
+ },
2494
+ ],
2495
+ )
2491
2496
 
2492
2497
  # There are no updates in root.
2493
2498
  self.assertEqual(root_updates, [])
@@ -2510,28 +2515,28 @@ class EventsTest(unittest.TestCase):
2510
2515
  root_updates[0],
2511
2516
  {
2512
2517
  'a1': base.FieldUpdate(
2513
- path=object_utils.KeyPath.parse('a1'),
2518
+ path=utils.KeyPath.parse('a1'),
2514
2519
  target=sd,
2515
2520
  field=sd.value_spec.schema['a1'],
2516
2521
  old_value=MISSING_VALUE,
2517
2522
  new_value=1,
2518
2523
  ),
2519
2524
  'a2.b1.c1[0].d1': base.FieldUpdate(
2520
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d1'),
2525
+ path=utils.KeyPath.parse('a2.b1.c1[0].d1'),
2521
2526
  target=sd.a2.b1.c1[0],
2522
2527
  field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2523
2528
  old_value='foo',
2524
2529
  new_value='bar',
2525
2530
  ),
2526
2531
  'a2.b1.c1[0].d2': base.FieldUpdate(
2527
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d2'),
2532
+ path=utils.KeyPath.parse('a2.b1.c1[0].d2'),
2528
2533
  target=sd.a2.b1.c1[0],
2529
2534
  field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2530
2535
  old_value=True,
2531
2536
  new_value=False,
2532
2537
  ),
2533
2538
  'a2.b1.c1[0].d3.z': base.FieldUpdate(
2534
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d3.z'),
2539
+ path=utils.KeyPath.parse('a2.b1.c1[0].d3.z'),
2535
2540
  target=sd.a2.b1.c1[0].d3,
2536
2541
  field=sd.a2.b1.c1[0].d3.__class__.__schema__['z'],
2537
2542
  old_value=MISSING_VALUE,
@@ -2547,21 +2552,21 @@ class EventsTest(unittest.TestCase):
2547
2552
  # Root object rebind.
2548
2553
  {
2549
2554
  '[0].d1': base.FieldUpdate(
2550
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d1'),
2555
+ path=utils.KeyPath.parse('a2.b1.c1[0].d1'),
2551
2556
  target=sd.a2.b1.c1[0],
2552
2557
  field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2553
2558
  old_value='foo',
2554
2559
  new_value='bar',
2555
2560
  ),
2556
2561
  '[0].d2': base.FieldUpdate(
2557
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d2'),
2562
+ path=utils.KeyPath.parse('a2.b1.c1[0].d2'),
2558
2563
  target=sd.a2.b1.c1[0],
2559
2564
  field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2560
2565
  old_value=True,
2561
2566
  new_value=False,
2562
2567
  ),
2563
2568
  '[0].d3.z': base.FieldUpdate(
2564
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d3.z'),
2569
+ path=utils.KeyPath.parse('a2.b1.c1[0].d3.z'),
2565
2570
  target=sd.a2.b1.c1[0].d3,
2566
2571
  field=sd.a2.b1.c1[0].d3.__class__.__schema__['z'],
2567
2572
  old_value=MISSING_VALUE,
@@ -2577,29 +2582,30 @@ class EventsTest(unittest.TestCase):
2577
2582
  [
2578
2583
  # Root object rebind.
2579
2584
  {
2580
- 'd1':
2581
- base.FieldUpdate(
2582
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d1'),
2583
- target=sd.a2.b1.c1[0],
2584
- field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2585
- old_value='foo',
2586
- new_value='bar'),
2587
- 'd2':
2588
- base.FieldUpdate(
2589
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d2'),
2590
- target=sd.a2.b1.c1[0],
2591
- field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2592
- old_value=True,
2593
- new_value=False),
2594
- 'd3.z':
2595
- base.FieldUpdate(
2596
- path=object_utils.KeyPath.parse('a2.b1.c1[0].d3.z'),
2597
- target=sd.a2.b1.c1[0].d3,
2598
- field=sd.a2.b1.c1[0].d3.__class__.__schema__['z'],
2599
- old_value=MISSING_VALUE,
2600
- new_value='foo')
2585
+ 'd1': base.FieldUpdate(
2586
+ path=utils.KeyPath.parse('a2.b1.c1[0].d1'),
2587
+ target=sd.a2.b1.c1[0],
2588
+ field=sd.a2.b1.c1[0].value_spec.schema['d1'],
2589
+ old_value='foo',
2590
+ new_value='bar',
2591
+ ),
2592
+ 'd2': base.FieldUpdate(
2593
+ path=utils.KeyPath.parse('a2.b1.c1[0].d2'),
2594
+ target=sd.a2.b1.c1[0],
2595
+ field=sd.a2.b1.c1[0].value_spec.schema['d2'],
2596
+ old_value=True,
2597
+ new_value=False,
2598
+ ),
2599
+ 'd3.z': base.FieldUpdate(
2600
+ path=utils.KeyPath.parse('a2.b1.c1[0].d3.z'),
2601
+ target=sd.a2.b1.c1[0].d3,
2602
+ field=sd.a2.b1.c1[0].d3.__class__.__schema__['z'],
2603
+ old_value=MISSING_VALUE,
2604
+ new_value='foo',
2605
+ ),
2601
2606
  }
2602
- ])
2607
+ ],
2608
+ )
2603
2609
 
2604
2610
  def test_on_change_notification_order(self):
2605
2611
  change_order = []
@@ -2645,7 +2651,7 @@ class EventsTest(unittest.TestCase):
2645
2651
  y.x = A()
2646
2652
  self.assertIs(x.old_parent, y)
2647
2653
  self.assertIsNone(x.new_parent)
2648
- self.assertEqual(x.sym_path, object_utils.KeyPath())
2654
+ self.assertEqual(x.sym_path, utils.KeyPath())
2649
2655
 
2650
2656
  def test_on_path_change(self):
2651
2657
 
@@ -2656,8 +2662,8 @@ class EventsTest(unittest.TestCase):
2656
2662
  self.new_path = new_path
2657
2663
 
2658
2664
  x = A()
2659
- x.sym_setpath(object_utils.KeyPath('a'))
2660
- self.assertEqual(x.old_path, object_utils.KeyPath())
2665
+ x.sym_setpath(utils.KeyPath('a'))
2666
+ self.assertEqual(x.old_path, utils.KeyPath())
2661
2667
  self.assertEqual(x.new_path, 'a')
2662
2668
 
2663
2669
  y = Dict(x=x)
@@ -3059,7 +3065,7 @@ class SerializationTest(unittest.TestCase):
3059
3065
 
3060
3066
  def test_serialization_with_json_convertible(self):
3061
3067
 
3062
- class Y(object_utils.JSONConvertible):
3068
+ class Y(utils.JSONConvertible):
3063
3069
 
3064
3070
  TYPE_NAME = 'Y'
3065
3071
 
@@ -3079,7 +3085,7 @@ class SerializationTest(unittest.TestCase):
3079
3085
  def from_json(cls, json_dict, *args, **kwargs):
3080
3086
  return cls(json_dict.pop('value'))
3081
3087
 
3082
- object_utils.JSONConvertible.register(Y.TYPE_NAME, Y)
3088
+ utils.JSONConvertible.register(Y.TYPE_NAME, Y)
3083
3089
 
3084
3090
  a = self._A(Y(1), y=True)
3085
3091
  self.assertEqual(base.from_json_str(a.to_json_str()), a)
@@ -3286,9 +3292,7 @@ class FormatTest(unittest.TestCase):
3286
3292
 
3287
3293
  def test_compact_python_format(self):
3288
3294
  self.assertEqual(
3289
- object_utils.format(
3290
- self._a, compact=True, python_format=True, markdown=True
3291
- ),
3295
+ utils.format(self._a, compact=True, python_format=True, markdown=True),
3292
3296
  "`A(x=[A(x=1, y=None), A(x='foo', y={'a': A(x=True, y=1.0)})], "
3293
3297
  'y=MISSING_VALUE)`',
3294
3298
  )
@@ -3333,9 +3337,12 @@ class FormatTest(unittest.TestCase):
3333
3337
 
3334
3338
  def test_noncompact_python_format(self):
3335
3339
  self.assertEqual(
3336
- object_utils.format(
3337
- self._a, compact=False, verbose=False, python_format=True,
3338
- markdown=True
3340
+ utils.format(
3341
+ self._a,
3342
+ compact=False,
3343
+ verbose=False,
3344
+ python_format=True,
3345
+ markdown=True,
3339
3346
  ),
3340
3347
  inspect.cleandoc("""
3341
3348
  ```
@@ -3502,10 +3509,10 @@ class FormatTest(unittest.TestCase):
3502
3509
  return f() if f is not None else None
3503
3510
  return fn
3504
3511
 
3505
- with object_utils.str_format(custom_format=_method('_repr_xml_')):
3512
+ with utils.str_format(custom_format=_method('_repr_xml_')):
3506
3513
  self.assertEqual(str(Bar(Foo())), 'Bar(\n foo = Foo()\n)')
3507
3514
 
3508
- with object_utils.str_format(custom_format=_method('_repr_html_')):
3515
+ with utils.str_format(custom_format=_method('_repr_html_')):
3509
3516
  self.assertIn('<html>', str(Bar(Foo())))
3510
3517
 
3511
3518
 
@@ -16,11 +16,11 @@
16
16
  import traceback
17
17
  from typing import Any, Callable, List, Optional
18
18
 
19
- from pyglove.core import object_utils
19
+ from pyglove.core import utils
20
20
  from pyglove.core.symbolic import flags
21
21
 
22
22
 
23
- class Origin(object_utils.Formattable):
23
+ class Origin(utils.Formattable):
24
24
  """Class that represents the origin of a symbolic value.
25
25
 
26
26
  Origin is used for debugging the creation chain of a symbolic value, as
@@ -158,14 +158,12 @@ class Origin(object_utils.Formattable):
158
158
  if isinstance(self._source, (str, type(None))):
159
159
  source_str = self._source
160
160
  else:
161
- source_info = object_utils.format(
161
+ source_info = utils.format(
162
162
  self._source, compact, verbose, root_indent + 1, **kwargs
163
163
  )
164
- source_str = object_utils.RawText(
165
- f'{source_info} at 0x{id(self._source):8x}'
166
- )
164
+ source_str = utils.RawText(f'{source_info} at 0x{id(self._source):8x}')
167
165
 
168
- return object_utils.kvlist_str(
166
+ return utils.kvlist_str(
169
167
  [
170
168
  ('tag', self._tag, None),
171
169
  ('source', source_str, None),
@@ -14,8 +14,8 @@
14
14
  """Interfaces for pure symbolic objects."""
15
15
 
16
16
  from typing import Any, Callable, Optional, 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
 
20
20
 
21
21
  class PureSymbolic(pg_typing.CustomTyping):
@@ -37,11 +37,12 @@ class PureSymbolic(pg_typing.CustomTyping):
37
37
 
38
38
  def custom_apply(
39
39
  self,
40
- path: object_utils.KeyPath,
40
+ path: utils.KeyPath,
41
41
  value_spec: pg_typing.ValueSpec,
42
42
  allow_partial: bool,
43
43
  child_transform: Optional[
44
- Callable[[object_utils.KeyPath, pg_typing.Field, Any], Any]] = None
44
+ Callable[[utils.KeyPath, pg_typing.Field, Any], Any]
45
+ ] = None,
45
46
  ) -> Tuple[bool, Any]:
46
47
  """Custom apply on a value based on its original value spec.
47
48