pyglove 0.4.5.dev202501050808__py3-none-any.whl → 0.4.5.dev202501070809__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.dev202501070809.dist-info}/METADATA +1 -1
  83. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501070809.dist-info}/RECORD +90 -90
  84. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501070809.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.dev202501070809.dist-info}/LICENSE +0 -0
  91. {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501070809.dist-info}/top_level.txt +0 -0
pyglove/core/__init__.py CHANGED
@@ -37,8 +37,7 @@ Here lists the sub-modules included in the core PyGlove library:
37
37
  |__ tuning : Interface for program tuning with a local backend.
38
38
  |__ detouring : Detouring classes creation without symbolic types.
39
39
  |__ patching : Patching a program with URL-like strings.
40
- |__ object_utils : Utility libary on operating with Python objects.
41
-
40
+ |__ utils : Utility libary on operating with Python objects.
42
41
  """
43
42
 
44
43
  # NOTE(daiyip): We disable bad-import-order to preserve the relation of
@@ -273,31 +272,35 @@ ObjectFactory = patching.ObjectFactory
273
272
 
274
273
 
275
274
  #
276
- # Symbols from 'object_utils' sub-module.
275
+ # Symbols from 'utils' sub-module.
277
276
  #
278
277
 
279
- from pyglove.core import object_utils
280
- KeyPath = object_utils.KeyPath
281
- KeyPathSet = object_utils.KeyPathSet
282
- MISSING_VALUE = object_utils.MISSING_VALUE
278
+ from pyglove.core import utils
279
+
280
+ # For backward compatibility.
281
+ object_utils = utils
282
+
283
+ KeyPath = utils.KeyPath
284
+ KeyPathSet = utils.KeyPathSet
285
+ MISSING_VALUE = utils.MISSING_VALUE
283
286
 
284
- Formattable = object_utils.Formattable
285
- repr_format = object_utils.repr_format
286
- str_format = object_utils.str_format
287
+ Formattable = utils.Formattable
288
+ repr_format = utils.repr_format
289
+ str_format = utils.str_format
287
290
 
288
- MaybePartial = object_utils.MaybePartial
289
- JSONConvertible = object_utils.JSONConvertible
290
- DocStr = object_utils.DocStr
291
+ MaybePartial = utils.MaybePartial
292
+ JSONConvertible = utils.JSONConvertible
293
+ DocStr = utils.DocStr
291
294
 
292
- registered_types = object_utils.registered_types
293
- explicit_method_override = object_utils.explicit_method_override
295
+ registered_types = utils.registered_types
296
+ explicit_method_override = utils.explicit_method_override
294
297
 
295
- is_partial = object_utils.is_partial
296
- format = object_utils.format # pylint: disable=redefined-builtin
297
- print = object_utils.print # pylint: disable=redefined-builtin
298
- docstr = object_utils.docstr
299
- catch_errors = object_utils.catch_errors
300
- timeit = object_utils.timeit
298
+ is_partial = utils.is_partial
299
+ format = utils.format # pylint: disable=redefined-builtin
300
+ print = utils.print # pylint: disable=redefined-builtin
301
+ docstr = utils.docstr
302
+ catch_errors = utils.catch_errors
303
+ timeit = utils.timeit
301
304
 
302
305
  # Symbols from 'views' sub-module.
303
306
 
pyglove/core/geno/base.py CHANGED
@@ -19,9 +19,9 @@ import random
19
19
  import types
20
20
  from typing import Any, Callable, Dict, List, Optional, Tuple, Union
21
21
 
22
- from pyglove.core import object_utils
23
22
  from pyglove.core import symbolic
24
23
  from pyglove.core import typing as pg_typing
24
+ from pyglove.core import utils
25
25
 
26
26
 
27
27
  class AttributeDict(dict):
@@ -37,12 +37,20 @@ class AttributeDict(dict):
37
37
 
38
38
 
39
39
  @symbolic.members([
40
- ('location',
41
- pg_typing.Object(object_utils.KeyPath, default=object_utils.KeyPath()),
42
- ('KeyPath of associated genetic encoder relative to parent object '
43
- 'template. This allows DNA generator to apply rule based on locations.')),
44
- ('hints',
45
- pg_typing.Any(default=None), 'Hints for DNA generator to consume.')
40
+ (
41
+ 'location',
42
+ pg_typing.Object(utils.KeyPath, default=utils.KeyPath()),
43
+ (
44
+ 'KeyPath of associated genetic encoder relative to parent object'
45
+ ' template. This allows DNA generator to apply rule based on'
46
+ ' locations.'
47
+ ),
48
+ ),
49
+ (
50
+ 'hints',
51
+ pg_typing.Any(default=None),
52
+ 'Hints for DNA generator to consume.',
53
+ ),
46
54
  ])
47
55
  class DNASpec(symbolic.Object):
48
56
  """Base class for DNA specifications (genotypes).
