pyglove 0.4.5.dev202501030808__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.dev202501030808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/METADATA +1 -1
  83. {pyglove-0.4.5.dev202501030808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/RECORD +90 -90
  84. {pyglove-0.4.5.dev202501030808.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.dev202501030808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/LICENSE +0 -0
  91. {pyglove-0.4.5.dev202501030808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/top_level.txt +0 -0
@@ -25,8 +25,8 @@ import typing
25
25
  from typing import Any, Callable, Dict, Iterator, List, Literal, Optional, Tuple, Type, Union
26
26
 
27
27
  from pyglove.core import io as pg_io
28
- from pyglove.core import object_utils
29
28
  from pyglove.core import typing as pg_typing
29
+ from pyglove.core import utils
30
30
  from pyglove.core.symbolic import flags
31
31
  from pyglove.core.symbolic.origin import Origin
32
32
  from pyglove.core.symbolic.pure_symbolic import NonDeterministic
@@ -38,15 +38,17 @@ class WritePermissionError(Exception):
38
38
  """Exception raisen when write access to object fields is not allowed."""
39
39
 
40
40
 
41
- class FieldUpdate(object_utils.Formattable):
41
+ class FieldUpdate(utils.Formattable):
42
42
  """Class that describes an update to a field in an object tree."""
43
43
 
44
- def __init__(self,
45
- path: object_utils.KeyPath,
46
- target: 'Symbolic',
47
- field: Optional[pg_typing.Field],
48
- old_value: Any,
49
- new_value: Any):
44
+ def __init__(
45
+ self,
46
+ path: utils.KeyPath,
47
+ target: 'Symbolic',
48
+ field: Optional[pg_typing.Field],
49
+ old_value: Any,
50
+ new_value: Any,
51
+ ):
50
52
  """Constructor.
51
53
 
52
54
  Args:
@@ -70,18 +72,18 @@ class FieldUpdate(object_utils.Formattable):
70
72
  **kwargs,
71
73
  ) -> str:
72
74
  """Formats this object."""
73
- return object_utils.kvlist_str(
75
+ return utils.kvlist_str(
74
76
  [
75
77
  ('parent_path', self.target.sym_path, None),
76
78
  ('path', self.path, None),
77
- ('old_value', self.old_value, object_utils.MISSING_VALUE),
78
- ('new_value', self.new_value, object_utils.MISSING_VALUE),
79
+ ('old_value', self.old_value, utils.MISSING_VALUE),
80
+ ('new_value', self.new_value, utils.MISSING_VALUE),
79
81
  ],
80
82
  label=self.__class__.__name__,
81
83
  compact=compact,
82
84
  verbose=verbose,
83
85
  root_indent=root_indent,
84
- **kwargs
86
+ **kwargs,
85
87
  )
86
88
 
87
89
  def __eq__(self, other: Any) -> bool:
@@ -124,11 +126,11 @@ class TopologyAware(metaclass=abc.ABCMeta):
124
126
 
125
127
  @property
126
128
  @abc.abstractmethod
127
- def sym_path(self) -> object_utils.KeyPath:
129
+ def sym_path(self) -> utils.KeyPath:
128
130
  """Returns the path of this object under its topology."""
129
131
 
130
132
  @abc.abstractmethod
131
- def sym_setpath(self, path: object_utils.KeyPath) -> None:
133
+ def sym_setpath(self, path: utils.KeyPath) -> None:
132
134
  """Sets the path of this object under its topology."""
133
135
 
134
136
 
@@ -172,9 +174,9 @@ RAISE_IF_NOT_FOUND = (pg_typing.MISSING_VALUE,)
172
174
 
173
175
  class Symbolic(
174
176
  TopologyAware,
175
- object_utils.Formattable,
176
- object_utils.JSONConvertible,
177
- object_utils.MaybePartial,
177
+ utils.Formattable,
178
+ utils.JSONConvertible,
179
+ utils.MaybePartial,
178
180
  HtmlConvertible,
179
181
  ):
180
182
  """Base for all symbolic types.
@@ -203,13 +205,15 @@ class Symbolic(
203
205
 
204
206
  # pylint: enable=invalid-name
205
207
 
206
- def __init__(self,
207
- *,
208
- allow_partial: bool,
209
- accessor_writable: bool,
210
- sealed: bool,
211
- root_path: Optional[object_utils.KeyPath],
212
- init_super: bool = True):
208
+ def __init__(
209
+ self,
210
+ *,
211
+ allow_partial: bool,
212
+ accessor_writable: bool,
213
+ sealed: bool,
214
+ root_path: Optional[utils.KeyPath],
215
+ init_super: bool = True,
216
+ ):
213
217
  """Constructor.
214
218
 
215
219
  Args:
@@ -237,7 +241,7 @@ class Symbolic(
237
241
  # NOTE(daiyip): parent is used for rebind call to notify their ancestors
238
242
  # for updates, not for external usage.
239
243
  self._set_raw_attr('_sym_parent', None)
240
- self._set_raw_attr('_sym_path', root_path or object_utils.KeyPath())
244
+ self._set_raw_attr('_sym_path', root_path or utils.KeyPath())
241
245
  self._set_raw_attr('_sym_puresymbolic', None)
242
246
  self._set_raw_attr('_sym_missing_values', None)
243
247
  self._set_raw_attr('_sym_nondefault_values', None)
@@ -317,7 +321,7 @@ class Symbolic(
317
321
  missing = self._sym_missing()
318
322
  self._set_raw_attr('_sym_missing_values', missing)
319
323
  if flatten:
320
- missing = object_utils.flatten(missing)
324
+ missing = utils.flatten(missing)
321
325
  return missing
322
326
 
323
327
  def sym_nondefault(self, flatten: bool = True) -> Dict[Union[int, str], Any]:
@@ -327,7 +331,7 @@ class Symbolic(
327
331
  nondefault = self._sym_nondefault()
328
332
  self._set_raw_attr('_sym_nondefault_values', nondefault)
329
333
  if flatten:
330
- nondefault = object_utils.flatten(nondefault)
334
+ nondefault = utils.flatten(nondefault)
331
335
  return nondefault
332
336
 
333
337
  @property
@@ -405,7 +409,7 @@ class Symbolic(
405
409
  def sym_attr_field(self, key: Union[str, int]) -> Optional[pg_typing.Field]:
406
410
  """Returns the field definition for a symbolic attribute."""
407
411
 
408
- def sym_has(self, path: Union[object_utils.KeyPath, str, int]) -> bool:
412
+ def sym_has(self, path: Union[utils.KeyPath, str, int]) -> bool:
409
413
  """Returns True if a path exists in the sub-tree.
410
414
 
411
415
  Args:
@@ -414,13 +418,14 @@ class Symbolic(
414
418
  Returns:
415
419
  True if the path exists in current sub-tree, otherwise False.
416
420
  """
417
- return object_utils.KeyPath.from_value(path).exists(self)
421
+ return utils.KeyPath.from_value(path).exists(self)
418
422
 
419
423
  def sym_get(
420
424
  self,
421
- path: Union[object_utils.KeyPath, str, int],
425
+ path: Union[utils.KeyPath, str, int],
422
426
  default: Any = RAISE_IF_NOT_FOUND,
423
- use_inferred: bool = False) -> Any:
427
+ use_inferred: bool = False,
428
+ ) -> Any:
424
429
  """Returns a sub-node by path.
425
430
 
426
431
  NOTE: there is no `sym_set`, use `sym_rebind`.
@@ -439,7 +444,7 @@ class Symbolic(
439
444
  Raises:
440
445
  KeyError if `path` does not exist and `default` is not specified.
441
446
  """
442
- path = object_utils.KeyPath.from_value(path)
447
+ path = utils.KeyPath.from_value(path)
443
448
  if default is RAISE_IF_NOT_FOUND:
444
449
  return path.query(self, use_inferred=use_inferred)
445
450
  else:
@@ -533,12 +538,11 @@ class Symbolic(
533
538
  return contains(self, value, type)
534
539
 
535
540
  @property
536
- def sym_path(self) -> object_utils.KeyPath:
541
+ def sym_path(self) -> utils.KeyPath:
537
542
  """Returns the path of current object from the root of its symbolic tree."""
538
543
  return getattr(self, '_sym_path')
539
544
 
540
- def sym_setpath(
541
- self, path: Optional[Union[str, object_utils.KeyPath]]) -> None:
545
+ def sym_setpath(self, path: Optional[Union[str, utils.KeyPath]]) -> None:
542
546
  """Sets the path of current node in its symbolic tree."""
543
547
  if self.sym_path != path:
544
548
  old_path = self.sym_path
@@ -547,11 +551,9 @@ class Symbolic(
547
551
 
548
552
  def sym_rebind(
549
553
  self,
550
- path_value_pairs: Optional[Union[
551
- Dict[
552
- Union[object_utils.KeyPath, str, int],
553
- Any],
554
- Callable]] = None, # pylint: disable=g-bare-generic
554
+ path_value_pairs: Optional[
555
+ Union[Dict[Union[utils.KeyPath, str, int], Any], Callable[..., Any]]
556
+ ] = None, # pylint: disable=g-bare-generic
555
557
  *,
556
558
  raise_on_no_change: bool = True,
557
559
  notify_parents: bool = True,
@@ -575,8 +577,9 @@ class Symbolic(
575
577
  f'Argument \'path_value_pairs\' should be a dict. '
576
578
  f'Encountered {path_value_pairs}'))
577
579
  path_value_pairs.update(kwargs)
578
- path_value_pairs = {object_utils.KeyPath.from_value(k): v
579
- for k, v in path_value_pairs.items()}
580
+ path_value_pairs = {
581
+ utils.KeyPath.from_value(k): v for k, v in path_value_pairs.items()
582
+ }
580
583
 
581
584
  if not path_value_pairs and raise_on_no_change:
582
585
  raise ValueError(self._error_message('There are no values to rebind.'))
@@ -601,10 +604,9 @@ class Symbolic(
601
604
  return new_value
602
605
 
603
606
  @abc.abstractmethod
604
- def sym_jsonify(self,
605
- *,
606
- hide_default_values: bool = False,
607
- **kwargs) -> object_utils.JSONValueType:
607
+ def sym_jsonify(
608
+ self, *, hide_default_values: bool = False, **kwargs
609
+ ) -> utils.JSONValueType:
608
610
  """Converts representation of current object to a plain Python object."""
609
611
 
610
612
  def sym_ne(self, other: Any) -> bool:
@@ -749,16 +751,15 @@ class Symbolic(
749
751
 
750
752
  def rebind(
751
753
  self,
752
- path_value_pairs: Optional[Union[
753
- Dict[
754
- Union[object_utils.KeyPath, str, int],
755
- Any],
756
- Callable]] = None, # pylint: disable=g-bare-generic
754
+ path_value_pairs: Optional[
755
+ Union[Dict[Union[utils.KeyPath, str, int], Any], Callable[..., Any]]
756
+ ] = None, # pylint: disable=g-bare-generic
757
757
  *,
758
758
  raise_on_no_change: bool = True,
759
759
  notify_parents: bool = True,
760
760
  skip_notification: Optional[bool] = None,
761
- **kwargs) -> 'Symbolic':
761
+ **kwargs,
762
+ ) -> 'Symbolic':
762
763
  """Alias for `sym_rebind`.
763
764
 
764
765
  Alias for `sym_rebind`. `rebind` is the recommended way for mutating
@@ -941,7 +942,7 @@ class Symbolic(
941
942
  """
942
943
  return self.sym_clone(deep, memo, override)
943
944
 
944
- def to_json(self, **kwargs) -> object_utils.JSONValueType:
945
+ def to_json(self, **kwargs) -> utils.JSONValueType:
945
946
  """Alias for `sym_jsonify`."""
946
947
  return to_json(self, **kwargs)
947
948
 
@@ -964,13 +965,18 @@ class Symbolic(
964
965
  def inspect(
965
966
  self,
966
967
  path_regex: Optional[str] = None,
967
- where: Optional[Union[Callable[[Any], bool],
968
- Callable[[Any, Any], bool]]] = None,
969
- custom_selector: Optional[Union[
970
- Callable[[object_utils.KeyPath, Any], bool],
971
- Callable[[object_utils.KeyPath, Any, Any], bool]]] = None,
968
+ where: Optional[
969
+ Union[Callable[[Any], bool], Callable[[Any, Any], bool]]
970
+ ] = None,
971
+ custom_selector: Optional[
972
+ Union[
973
+ Callable[[utils.KeyPath, Any], bool],
974
+ Callable[[utils.KeyPath, Any, Any], bool],
975
+ ]
976
+ ] = None,
972
977
  file=sys.stdout, # pylint: disable=redefined-builtin
973
- **kwargs) -> None:
978
+ **kwargs,
979
+ ) -> None:
974
980
  """Inspects current object by printing out selected values.
975
981
 
976
982
  Example::
@@ -1058,7 +1064,7 @@ class Symbolic(
1058
1064
  v = self
1059
1065
  else:
1060
1066
  v = query(self, path_regex, where, False, custom_selector)
1061
- object_utils.print(v, file=file, **kwargs)
1067
+ utils.print(v, file=file, **kwargs)
1062
1068
 
1063
1069
  def __copy__(self) -> 'Symbolic':
1064
1070
  """Overridden shallow copy."""
@@ -1074,8 +1080,8 @@ class Symbolic(
1074
1080
 
1075
1081
  @abc.abstractmethod
1076
1082
  def _sym_rebind(
1077
- self, path_value_pairs: Dict[object_utils.KeyPath, Any]
1078
- ) -> List[FieldUpdate]:
1083
+ self, path_value_pairs: Dict[utils.KeyPath, Any]
1084
+ ) -> List[FieldUpdate]:
1079
1085
  """Subclass specific rebind implementation.
1080
1086
 
1081
1087
  Args:
@@ -1111,9 +1117,8 @@ class Symbolic(
1111
1117
 
1112
1118
  @abc.abstractmethod
1113
1119
  def _update_children_paths(
1114
- self,
1115
- old_path: object_utils.KeyPath,
1116
- new_path: object_utils.KeyPath) -> None:
1120
+ self, old_path: utils.KeyPath, new_path: utils.KeyPath
1121
+ ) -> None:
1117
1122
  """Update children paths according to root_path of current node."""
1118
1123
 
1119
1124
  @abc.abstractmethod
@@ -1122,7 +1127,7 @@ class Symbolic(
1122
1127
  """Child should implement: set an item without permission check."""
1123
1128
 
1124
1129
  @abc.abstractmethod
1125
- def _on_change(self, field_updates: Dict[object_utils.KeyPath, FieldUpdate]):
1130
+ def _on_change(self, field_updates: Dict[utils.KeyPath, FieldUpdate]):
1126
1131
  """Event that is triggered when field values in the subtree are updated.
1127
1132
 
1128
1133
  This event will be called
@@ -1175,14 +1180,14 @@ class Symbolic(
1175
1180
  # NOTE(daiyip): make a copy of symbolic object if it belongs to another
1176
1181
  # object tree, this prevents it from having multiple parents. See
1177
1182
  # List._formalized_value for similar logic.
1178
- root_path = object_utils.KeyPath(key, self.sym_path)
1183
+ root_path = utils.KeyPath(key, self.sym_path)
1179
1184
  if (value.sym_parent is not None and
1180
1185
  (value.sym_parent is not self
1181
1186
  or root_path != value.sym_path)):
1182
1187
  value = value.clone()
1183
1188
 
1184
1189
  if isinstance(value, TopologyAware):
1185
- value.sym_setpath(object_utils.KeyPath(key, self.sym_path))
1190
+ value.sym_setpath(utils.KeyPath(key, self.sym_path))
1186
1191
  value.sym_setparent(self._sym_parent_for_children())
1187
1192
  return value
1188
1193
 
@@ -1191,9 +1196,10 @@ class Symbolic(
1191
1196
  return self
1192
1197
 
1193
1198
  def _set_item_of_current_tree(
1194
- self, path: object_utils.KeyPath, value: Any) -> Optional[FieldUpdate]:
1199
+ self, path: utils.KeyPath, value: Any
1200
+ ) -> Optional[FieldUpdate]:
1195
1201
  """Set a field of current tree by key path and return its parent."""
1196
- assert isinstance(path, object_utils.KeyPath), path
1202
+ assert isinstance(path, utils.KeyPath), path
1197
1203
  if not path:
1198
1204
  raise KeyError(
1199
1205
  self._error_message(
@@ -1222,8 +1228,8 @@ class Symbolic(
1222
1228
  per_target_updates = dict()
1223
1229
 
1224
1230
  def _get_target_updates(
1225
- target: 'Symbolic'
1226
- ) -> Dict[object_utils.KeyPath, FieldUpdate]:
1231
+ target: 'Symbolic',
1232
+ ) -> Dict[utils.KeyPath, FieldUpdate]:
1227
1233
  target_id = id(target)
1228
1234
  if target_id not in per_target_updates:
1229
1235
  per_target_updates[target_id] = (target, dict())
@@ -1256,7 +1262,7 @@ class Symbolic(
1256
1262
 
1257
1263
  def _error_message(self, message: str) -> str:
1258
1264
  """Create error message to include path information."""
1259
- return object_utils.message_on_path(message, self.sym_path)
1265
+ return utils.message_on_path(message, self.sym_path)
1260
1266
 
1261
1267
 
1262
1268
  #
@@ -1271,12 +1277,11 @@ def get_rebind_dict(
1271
1277
  """Generate rebind dict using rebinder on target value.
1272
1278
 
1273
1279
  Args:
1274
- rebinder: A callable object with signature:
1275
- (key_path: object_utils.KeyPath, value: Any) -> Any or
1276
- (key_path: object_utils.KeyPath, value: Any, parent: Any) -> Any. If
1277
- rebinder returns the same value from input, the value is considered
1278
- unchanged. Otherwise it will be put into the returning rebind dict. See
1279
- `Symbolic.rebind` for more details.
1280
+ rebinder: A callable object with signature: (key_path: utils.KeyPath, value:
1281
+ Any) -> Any or (key_path: utils.KeyPath, value: Any, parent: Any) -> Any.
1282
+ If rebinder returns the same value from input, the value is considered
1283
+ unchanged. Otherwise it will be put into the returning rebind dict. See
1284
+ `Symbolic.rebind` for more details.
1280
1285
  target: Upon which value the rebind dict is computed.
1281
1286
 
1282
1287
  Returns:
@@ -1329,15 +1334,17 @@ class TraverseAction(enum.Enum):
1329
1334
  CONTINUE = 2
1330
1335
 
1331
1336
 
1332
- def traverse(x: Any,
1333
- preorder_visitor_fn: Optional[
1334
- Callable[[object_utils.KeyPath, Any, Any],
1335
- Optional[TraverseAction]]] = None,
1336
- postorder_visitor_fn: Optional[
1337
- Callable[[object_utils.KeyPath, Any, Any],
1338
- Optional[TraverseAction]]] = None,
1339
- root_path: Optional[object_utils.KeyPath] = None,
1340
- parent: Optional[Any] = None) -> bool:
1337
+ def traverse(
1338
+ x: Any,
1339
+ preorder_visitor_fn: Optional[
1340
+ Callable[[utils.KeyPath, Any, Any], Optional[TraverseAction]]
1341
+ ] = None,
1342
+ postorder_visitor_fn: Optional[
1343
+ Callable[[utils.KeyPath, Any, Any], Optional[TraverseAction]]
1344
+ ] = None,
1345
+ root_path: Optional[utils.KeyPath] = None,
1346
+ parent: Optional[Any] = None,
1347
+ ) -> bool:
1341
1348
  """Traverse a (maybe) symbolic value using visitor functions.
1342
1349
 
1343
1350
  Example::
@@ -1372,7 +1379,7 @@ def traverse(x: Any,
1372
1379
  either `TraverseAction.ENTER` or `TraverseAction.CONTINUE` for all nodes.
1373
1380
  Otherwise False.
1374
1381
  """
1375
- root_path = root_path or object_utils.KeyPath()
1382
+ root_path = root_path or utils.KeyPath()
1376
1383
 
1377
1384
  def no_op_visitor(path, value, parent):
1378
1385
  del path, value, parent
@@ -1387,20 +1394,35 @@ def traverse(x: Any,
1387
1394
  if preorder_action is None or preorder_action == TraverseAction.ENTER:
1388
1395
  if isinstance(x, dict):
1389
1396
  for k, v in x.items():
1390
- if not traverse(v, preorder_visitor_fn, postorder_visitor_fn,
1391
- object_utils.KeyPath(k, root_path), x):
1397
+ if not traverse(
1398
+ v,
1399
+ preorder_visitor_fn,
1400
+ postorder_visitor_fn,
1401
+ utils.KeyPath(k, root_path),
1402
+ x,
1403
+ ):
1392
1404
  preorder_action = TraverseAction.STOP
1393
1405
  break
1394
1406
  elif isinstance(x, list):
1395
1407
  for i, v in enumerate(x):
1396
- if not traverse(v, preorder_visitor_fn, postorder_visitor_fn,
1397
- object_utils.KeyPath(i, root_path), x):
1408
+ if not traverse(
1409
+ v,
1410
+ preorder_visitor_fn,
1411
+ postorder_visitor_fn,
1412
+ utils.KeyPath(i, root_path),
1413
+ x,
1414
+ ):
1398
1415
  preorder_action = TraverseAction.STOP
1399
1416
  break
1400
1417
  elif isinstance(x, Symbolic.ObjectType): # pytype: disable=wrong-arg-types
1401
1418
  for k, v in x.sym_items():
1402
- if not traverse(v, preorder_visitor_fn, postorder_visitor_fn,
1403
- object_utils.KeyPath(k, root_path), x):
1419
+ if not traverse(
1420
+ v,
1421
+ preorder_visitor_fn,
1422
+ postorder_visitor_fn,
1423
+ utils.KeyPath(k, root_path),
1424
+ x,
1425
+ ):
1404
1426
  preorder_action = TraverseAction.STOP
1405
1427
  break
1406
1428
  postorder_action = postorder_visitor_fn(root_path, x, parent)
@@ -1413,12 +1435,16 @@ def traverse(x: Any,
1413
1435
  def query(
1414
1436
  x: Any,
1415
1437
  path_regex: Optional[str] = None,
1416
- where: Optional[Union[Callable[[Any], bool],
1417
- Callable[[Any, Any], bool]]] = None,
1438
+ where: Optional[
1439
+ Union[Callable[[Any], bool], Callable[[Any, Any], bool]]
1440
+ ] = None,
1418
1441
  enter_selected: bool = False,
1419
- custom_selector: Optional[Union[
1420
- Callable[[object_utils.KeyPath, Any], bool],
1421
- Callable[[object_utils.KeyPath, Any, Any], bool]]] = None
1442
+ custom_selector: Optional[
1443
+ Union[
1444
+ Callable[[utils.KeyPath, Any], bool],
1445
+ Callable[[utils.KeyPath, Any, Any], bool],
1446
+ ]
1447
+ ] = None,
1422
1448
  ) -> Dict[str, Any]:
1423
1449
  """Queries a (maybe) symbolic value.
1424
1450
 
@@ -1521,8 +1547,9 @@ def query(
1521
1547
 
1522
1548
  results = {}
1523
1549
 
1524
- def _preorder_visitor(path: object_utils.KeyPath, v: Any,
1525
- parent: Any) -> TraverseAction:
1550
+ def _preorder_visitor(
1551
+ path: utils.KeyPath, v: Any, parent: Any
1552
+ ) -> TraverseAction:
1526
1553
  if select_fn(path, v, parent): # pytype: disable=wrong-arg-count
1527
1554
  results[str(path)] = v
1528
1555
  return TraverseAction.ENTER if enter_selected else TraverseAction.CONTINUE
@@ -1752,7 +1779,7 @@ def gt(left: Any, right: Any) -> bool:
1752
1779
 
1753
1780
  def _type_order(value: Any) -> str:
1754
1781
  """Returns the ordering string of value's type."""
1755
- if isinstance(value, object_utils.MissingValue):
1782
+ if isinstance(value, utils.MissingValue):
1756
1783
  type_order = 0
1757
1784
  elif value is None:
1758
1785
  type_order = 1
@@ -1950,7 +1977,7 @@ def is_abstract(x: Any) -> bool:
1950
1977
  True if value itself is partial/PureSymbolic or its child and nested
1951
1978
  child fields contain partial/PureSymbolic values.
1952
1979
  """
1953
- return object_utils.is_partial(x) or is_pure_symbolic(x)
1980
+ return utils.is_partial(x) or is_pure_symbolic(x)
1954
1981
 
1955
1982
 
1956
1983
  def contains(
@@ -2009,11 +2036,11 @@ def from_json(
2009
2036
  json_value: Any,
2010
2037
  *,
2011
2038
  allow_partial: bool = False,
2012
- root_path: Optional[object_utils.KeyPath] = None,
2039
+ root_path: Optional[utils.KeyPath] = None,
2013
2040
  auto_import: bool = True,
2014
2041
  auto_dict: bool = False,
2015
2042
  value_spec: Optional[pg_typing.ValueSpec] = None,
2016
- **kwargs
2043
+ **kwargs,
2017
2044
  ) -> Any:
2018
2045
  """Deserializes a (maybe) symbolic value from JSON value.
2019
2046
 
@@ -2057,28 +2084,30 @@ def from_json(
2057
2084
 
2058
2085
  typename_resolved = kwargs.pop('_typename_resolved', False)
2059
2086
  if not typename_resolved:
2060
- json_value = object_utils.json_conversion.resolve_typenames(
2087
+ json_value = utils.json_conversion.resolve_typenames(
2061
2088
  json_value, auto_import=auto_import, auto_dict=auto_dict
2062
2089
  )
2063
2090
 
2064
2091
  def _load_child(k, v):
2065
2092
  return from_json(
2066
2093
  v,
2067
- root_path=object_utils.KeyPath(k, root_path),
2094
+ root_path=utils.KeyPath(k, root_path),
2068
2095
  _typename_resolved=True,
2069
2096
  allow_partial=allow_partial,
2070
- **kwargs
2097
+ **kwargs,
2071
2098
  )
2072
2099
 
2073
2100
  if isinstance(json_value, list):
2074
- if (json_value
2075
- and json_value[0] == object_utils.JSONConvertible.TUPLE_MARKER):
2101
+ if json_value and json_value[0] == utils.JSONConvertible.TUPLE_MARKER:
2076
2102
  if len(json_value) < 2:
2077
2103
  raise ValueError(
2078
- object_utils.message_on_path(
2079
- f'Tuple should have at least one element '
2080
- f'besides \'{object_utils.JSONConvertible.TUPLE_MARKER}\'. '
2081
- f'Encountered: {json_value}', root_path))
2104
+ utils.message_on_path(
2105
+ 'Tuple should have at least one element '
2106
+ f"besides '{utils.JSONConvertible.TUPLE_MARKER}'. "
2107
+ f'Encountered: {json_value}',
2108
+ root_path,
2109
+ )
2110
+ )
2082
2111
  return tuple(_load_child(i, v) for i, v in enumerate(json_value[1:]))
2083
2112
  return Symbolic.ListType.from_json( # pytype: disable=attribute-error
2084
2113
  json_value,
@@ -2088,7 +2117,7 @@ def from_json(
2088
2117
  **kwargs,
2089
2118
  )
2090
2119
  elif isinstance(json_value, dict):
2091
- if object_utils.JSONConvertible.TYPE_NAME_KEY not in json_value:
2120
+ if utils.JSONConvertible.TYPE_NAME_KEY not in json_value:
2092
2121
  return Symbolic.DictType.from_json( # pytype: disable=attribute-error
2093
2122
  json_value,
2094
2123
  value_spec=value_spec,
@@ -2096,20 +2125,25 @@ def from_json(
2096
2125
  allow_partial=allow_partial,
2097
2126
  **kwargs,
2098
2127
  )
2099
- return object_utils.from_json(
2100
- json_value, _typename_resolved=True,
2101
- root_path=root_path, allow_partial=allow_partial, **kwargs
2128
+ return utils.from_json(
2129
+ json_value,
2130
+ _typename_resolved=True,
2131
+ root_path=root_path,
2132
+ allow_partial=allow_partial,
2133
+ **kwargs,
2102
2134
  )
2103
2135
  return json_value
2104
2136
 
2105
2137
 
2106
- def from_json_str(json_str: str,
2107
- *,
2108
- allow_partial: bool = False,
2109
- root_path: Optional[object_utils.KeyPath] = None,
2110
- auto_import: bool = True,
2111
- auto_dict: bool = False,
2112
- **kwargs) -> Any:
2138
+ def from_json_str(
2139
+ json_str: str,
2140
+ *,
2141
+ allow_partial: bool = False,
2142
+ root_path: Optional[utils.KeyPath] = None,
2143
+ auto_import: bool = True,
2144
+ auto_dict: bool = False,
2145
+ **kwargs,
2146
+ ) -> Any:
2113
2147
  """Deserialize (maybe) symbolic object from JSON string.
2114
2148
 
2115
2149
  Example::
@@ -2202,7 +2236,7 @@ def to_json(value: Any, **kwargs) -> Any:
2202
2236
  # classes may have conflicting `to_json` method in their existing classes.
2203
2237
  if isinstance(value, Symbolic):
2204
2238
  return value.sym_jsonify(**kwargs)
2205
- return object_utils.to_json(value, **kwargs)
2239
+ return utils.to_json(value, **kwargs)
2206
2240
 
2207
2241
 
2208
2242
  def to_json_str(value: Any,
@@ -2378,8 +2412,11 @@ def default_save_handler(
2378
2412
  if file_format == 'json':
2379
2413
  content = to_json_str(value, json_indent=indent, **kwargs)
2380
2414
  elif file_format == 'txt':
2381
- content = value if isinstance(value, str) else object_utils.format(
2382
- value, compact=False, verbose=True)
2415
+ content = (
2416
+ value
2417
+ if isinstance(value, str)
2418
+ else utils.format(value, compact=False, verbose=True)
2419
+ )
2383
2420
  else:
2384
2421
  raise ValueError(f'Unsupported `file_format`: {file_format!r}.')
2385
2422
 
@@ -2415,8 +2452,7 @@ def treats_as_sealed(value: Symbolic) -> bool:
2415
2452
  def symbolic_transform_fn(allow_partial: bool):
2416
2453
  """Symbolic object transform function builder."""
2417
2454
 
2418
- def _fn(
2419
- path: object_utils.KeyPath, field: pg_typing.Field, value: Any) -> Any:
2455
+ def _fn(path: utils.KeyPath, field: pg_typing.Field, value: Any) -> Any:
2420
2456
  """Transform schema-less List and Dict to symbolic."""
2421
2457
  if isinstance(value, Symbolic):
2422
2458
  return value