pyglove 0.4.5.dev202411132359__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.
- pyglove/core/__init__.py +40 -21
- pyglove/core/coding/__init__.py +42 -0
- pyglove/core/coding/errors.py +111 -0
- pyglove/core/coding/errors_test.py +98 -0
- pyglove/core/coding/execution.py +312 -0
- pyglove/core/coding/execution_test.py +333 -0
- pyglove/core/{object_utils/codegen.py → coding/function_generation.py} +10 -4
- pyglove/core/{object_utils/codegen_test.py → coding/function_generation_test.py} +5 -7
- pyglove/core/coding/parsing.py +153 -0
- pyglove/core/coding/parsing_test.py +150 -0
- pyglove/core/coding/permissions.py +100 -0
- pyglove/core/coding/permissions_test.py +93 -0
- pyglove/core/geno/base.py +53 -38
- pyglove/core/geno/base_test.py +2 -4
- pyglove/core/geno/categorical.py +36 -27
- pyglove/core/geno/custom.py +18 -15
- pyglove/core/geno/numerical.py +19 -16
- pyglove/core/geno/space.py +3 -4
- pyglove/core/hyper/base.py +6 -6
- pyglove/core/hyper/categorical.py +91 -52
- pyglove/core/hyper/custom.py +7 -7
- pyglove/core/hyper/custom_test.py +9 -10
- pyglove/core/hyper/derived.py +30 -22
- pyglove/core/hyper/derived_test.py +3 -5
- pyglove/core/hyper/dynamic_evaluation.py +3 -4
- pyglove/core/hyper/evolvable.py +57 -46
- pyglove/core/hyper/numerical.py +48 -24
- pyglove/core/hyper/numerical_test.py +9 -9
- pyglove/core/hyper/object_template.py +58 -46
- pyglove/core/logging_test.py +0 -2
- pyglove/core/patching/object_factory.py +4 -4
- pyglove/core/patching/pattern_based.py +4 -4
- pyglove/core/patching/rule_based.py +4 -3
- pyglove/core/symbolic/__init__.py +4 -0
- pyglove/core/symbolic/base.py +200 -136
- pyglove/core/symbolic/base_test.py +17 -19
- pyglove/core/symbolic/boilerplate.py +4 -5
- pyglove/core/symbolic/class_wrapper.py +10 -14
- pyglove/core/symbolic/class_wrapper_test.py +2 -2
- pyglove/core/symbolic/compounding.py +2 -2
- pyglove/core/symbolic/compounding_test.py +2 -4
- pyglove/core/symbolic/contextual_object.py +288 -0
- pyglove/core/symbolic/contextual_object_test.py +327 -0
- pyglove/core/symbolic/dict.py +115 -87
- pyglove/core/symbolic/dict_test.py +188 -131
- pyglove/core/symbolic/diff.py +12 -12
- pyglove/core/symbolic/flags.py +1 -1
- pyglove/core/symbolic/functor.py +16 -15
- pyglove/core/symbolic/functor_test.py +2 -4
- pyglove/core/symbolic/inferred.py +2 -2
- pyglove/core/symbolic/list.py +70 -47
- pyglove/core/symbolic/list_test.py +117 -98
- pyglove/core/symbolic/object.py +59 -58
- pyglove/core/symbolic/object_test.py +143 -90
- pyglove/core/symbolic/origin.py +5 -7
- pyglove/core/symbolic/pure_symbolic.py +4 -3
- pyglove/core/symbolic/ref.py +33 -16
- pyglove/core/symbolic/ref_test.py +17 -0
- pyglove/core/tuning/local_backend.py +2 -2
- pyglove/core/tuning/protocols.py +3 -3
- pyglove/core/typing/annotation_conversion.py +8 -3
- pyglove/core/typing/annotation_conversion_test.py +8 -0
- pyglove/core/typing/callable_ext.py +11 -13
- pyglove/core/typing/callable_signature.py +22 -19
- pyglove/core/typing/callable_signature_test.py +3 -5
- pyglove/core/typing/class_schema.py +93 -54
- pyglove/core/typing/class_schema_test.py +4 -5
- pyglove/core/typing/custom_typing.py +5 -4
- pyglove/core/typing/key_specs.py +5 -7
- pyglove/core/typing/key_specs_test.py +4 -4
- pyglove/core/typing/type_conversion.py +4 -5
- pyglove/core/typing/type_conversion_test.py +12 -12
- pyglove/core/typing/typed_missing.py +6 -7
- pyglove/core/typing/typed_missing_test.py +7 -8
- pyglove/core/typing/value_specs.py +287 -144
- pyglove/core/typing/value_specs_test.py +148 -25
- pyglove/core/utils/__init__.py +172 -0
- pyglove/core/{object_utils → utils}/common_traits.py +2 -2
- pyglove/core/{object_utils → utils}/common_traits_test.py +1 -3
- pyglove/core/utils/contextual.py +147 -0
- pyglove/core/utils/contextual_test.py +88 -0
- pyglove/core/{object_utils → utils}/docstr_utils_test.py +1 -3
- pyglove/core/{object_utils → utils}/error_utils.py +3 -3
- pyglove/core/{object_utils → utils}/error_utils_test.py +1 -1
- pyglove/core/{object_utils → utils}/formatting.py +1 -1
- pyglove/core/{object_utils → utils}/formatting_test.py +1 -2
- pyglove/core/{object_utils → utils}/hierarchical.py +23 -25
- pyglove/core/{object_utils → utils}/hierarchical_test.py +3 -5
- pyglove/core/{object_utils → utils}/json_conversion.py +1 -1
- pyglove/core/{object_utils → utils}/json_conversion_test.py +1 -3
- pyglove/core/{object_utils → utils}/missing.py +2 -2
- pyglove/core/{object_utils → utils}/missing_test.py +2 -4
- pyglove/core/utils/text_color.py +128 -0
- pyglove/core/utils/text_color_test.py +94 -0
- pyglove/core/{object_utils → utils}/thread_local_test.py +1 -3
- pyglove/core/{object_utils → utils}/timing.py +21 -10
- pyglove/core/{object_utils → utils}/timing_test.py +14 -12
- pyglove/core/{object_utils → utils}/value_location.py +2 -2
- pyglove/core/{object_utils → utils}/value_location_test.py +2 -4
- pyglove/core/views/base.py +25 -29
- pyglove/core/views/html/base.py +15 -16
- pyglove/core/views/html/controls/base.py +46 -9
- pyglove/core/views/html/controls/label.py +13 -2
- pyglove/core/views/html/controls/label_test.py +27 -8
- pyglove/core/views/html/controls/progress_bar.py +3 -5
- pyglove/core/views/html/controls/progress_bar_test.py +2 -2
- pyglove/core/views/html/controls/tab.py +217 -66
- pyglove/core/views/html/controls/tab_test.py +46 -15
- pyglove/core/views/html/tree_view.py +39 -37
- {pyglove-0.4.5.dev202411132359.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/METADATA +17 -3
- pyglove-0.4.5.dev202501250807.dist-info/RECORD +218 -0
- {pyglove-0.4.5.dev202411132359.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/WHEEL +1 -1
- pyglove/core/object_utils/__init__.py +0 -164
- pyglove-0.4.5.dev202411132359.dist-info/RECORD +0 -203
- /pyglove/core/{object_utils → utils}/docstr_utils.py +0 -0
- /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
- {pyglove-0.4.5.dev202411132359.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev202411132359.dist-info → pyglove-0.4.5.dev202501250807.dist-info}/top_level.txt +0 -0
pyglove/core/symbolic/dict.py
CHANGED
@@ -16,8 +16,8 @@
|
|
16
16
|
import typing
|
17
17
|
from typing import Any, Callable, Iterable, Iterator, List, Optional, Sequence, Set, Tuple, Union
|
18
18
|
|
19
|
-
from pyglove.core import object_utils
|
20
19
|
from pyglove.core import typing as pg_typing
|
20
|
+
from pyglove.core import utils
|
21
21
|
from pyglove.core.symbolic import base
|
22
22
|
from pyglove.core.symbolic import flags
|
23
23
|
|
@@ -96,14 +96,16 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
96
96
|
"""
|
97
97
|
|
98
98
|
@classmethod
|
99
|
-
def partial(
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
99
|
+
def partial(
|
100
|
+
cls,
|
101
|
+
dict_obj: Optional[typing.Dict[Union[str, int], Any]] = None,
|
102
|
+
value_spec: Optional[pg_typing.Dict] = None,
|
103
|
+
*,
|
104
|
+
onchange_callback: Optional[
|
105
|
+
Callable[[typing.Dict[utils.KeyPath, base.FieldUpdate]], None]
|
106
|
+
] = None, # pylint: disable=bad-continuation
|
107
|
+
**kwargs,
|
108
|
+
) -> 'Dict':
|
107
109
|
"""Class method that creates a partial Dict object."""
|
108
110
|
return cls(dict_obj,
|
109
111
|
value_spec=value_spec,
|
@@ -112,13 +114,15 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
112
114
|
**kwargs)
|
113
115
|
|
114
116
|
@classmethod
|
115
|
-
def from_json(
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
117
|
+
def from_json(
|
118
|
+
cls,
|
119
|
+
json_value: Any,
|
120
|
+
*,
|
121
|
+
value_spec: Optional[pg_typing.Dict] = None,
|
122
|
+
allow_partial: bool = False,
|
123
|
+
root_path: Optional[utils.KeyPath] = None,
|
124
|
+
**kwargs,
|
125
|
+
) -> 'Dict':
|
122
126
|
"""Class method that load an symbolic Dict from a JSON value.
|
123
127
|
|
124
128
|
Args:
|
@@ -156,27 +160,31 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
156
160
|
{
|
157
161
|
k: base.from_json(
|
158
162
|
v,
|
159
|
-
root_path=
|
163
|
+
root_path=utils.KeyPath(k, root_path),
|
160
164
|
allow_partial=allow_partial,
|
161
|
-
**kwargs
|
162
|
-
)
|
165
|
+
**kwargs,
|
166
|
+
)
|
167
|
+
for k, v in json_value.items()
|
163
168
|
},
|
164
169
|
value_spec=value_spec,
|
165
170
|
root_path=root_path,
|
166
171
|
allow_partial=allow_partial,
|
167
172
|
)
|
168
173
|
|
169
|
-
def __init__(
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
174
|
+
def __init__(
|
175
|
+
self,
|
176
|
+
dict_obj: Union[
|
177
|
+
None,
|
178
|
+
Iterable[Tuple[Union[str, int], Any]],
|
179
|
+
typing.Dict[Union[str, int], Any],
|
180
|
+
] = None,
|
181
|
+
*,
|
182
|
+
value_spec: Optional[pg_typing.Dict] = None,
|
183
|
+
onchange_callback: Optional[
|
184
|
+
Callable[[typing.Dict[utils.KeyPath, base.FieldUpdate]], None]
|
185
|
+
] = None, # pylint: disable=bad-continuation
|
186
|
+
**kwargs,
|
187
|
+
):
|
180
188
|
"""Constructor.
|
181
189
|
|
182
190
|
Args:
|
@@ -335,8 +343,8 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
335
343
|
return self
|
336
344
|
|
337
345
|
def _sym_rebind(
|
338
|
-
self, path_value_pairs: typing.Dict[
|
339
|
-
|
346
|
+
self, path_value_pairs: typing.Dict[utils.KeyPath, Any]
|
347
|
+
) -> List[base.FieldUpdate]:
|
340
348
|
"""Subclass specific rebind implementation."""
|
341
349
|
updates = []
|
342
350
|
for k, v in path_value_pairs.items():
|
@@ -345,7 +353,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
345
353
|
updates.append(update)
|
346
354
|
return updates
|
347
355
|
|
348
|
-
def _sym_missing(self) -> typing.Dict[str, Any]:
|
356
|
+
def _sym_missing(self) -> typing.Dict[Union[str, int], Any]:
|
349
357
|
"""Returns missing values.
|
350
358
|
|
351
359
|
Returns:
|
@@ -360,7 +368,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
360
368
|
if keys:
|
361
369
|
for key in keys:
|
362
370
|
v = self.sym_getattr(key)
|
363
|
-
if
|
371
|
+
if utils.MISSING_VALUE == v:
|
364
372
|
missing[key] = field.value.default
|
365
373
|
else:
|
366
374
|
if isinstance(v, base.Symbolic):
|
@@ -375,7 +383,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
375
383
|
missing[k] = missing_child
|
376
384
|
return missing
|
377
385
|
|
378
|
-
def _sym_nondefault(self) -> typing.Dict[str, Any]:
|
386
|
+
def _sym_nondefault(self) -> typing.Dict[Union[str, int], Any]:
|
379
387
|
"""Returns non-default values as key/value pairs in a dict."""
|
380
388
|
non_defaults = dict()
|
381
389
|
if self._value_spec is not None and self._value_spec.schema:
|
@@ -444,7 +452,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
444
452
|
"""Tests if a symbolic attribute exists."""
|
445
453
|
return key in self
|
446
454
|
|
447
|
-
def sym_keys(self) -> Iterator[str]:
|
455
|
+
def sym_keys(self) -> Iterator[Union[str, int]]:
|
448
456
|
"""Iterates the keys of symbolic attributes."""
|
449
457
|
if self._value_spec is None or self._value_spec.schema is None:
|
450
458
|
for key in super().__iter__():
|
@@ -467,7 +475,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
467
475
|
yield self._sym_getattr(k)
|
468
476
|
|
469
477
|
def sym_items(self) -> Iterator[
|
470
|
-
Tuple[str, Any]]:
|
478
|
+
Tuple[Union[str, int], Any]]:
|
471
479
|
"""Iterates the (key, value) pairs of symbolic attributes."""
|
472
480
|
for k in self.sym_keys():
|
473
481
|
yield k, self._sym_getattr(k)
|
@@ -490,7 +498,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
490
498
|
if v != pg_typing.MISSING_VALUE])))
|
491
499
|
|
492
500
|
def _sym_getattr( # pytype: disable=signature-mismatch # overriding-parameter-type-checks
|
493
|
-
self, key: str) -> Any:
|
501
|
+
self, key: Union[str, int]) -> Any:
|
494
502
|
"""Gets symbolic attribute by key."""
|
495
503
|
return super().__getitem__(key)
|
496
504
|
|
@@ -514,21 +522,20 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
514
522
|
pass_through=True)
|
515
523
|
|
516
524
|
def _update_children_paths(
|
517
|
-
self,
|
518
|
-
|
519
|
-
new_path: object_utils.KeyPath) -> None:
|
525
|
+
self, old_path: utils.KeyPath, new_path: utils.KeyPath
|
526
|
+
) -> None:
|
520
527
|
"""Update children paths according to root_path of current node."""
|
521
528
|
del old_path
|
522
529
|
for k, v in self.sym_items():
|
523
530
|
if isinstance(v, base.TopologyAware):
|
524
|
-
v.sym_setpath(
|
531
|
+
v.sym_setpath(utils.KeyPath(k, new_path))
|
525
532
|
|
526
533
|
def _set_item_without_permission_check( # pytype: disable=signature-mismatch # overriding-parameter-type-checks
|
527
|
-
self, key: str, value: Any) -> Optional[base.FieldUpdate]:
|
534
|
+
self, key: Union[str, int], value: Any) -> Optional[base.FieldUpdate]:
|
528
535
|
"""Set item without permission check."""
|
529
|
-
if not isinstance(key, str):
|
536
|
+
if not isinstance(key, (str, int)):
|
530
537
|
raise KeyError(self._error_message(
|
531
|
-
f'Key must be string type. Encountered {key!r}.'))
|
538
|
+
f'Key must be string or int type. Encountered {key!r}.'))
|
532
539
|
|
533
540
|
old_value = self.get(key, pg_typing.MISSING_VALUE)
|
534
541
|
if old_value is value:
|
@@ -545,12 +552,12 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
545
552
|
container_cls = self.__class__
|
546
553
|
raise KeyError(
|
547
554
|
self._error_message(
|
548
|
-
f'Key
|
555
|
+
f'Key {key!r} is not allowed for {container_cls}.'))
|
549
556
|
|
550
557
|
# Detach old value from object tree.
|
551
558
|
if isinstance(old_value, base.TopologyAware):
|
552
559
|
old_value.sym_setparent(None)
|
553
|
-
old_value.sym_setpath(
|
560
|
+
old_value.sym_setpath(utils.KeyPath())
|
554
561
|
|
555
562
|
if (pg_typing.MISSING_VALUE == value and
|
556
563
|
(not field or isinstance(field.key, pg_typing.NonConstKey))):
|
@@ -575,9 +582,11 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
575
582
|
return base.FieldUpdate(
|
576
583
|
self.sym_path + key, target, field, old_value, new_value)
|
577
584
|
|
578
|
-
def _formalized_value(
|
579
|
-
|
580
|
-
|
585
|
+
def _formalized_value(
|
586
|
+
self, name: Union[str, int],
|
587
|
+
field: Optional[pg_typing.Field],
|
588
|
+
value: Any
|
589
|
+
) -> Any:
|
581
590
|
"""Get transformed (formal) value from user input."""
|
582
591
|
allow_partial = base.accepts_partial(self)
|
583
592
|
if field and pg_typing.MISSING_VALUE == value:
|
@@ -587,13 +596,15 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
587
596
|
value = base.from_json(
|
588
597
|
value,
|
589
598
|
allow_partial=allow_partial,
|
590
|
-
root_path=
|
599
|
+
root_path=utils.KeyPath(name, self.sym_path),
|
600
|
+
)
|
591
601
|
if field and flags.is_type_check_enabled():
|
592
602
|
value = field.apply(
|
593
603
|
value,
|
594
604
|
allow_partial=allow_partial,
|
595
605
|
transform_fn=base.symbolic_transform_fn(self._allow_partial),
|
596
|
-
root_path=
|
606
|
+
root_path=utils.KeyPath(name, self.sym_path),
|
607
|
+
)
|
597
608
|
return self._relocate_if_symbolic(name, value)
|
598
609
|
|
599
610
|
@property
|
@@ -601,8 +612,9 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
601
612
|
"""Returns True if current dict subscribes field updates."""
|
602
613
|
return self._onchange_callback is not None
|
603
614
|
|
604
|
-
def _on_change(
|
605
|
-
|
615
|
+
def _on_change(
|
616
|
+
self, field_updates: typing.Dict[utils.KeyPath, base.FieldUpdate]
|
617
|
+
):
|
606
618
|
"""On change event of Dict."""
|
607
619
|
if self._onchange_callback:
|
608
620
|
self._onchange_callback(field_updates)
|
@@ -625,14 +637,14 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
625
637
|
"""Customizes pickle.load."""
|
626
638
|
self.__init__(state['value'], **state['kwargs'])
|
627
639
|
|
628
|
-
def __getitem__(self, key: str) -> Any:
|
640
|
+
def __getitem__(self, key: Union[str, int]) -> Any:
|
629
641
|
"""Get item in this Dict."""
|
630
642
|
try:
|
631
643
|
return self.sym_inferred(key)
|
632
644
|
except AttributeError as e:
|
633
645
|
raise KeyError(key) from e
|
634
646
|
|
635
|
-
def __setitem__(self, key: str, value: Any) -> None:
|
647
|
+
def __setitem__(self, key: Union[str, int], value: Any) -> None:
|
636
648
|
"""Set item in this Dict.
|
637
649
|
|
638
650
|
Args:
|
@@ -733,11 +745,11 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
733
745
|
"""Iterate keys in field declaration order."""
|
734
746
|
return self.sym_keys()
|
735
747
|
|
736
|
-
def keys(self) -> Iterator[str]: # pytype: disable=signature-mismatch
|
748
|
+
def keys(self) -> Iterator[Union[str, int]]: # pytype: disable=signature-mismatch
|
737
749
|
"""Returns an iterator of keys in current dict."""
|
738
750
|
return self.sym_keys()
|
739
751
|
|
740
|
-
def items(self) -> Iterator[Tuple[str, Any]]: # pytype: disable=signature-mismatch
|
752
|
+
def items(self) -> Iterator[Tuple[Union[str, int], Any]]: # pytype: disable=signature-mismatch
|
741
753
|
"""Returns an iterator of (key, value) items in current dict."""
|
742
754
|
return self.sym_items()
|
743
755
|
|
@@ -750,7 +762,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
750
762
|
return self.sym_clone(deep=False)
|
751
763
|
|
752
764
|
def pop(
|
753
|
-
self, key:
|
765
|
+
self, key: Union[str, int], default: Any = base.RAISE_IF_NOT_FOUND # pylint: disable=protected-access
|
754
766
|
) -> Any:
|
755
767
|
"""Pops a key from current dict."""
|
756
768
|
if key in self:
|
@@ -762,7 +774,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
762
774
|
raise KeyError(key)
|
763
775
|
return default
|
764
776
|
|
765
|
-
def popitem(self) -> Tuple[str, Any]:
|
777
|
+
def popitem(self) -> Tuple[Union[str, int], Any]:
|
766
778
|
if self._value_spec is not None:
|
767
779
|
raise ValueError(
|
768
780
|
'\'popitem\' cannot be performed on a Dict with value spec.')
|
@@ -781,7 +793,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
781
793
|
if value_spec:
|
782
794
|
self.use_value_spec(value_spec, self._allow_partial)
|
783
795
|
|
784
|
-
def setdefault(self, key: str, default: Any = None) -> Any:
|
796
|
+
def setdefault(self, key: Union[str, int], default: Any = None) -> Any:
|
785
797
|
"""Sets default as the value to key if not present."""
|
786
798
|
value = pg_typing.MISSING_VALUE
|
787
799
|
if key in self:
|
@@ -791,12 +803,15 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
791
803
|
value = default
|
792
804
|
return value
|
793
805
|
|
794
|
-
def update(
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
806
|
+
def update(
|
807
|
+
self,
|
808
|
+
other: Union[
|
809
|
+
None,
|
810
|
+
typing.Dict[Union[str, int], Any],
|
811
|
+
Iterable[Tuple[Union[str, int], Any]]
|
812
|
+
] = None,
|
813
|
+
**kwargs
|
814
|
+
) -> None: # pytype: disable=signature-mismatch
|
800
815
|
"""Update Dict with the same semantic as update on standard dict."""
|
801
816
|
updates = dict(other) if other else {}
|
802
817
|
updates.update(kwargs)
|
@@ -807,9 +822,10 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
807
822
|
self,
|
808
823
|
hide_frozen: bool = True,
|
809
824
|
hide_default_values: bool = False,
|
810
|
-
exclude_keys: Optional[Sequence[str]] = None,
|
825
|
+
exclude_keys: Optional[Sequence[Union[str, int]]] = None,
|
811
826
|
use_inferred: bool = False,
|
812
|
-
**kwargs
|
827
|
+
**kwargs,
|
828
|
+
) -> utils.JSONValueType:
|
813
829
|
"""Converts current object to a dict with plain Python objects."""
|
814
830
|
exclude_keys = set(exclude_keys or [])
|
815
831
|
if self._value_spec and self._value_spec.schema:
|
@@ -852,11 +868,12 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
852
868
|
|
853
869
|
def custom_apply(
|
854
870
|
self,
|
855
|
-
path:
|
871
|
+
path: utils.KeyPath,
|
856
872
|
value_spec: pg_typing.ValueSpec,
|
857
873
|
allow_partial: bool,
|
858
874
|
child_transform: Optional[
|
859
|
-
Callable[[
|
875
|
+
Callable[[utils.KeyPath, pg_typing.Field, Any], Any]
|
876
|
+
] = None,
|
860
877
|
) -> Tuple[bool, 'Dict']:
|
861
878
|
"""Implement pg.typing.CustomTyping interface.
|
862
879
|
|
@@ -875,9 +892,12 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
875
892
|
if self._value_spec:
|
876
893
|
if value_spec and not value_spec.is_compatible(self._value_spec):
|
877
894
|
raise ValueError(
|
878
|
-
|
895
|
+
utils.message_on_path(
|
879
896
|
f'Dict (spec={self._value_spec!r}) cannot be assigned to an '
|
880
|
-
f'incompatible field (spec={value_spec!r}).',
|
897
|
+
f'incompatible field (spec={value_spec!r}).',
|
898
|
+
path,
|
899
|
+
)
|
900
|
+
)
|
881
901
|
if self._allow_partial == allow_partial:
|
882
902
|
proceed_with_standard_apply = False
|
883
903
|
else:
|
@@ -896,11 +916,11 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
896
916
|
hide_frozen: bool = True,
|
897
917
|
hide_default_values: bool = False,
|
898
918
|
hide_missing_values: bool = False,
|
899
|
-
include_keys: Optional[Set[str]] = None,
|
900
|
-
exclude_keys: Optional[Set[str]] = None,
|
919
|
+
include_keys: Optional[Set[Union[str, int]]] = None,
|
920
|
+
exclude_keys: Optional[Set[Union[str, int]]] = None,
|
901
921
|
use_inferred: bool = False,
|
902
922
|
cls_name: Optional[str] = None,
|
903
|
-
bracket_type:
|
923
|
+
bracket_type: utils.BracketType = utils.BracketType.CURLY,
|
904
924
|
key_as_attribute: bool = False,
|
905
925
|
extra_blankline_for_field_docstr: bool = False,
|
906
926
|
**kwargs,
|
@@ -942,7 +962,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
942
962
|
v = self.sym_inferred(k, default=v)
|
943
963
|
field_list.append((None, k, v))
|
944
964
|
|
945
|
-
open_bracket, close_bracket =
|
965
|
+
open_bracket, close_bracket = utils.bracket_chars(bracket_type)
|
946
966
|
if not field_list:
|
947
967
|
return f'{cls_name}{open_bracket}{close_bracket}'
|
948
968
|
|
@@ -950,7 +970,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
950
970
|
s = [f'{cls_name}{open_bracket}']
|
951
971
|
kv_strs = []
|
952
972
|
for _, k, v in field_list:
|
953
|
-
v_str =
|
973
|
+
v_str = utils.format(
|
954
974
|
v,
|
955
975
|
compact,
|
956
976
|
verbose,
|
@@ -961,12 +981,15 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
961
981
|
python_format=python_format,
|
962
982
|
use_inferred=use_inferred,
|
963
983
|
extra_blankline_for_field_docstr=extra_blankline_for_field_docstr,
|
964
|
-
**kwargs
|
984
|
+
**kwargs,
|
985
|
+
)
|
965
986
|
if not python_format or key_as_attribute:
|
966
|
-
|
987
|
+
if isinstance(k, int):
|
988
|
+
k = f'[{k}]'
|
989
|
+
item = f'{k}={v_str}'
|
967
990
|
else:
|
968
|
-
|
969
|
-
|
991
|
+
item = f'{k!r}: {v_str}'
|
992
|
+
kv_strs.append(item)
|
970
993
|
s.append(', '.join(kv_strs))
|
971
994
|
s.append(close_bracket)
|
972
995
|
else:
|
@@ -981,7 +1004,7 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
981
1004
|
description = typing.cast(pg_typing.Field, f).description
|
982
1005
|
for line in description.split('\n'):
|
983
1006
|
s.append(_indent(f'# {line}\n', root_indent + 1))
|
984
|
-
v_str =
|
1007
|
+
v_str = utils.format(
|
985
1008
|
v,
|
986
1009
|
compact,
|
987
1010
|
verbose,
|
@@ -992,16 +1015,21 @@ class Dict(dict, base.Symbolic, pg_typing.CustomTyping):
|
|
992
1015
|
python_format=python_format,
|
993
1016
|
use_inferred=use_inferred,
|
994
1017
|
extra_blankline_for_field_docstr=extra_blankline_for_field_docstr,
|
995
|
-
**kwargs
|
1018
|
+
**kwargs,
|
1019
|
+
)
|
1020
|
+
|
996
1021
|
if not python_format:
|
997
1022
|
# Format in PyGlove's format (default).
|
998
|
-
|
1023
|
+
if isinstance(k, int):
|
1024
|
+
k = f'[{k}]'
|
1025
|
+
item = f'{k} = {v_str}'
|
999
1026
|
elif key_as_attribute:
|
1000
1027
|
# Format `pg.Objects` under Python format.
|
1001
|
-
|
1028
|
+
item = f'{k}={v_str}'
|
1002
1029
|
else:
|
1003
1030
|
# Format regular `pg.Dict` under Python format.
|
1004
|
-
|
1031
|
+
item = f'{k!r}: {v_str}'
|
1032
|
+
s.append(_indent(item, root_indent + 1))
|
1005
1033
|
s.append('\n')
|
1006
1034
|
s.append(_indent(close_bracket, root_indent))
|
1007
1035
|
return ''.join(s)
|