@@ -175,7 +183,7 @@ class DNASpec(symbolic.Object):
175
183
  """Returns all decision points in their declaration order."""
176
184
 
177
185
  @property
178
- def decision_ids(self) -> List[object_utils.KeyPath]:
186
+ def decision_ids(self) -> List[utils.KeyPath]:
179
187
  """Returns decision IDs."""
180
188
  return list(self._decision_point_by_id.keys())
181
189
 
@@ -286,7 +294,7 @@ class DNASpec(symbolic.Object):
286
294
  return self.parent_spec if self.is_space else self.parent_spec.parent_choice
287
295
 
288
296
  @property
289
- def id(self) -> object_utils.KeyPath:
297
+ def id(self) -> utils.KeyPath:
290
298
  """Returns a path of locations from the root as the ID for current node."""
291
299
  if self._id is None:
292
300
  parent = self.parent_spec
@@ -295,18 +303,20 @@ class DNASpec(symbolic.Object):
295
303
  elif self.is_space:
296
304
  assert parent.is_categorical, parent
297
305
  assert self.index is not None
298
- self._id = object_utils.KeyPath(
299
- ConditionalKey(self.index, len(parent.candidates)),
300
- parent.id) + self.location
306
+ self._id = (
307
+ utils.KeyPath(
308
+ ConditionalKey(self.index, len(parent.candidates)), parent.id
309
+ )
310
+ + self.location
311
+ )
301
312
  else:
302
313
  # Float() or a multi-choice spec of a parent Choice.
303
314
  self._id = parent.id + self.location
304
315
  return self._id
305
316
 
306
- def get(self,
307
- name_or_id: Union[object_utils.KeyPath, str],
308
- default: Any = None
309
- ) -> Union['DecisionPoint', List['DecisionPoint']]:
317
+ def get(
318
+ self, name_or_id: Union[utils.KeyPath, str], default: Any = None
319
+ ) -> Union['DecisionPoint', List['DecisionPoint']]:
310
320
  """Get decision point(s) by name or ID."""
311
321
  try:
312
322
  return self[name_or_id]
@@ -314,9 +324,8 @@ class DNASpec(symbolic.Object):
314
324
  return default
315
325
 
316
326
  def __getitem__(
317
- self,
318
- name_or_id: Union[object_utils.KeyPath, str]
319
- ) -> Union['DecisionPoint', List['DecisionPoint']]:
327
+ self, name_or_id: Union[utils.KeyPath, str]
328
+ ) -> Union['DecisionPoint', List['DecisionPoint']]:
320
329
  """Get decision point(s) by name or ID ."""
321
330
  v = self._named_decision_points.get(name_or_id, None)
322
331
  if v is None:
@@ -475,7 +484,7 @@ class DNA(symbolic.Object):
475
484
  # Allow assignment on symbolic attributes.
476
485
  allow_symbolic_assignment = True
477
486
 
478
- @object_utils.explicit_method_override
487
+ @utils.explicit_method_override
479
488
  def __init__(
480
489
  self,
481
490
  value: Union[None, int, float, str, List[Any], Tuple[Any]] = None,
@@ -727,7 +736,7 @@ class DNA(symbolic.Object):
727
736
  return self._decision_by_id_cache
728
737
 
729
738
  @property
730
- def decision_ids(self) -> List[object_utils.KeyPath]:
739
+ def decision_ids(self) -> List[utils.KeyPath]:
731
740
  """Returns decision IDs."""
732
741
  self._ensure_dna_spec()
733
742
  return self._spec.decision_ids
@@ -1249,9 +1258,11 @@ class DNA(symbolic.Object):
1249
1258
  return dna
1250
1259
 
1251
1260
  def to_numbers(
1252
- self, flatten: bool = True,
1253
- ) -> Union[List[Union[int, float, str]],
1254
- object_utils.Nestable[Union[int, float, str]]]:
1261
+ self,
1262
+ flatten: bool = True,
1263
+ ) -> Union[
1264
+ List[Union[int, float, str]], utils.Nestable[Union[int, float, str]]
1265
+ ]:
1255
1266
  """Returns a (maybe) nested structure of numbers as decisions.
1256
1267
 
1257
1268
  Args:
@@ -1338,7 +1349,7 @@ class DNA(symbolic.Object):
1338
1349
  f'Location: {dna_spec.location.path}.')
1339
1350
  children = []
1340
1351
  for i, choice in enumerate(decision):
1341
- choice_location = object_utils.KeyPath(i, dna_spec.location)
1352
+ choice_location = utils.KeyPath(i, dna_spec.location)
1342
1353
  if not isinstance(choice, int):
1343
1354
  raise ValueError(
1344
1355
  f'Choice value should be int. Encountered: {choice}, '
@@ -1410,7 +1421,7 @@ class DNA(symbolic.Object):
1410
1421
 
1411
1422
  if type_info:
1412
1423
  json_value = {
1413
- object_utils.JSONConvertible.TYPE_NAME_KEY: (
1424
+ utils.JSONConvertible.TYPE_NAME_KEY: (
1414
1425
  self.__class__.__serialization_key__
1415
1426
  ),
1416
1427
  'format': 'compact',
@@ -1435,7 +1446,8 @@ class DNA(symbolic.Object):
1435
1446
  json_value: Dict[str, Any],
1436
1447
  *,
1437
1448
  allow_partial: bool = False,
1438
- root_path: Optional[object_utils.KeyPath] = None) -> 'DNA':
1449
+ root_path: Optional[utils.KeyPath] = None,
1450
+ ) -> 'DNA':
1439
1451
  """Class method that load a DNA from a JSON value.
1440
1452
 
1441
1453
  Args:
@@ -1472,8 +1484,8 @@ class DNA(symbolic.Object):
1472
1484
  return not self.children
1473
1485
 
1474
1486
  def __getitem__(
1475
- self, key: Union[int, slice, str, object_utils.KeyPath, 'DecisionPoint']
1476
- ) -> Union[None, 'DNA', List[Optional['DNA']]]:
1487
+ self, key: Union[int, slice, str, utils.KeyPath, 'DecisionPoint']
1488
+ ) -> Union[None, 'DNA', List[Optional['DNA']]]:
1477
1489
  """Get an immediate child DNA or DNA in the sub-tree.
1478
1490
 
1479
1491
  Args:
@@ -1504,10 +1516,11 @@ class DNA(symbolic.Object):
1504
1516
  v = self._decision_by_id[key]
1505
1517
  return v
1506
1518
 
1507
- def get(self,
1508
- key: Union[int, slice, str, object_utils.KeyPath, 'DecisionPoint'],
1509
- default: Any = None
1510
- ) -> Union[Any, None, 'DNA', List[Optional['DNA']]]:
1519
+ def get(
1520
+ self,
1521
+ key: Union[int, slice, str, utils.KeyPath, 'DecisionPoint'],
1522
+ default: Any = None,
1523
+ ) -> Union[Any, None, 'DNA', List[Optional['DNA']]]:
1511
1524
  """Get an immediate child DNA or DNA in the sub-tree."""
1512
1525
  try:
1513
1526
  return self[key]
@@ -1529,8 +1542,9 @@ class DNA(symbolic.Object):
1529
1542
  return True
1530
1543
  else:
1531
1544
  raise ValueError(
1532
- f'DNA.__contains__ does not accept '
1533
- f'{object_utils.quote_if_str(dna_or_value)!r}.')
1545
+ 'DNA.__contains__ does not accept '
1546
+ f'{utils.quote_if_str(dna_or_value)!r}.'
1547
+ )
1534
1548
  return False
1535
1549
 
1536
1550
  def __hash__(self):
@@ -1605,12 +1619,13 @@ class DNA(symbolic.Object):
1605
1619
  ):
1606
1620
  """Customize format method for DNA for more compact representation."""
1607
1621
  if as_dict and self.spec:
1608
- details = object_utils.format(
1622
+ details = utils.format(
1609
1623
  self.to_dict(value_type='choice_and_literal'),
1610
1624
  False,
1611
1625
  verbose,
1612
1626
  root_indent,
1613
- **kwargs)
1627
+ **kwargs,
1628
+ )
1614
1629
  s = f'DNA({details})'
1615
1630
  else:
1616
1631
  if 'list_wrap_threshold' not in kwargs:
@@ -1621,7 +1636,7 @@ class DNA(symbolic.Object):
1621
1636
  elif self.is_leaf:
1622
1637
  s = f'DNA({self.value!r})'
1623
1638
  else:
1624
- rep = object_utils.format(
1639
+ rep = utils.format(
1625
1640
  self.to_json(compact=True, type_info=False),
1626
1641
  compact,
1627
1642
  verbose,
@@ -11,12 +11,10 @@
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.geno.DNA."""
15
-
16
14
  import unittest
17
15
 
18
- from pyglove.core import object_utils
19
16
  from pyglove.core import symbolic
17
+ from pyglove.core import utils
20
18
  from pyglove.core.geno.base import ConditionalKey
21
19
  from pyglove.core.geno.base import DNA
22
20
  from pyglove.core.geno.categorical import manyof
@@ -1144,7 +1142,7 @@ class ConditionalKeyTest(unittest.TestCase):
1144
1142
  self.assertEqual(key.num_choices, 5)
1145
1143
 
1146
1144
  def test_to_str(self):
1147
- key = object_utils.KeyPath(['a', ConditionalKey(1, 5), 'b'])
1145
+ key = utils.KeyPath(['a', ConditionalKey(1, 5), 'b'])
1148
1146
  self.assertEqual(str(key), 'a[=1/5].b')
1149
1147
 
1150
1148
 
@@ -18,10 +18,9 @@ import re
18
18
  import types
19
19
  from typing import Any, List, Optional, Union
20
20
 
21
- from pyglove.core import object_utils
22
21
  from pyglove.core import symbolic
23
22
  from pyglove.core import typing as pg_typing
24
-
23
+ from pyglove.core import utils
25
24
  from pyglove.core.geno.base import DecisionPoint
26
25
  from pyglove.core.geno.base import DNA
27
26
  from pyglove.core.geno.base import DNASpec
@@ -139,14 +138,15 @@ class Choices(DecisionPoint):
139
138
  for i in range(self.num_choices):
140
139
  subchoice_spec = Choices(
141
140
  subchoice_index=i,
142
- location=object_utils.KeyPath(i),
141
+ location=utils.KeyPath(i),
143
142
  num_choices=1,
144
143
  candidates=self.candidates,
145
144
  literal_values=self.literal_values,
146
145
  distinct=self.distinct,
147
146
  sorted=self.sorted,
148
147
  name=self.name,
149
- hints=self.hints)
148
+ hints=self.hints,
149
+ )
150
150
  self._decision_points.extend(subchoice_spec.decision_points)
151
151
  subchoice_specs.append(subchoice_spec)
152
152
  self._subchoice_specs = symbolic.List(subchoice_specs)
@@ -158,7 +158,8 @@ class Choices(DecisionPoint):
158
158
  self._decision_points.extend(c.decision_points)
159
159
 
160
160
  def _update_children_paths(
161
- self, old_path: object_utils.KeyPath, new_path: object_utils.KeyPath):
161
+ self, old_path: utils.KeyPath, new_path: utils.KeyPath
162
+ ):
162
163
  """Trigger path change for subchoices so their IDs can be invalidated."""
163
164
  super()._update_children_paths(old_path, new_path)
164
165
  if self._subchoice_specs:
@@ -337,7 +338,7 @@ class Choices(DecisionPoint):
337
338
  f'DNA child values should be sorted. '
338
339
  f'Encountered: {sub_dna_values}, Location: {self.location.path}.')
339
340
  for i, sub_dna in enumerate(dna):
340
- sub_location = object_utils.KeyPath(i, self.location)
341
+ sub_location = utils.KeyPath(i, self.location)
341
342
  if not isinstance(sub_dna.value, int):
342
343
  raise ValueError(
343
344
  f'Choice value should be int. Encountered: {sub_dna.value}, '
@@ -601,13 +602,18 @@ class Choices(DecisionPoint):
601
602
  kvlist = [('id', str(self.id), '\'\'')]
602
603
  else:
603
604
  kvlist = []
604
- additionl_properties = object_utils.kvlist_str(kvlist + [
605
- ('name', self.name, None),
606
- ('distinct', self.distinct, True),
607
- ('sorted', self.sorted, False),
608
- ('hints', self.hints, None),
609
- ('subchoice_index', self.subchoice_index, None)
610
- ], compact=False, root_indent=root_indent)
605
+ additionl_properties = utils.kvlist_str(
606
+ kvlist
607
+ + [
608
+ ('name', self.name, None),
609
+ ('distinct', self.distinct, True),
610
+ ('sorted', self.sorted, False),
611
+ ('hints', self.hints, None),
612
+ ('subchoice_index', self.subchoice_index, None),
613
+ ],
614
+ compact=False,
615
+ root_indent=root_indent,
616
+ )
611
617
  if additionl_properties:
612
618
  s.append(', ')
613
619
  s.append(additionl_properties)
@@ -615,14 +621,16 @@ class Choices(DecisionPoint):
615
621
  return ''.join(s)
616
622
 
617
623
 
618
- def manyof(num_choices: int,
619
- candidates: List[DNASpec],
620
- distinct: bool = True,
621
- sorted: bool = False, # pylint: disable=redefined-builtin
622
- literal_values: Optional[List[Union[str, int, float]]] = None,
623
- hints: Any = None,
624
- location: Union[str, object_utils.KeyPath] = object_utils.KeyPath(),
625
- name: Optional[str] = None) -> Choices:
624
+ def manyof(
625
+ num_choices: int,
626
+ candidates: List[DNASpec],
627
+ distinct: bool = True,
628
+ sorted: bool = False, # pylint: disable=redefined-builtin
629
+ literal_values: Optional[List[Union[str, int, float]]] = None,
630
+ hints: Any = None,
631
+ location: Union[str, utils.KeyPath] = utils.KeyPath(),
632
+ name: Optional[str] = None,
633
+ ) -> Choices:
626
634
  """Returns a multi-choice specification.
627
635
 
628
636
  It creates the genotype for :func:`pyglove.manyof`.
@@ -674,11 +682,13 @@ def manyof(num_choices: int,
674
682
  hints=hints, location=location, name=name)
675
683
 
676
684
 
677
- def oneof(candidates: List[DNASpec],
678
- literal_values: Optional[List[Union[str, int, float]]] = None,
679
- hints: Any = None,
680
- location: Union[str, object_utils.KeyPath] = object_utils.KeyPath(),
681
- name: Optional[str] = None) -> Choices:
685
+ def oneof(
686
+ candidates: List[DNASpec],
687
+ literal_values: Optional[List[Union[str, int, float]]] = None,
688
+ hints: Any = None,
689
+ location: Union[str, utils.KeyPath] = utils.KeyPath(),
690
+ name: Optional[str] = None,
691
+ ) -> Choices:
682
692
  """Returns a single choice specification.
683
693
 
684
694
  It creates the genotype for :func:`pyglove.oneof`.
@@ -716,4 +726,3 @@ def oneof(candidates: List[DNASpec],
716
726
  """
717
727
  return manyof(1, candidates, literal_values=literal_values,
718
728
  hints=hints, location=location, name=name)
719
-
@@ -17,10 +17,9 @@ import random
17
17
  import types
18
18
  from typing import Any, Callable, List, Optional, Union
19
19
 
20
- from pyglove.core import object_utils
21
20
  from pyglove.core import symbolic
22
21
  from pyglove.core import typing as pg_typing
23
-
22
+ from pyglove.core import utils
24
23
  from pyglove.core.geno.base import DecisionPoint
25
24
  from pyglove.core.geno.base import DNA
26
25
 
@@ -125,7 +124,7 @@ class CustomDecisionPoint(DecisionPoint):
125
124
  f'CustomDecisionPoint expects string type DNA. '
126
125
  f'Encountered: {dna!r}, Location: {self.location.path}.')
127
126
 
128
- def sym_jsonify(self, **kwargs: Any) -> object_utils.JSONValueType:
127
+ def sym_jsonify(self, **kwargs: Any) -> utils.JSONValueType:
129
128
  """Overrides sym_jsonify to exclude non-serializable fields."""
130
129
  exclude_keys = kwargs.pop('exclude_keys', [])
131
130
  exclude_keys.extend(['random_dna_fn', 'next_dna_fn'])
@@ -153,21 +152,25 @@ class CustomDecisionPoint(DecisionPoint):
153
152
  kvlist = [('id', str(self.id), '\'\'')]
154
153
  else:
155
154
  kvlist = []
156
- details = object_utils.kvlist_str(kvlist + [
157
- ('hyper_type', self.hyper_type, None),
158
- ('name', self.name, None),
159
- ('hints', self.hints, None),
160
- ])
155
+ details = utils.kvlist_str(
156
+ kvlist
157
+ + [
158
+ ('hyper_type', self.hyper_type, None),
159
+ ('name', self.name, None),
160
+ ('hints', self.hints, None),
161
+ ]
162
+ )
161
163
  return f'{self.__class__.__name__}({details})'
162
164
 
163
165
 
164
- def custom(hyper_type: Optional[str] = None,
165
- next_dna_fn: Optional[
166
- Callable[[Optional[DNA]], Optional[DNA]]] = None,
167
- random_dna_fn: Optional[Callable[[Any], DNA]] = None,
168
- hints: Any = None,
169
- location: object_utils.KeyPath = object_utils.KeyPath(),
170
- name: Optional[str] = None) -> CustomDecisionPoint:
166
+ def custom(
167
+ hyper_type: Optional[str] = None,
168
+ next_dna_fn: Optional[Callable[[Optional[DNA]], Optional[DNA]]] = None,
169
+ random_dna_fn: Optional[Callable[[Any], DNA]] = None,
170
+ hints: Any = None,
171
+ location: utils.KeyPath = utils.KeyPath(),
172
+ name: Optional[str] = None,
173
+ ) -> CustomDecisionPoint:
171
174
  """Returns a custom decision point.
172
175
 
173
176
  It creates the genotype for subclasses of :func:`pyglove.hyper.CustomHyper`.
@@ -17,10 +17,9 @@ import random
17
17
  import types
18
18
  from typing import Any, List, Optional, Union
19
19
 
20
- from pyglove.core import object_utils
21
20
  from pyglove.core import symbolic
22
21
  from pyglove.core import typing as pg_typing
23
-
22
+ from pyglove.core import utils
24
23
  from pyglove.core.geno.base import DecisionPoint
25
24
  from pyglove.core.geno.base import DNA
26
25
 
@@ -167,22 +166,27 @@ class Float(DecisionPoint):
167
166
  kvlist = [('id', str(self.id), '\'\'')]
168
167
  else:
169
168
  kvlist = []
170
- details = object_utils.kvlist_str(kvlist + [
171
- ('name', self.name, None),
172
- ('min_value', self.min_value, None),
173
- ('max_value', self.max_value, None),
174
- ('scale', self.scale, None),
175
- ('hints', self.hints, None),
176
- ])
169
+ details = utils.kvlist_str(
170
+ kvlist
171
+ + [
172
+ ('name', self.name, None),
173
+ ('min_value', self.min_value, None),
174
+ ('max_value', self.max_value, None),
175
+ ('scale', self.scale, None),
176
+ ('hints', self.hints, None),
177
+ ]
178
+ )
177
179
  return f'{self.__class__.__name__}({details})'
178
180
 
179
181
 
180
- def floatv(min_value: float,
181
- max_value: float,
182
- scale: Optional[str] = None,
183
- hints: Any = None,
184
- location: object_utils.KeyPath = object_utils.KeyPath(),
185
- name: Optional[str] = None) -> Float:
182
+ def floatv(
183
+ min_value: float,
184
+ max_value: float,
185
+ scale: Optional[str] = None,
186
+ hints: Any = None,
187
+ location: utils.KeyPath = utils.KeyPath(),
188
+ name: Optional[str] = None,
189
+ ) -> Float:
186
190
  """Returns a Float specification.
187
191
 
188
192
  It creates the genotype for :func:`pyglove.floatv`.
@@ -226,4 +230,3 @@ def floatv(min_value: float,
226
230
  """
227
231
  return Float(min_value, max_value, scale,
228
232
  hints=hints, location=location, name=name)
229
-
@@ -18,10 +18,9 @@ import random
18
18
  import types
19
19
  from typing import List, Optional, Union
20
20
 
21
- from pyglove.core import object_utils
22
21
  from pyglove.core import symbolic
23
22
  from pyglove.core import typing as pg_typing
24
-
23
+ from pyglove.core import utils
25
24
  from pyglove.core.geno.base import DecisionPoint
26
25
  from pyglove.core.geno.base import DNA
27
26
  from pyglove.core.geno.base import DNASpec
@@ -231,8 +230,8 @@ class Space(DNASpec):
231
230
  return sum([len(elem) for elem in self.elements])
232
231
 
233
232
  def __getitem__(
234
- self, index: Union[int, slice, str, object_utils.KeyPath]
235
- ) -> Union[DecisionPoint, List[DecisionPoint]]:
233
+ self, index: Union[int, slice, str, utils.KeyPath]
234
+ ) -> Union[DecisionPoint, List[DecisionPoint]]:
236
235
  """Operator [] to return element by index or sub-DNASpec by name."""
237
236
  if isinstance(index, (int, slice)):
238
237
  return self.elements[index]
@@ -18,9 +18,9 @@ import abc
18
18
  from typing import Any, Callable, Optional
19
19
 
20
20
  from pyglove.core import geno
21
- from pyglove.core import object_utils
22
21
  from pyglove.core import symbolic
23
22
  from pyglove.core import typing as pg_typing
23
+ from pyglove.core import utils
24
24
 
25
25
 
26
26
  class HyperValue(symbolic.NonDeterministic): # pytype: disable=ignored-metaclass
@@ -110,8 +110,7 @@ class HyperValue(symbolic.NonDeterministic): # pytype: disable=ignored-metaclas
110
110
  """
111
111
 
112
112
  @abc.abstractmethod
113
- def dna_spec(self,
114
- location: Optional[object_utils.KeyPath] = None) -> geno.DNASpec:
113
+ def dna_spec(self, location: Optional[utils.KeyPath] = None) -> geno.DNASpec:
115
114
  """Get DNA spec of DNA that is decodable/encodable by this hyper value."""
116
115
 
117
116
 
@@ -186,12 +185,13 @@ def set_dynamic_evaluate_fn(
186
185
  global _global_dynamic_evaluate_fn
187
186
  if per_thread:
188
187
  assert _global_dynamic_evaluate_fn is None, _global_dynamic_evaluate_fn
189
- object_utils.thread_local_set(_TLS_KEY_DYNAMIC_EVALUATE_FN, fn)
188
+ utils.thread_local_set(_TLS_KEY_DYNAMIC_EVALUATE_FN, fn)
190
189
  else:
191
190
  _global_dynamic_evaluate_fn = fn
192
191
 
193
192
 
194
193
  def get_dynamic_evaluate_fn() -> Optional[Callable[[HyperValue], Any]]:
195
194
  """Gets current dynamic evaluate function."""
196
- return object_utils.thread_local_get(
197
- _TLS_KEY_DYNAMIC_EVALUATE_FN, _global_dynamic_evaluate_fn)
195
+ return utils.thread_local_get(
196
+ _TLS_KEY_DYNAMIC_EVALUATE_FN, _global_dynamic_evaluate_fn
197
+ )