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.
- pyglove/core/__init__.py +24 -21
- 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 +2 -4
- 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/base.py +167 -131
- pyglove/core/symbolic/base_test.py +17 -19
- pyglove/core/symbolic/boilerplate.py +4 -5
- pyglove/core/symbolic/class_wrapper.py +9 -9
- pyglove/core/symbolic/compounding.py +2 -2
- pyglove/core/symbolic/compounding_test.py +2 -4
- pyglove/core/symbolic/dict.py +70 -54
- pyglove/core/symbolic/dict_test.py +117 -100
- 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 +42 -40
- pyglove/core/symbolic/object_test.py +95 -88
- pyglove/core/symbolic/origin.py +5 -7
- pyglove/core/symbolic/pure_symbolic.py +4 -3
- pyglove/core/symbolic/ref.py +12 -8
- pyglove/core/tuning/local_backend.py +2 -2
- pyglove/core/tuning/protocols.py +3 -3
- pyglove/core/typing/annotation_conversion.py +3 -3
- pyglove/core/typing/callable_ext.py +11 -13
- pyglove/core/typing/callable_signature.py +19 -18
- pyglove/core/typing/callable_signature_test.py +3 -5
- pyglove/core/typing/class_schema.py +48 -44
- pyglove/core/typing/class_schema_test.py +3 -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 +210 -141
- pyglove/core/typing/value_specs_test.py +12 -13
- pyglove/core/utils/__init__.py +159 -0
- pyglove/core/{object_utils → utils}/common_traits_test.py +1 -3
- 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_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/{object_utils → utils}/thread_local_test.py +1 -3
- pyglove/core/{object_utils → utils}/timing.py +3 -3
- pyglove/core/{object_utils → utils}/timing_test.py +2 -3
- 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 +14 -15
- pyglove/core/views/html/controls/base.py +5 -5
- pyglove/core/views/html/controls/progress_bar.py +3 -5
- pyglove/core/views/html/tree_view.py +37 -35
- {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/METADATA +1 -1
- {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/RECORD +90 -90
- {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/WHEEL +1 -1
- pyglove/core/object_utils/__init__.py +0 -161
- /pyglove/core/{object_utils → utils}/common_traits.py +0 -0
- /pyglove/core/{object_utils → utils}/docstr_utils.py +0 -0
- /pyglove/core/{object_utils → utils}/json_conversion.py +0 -0
- /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
- {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/LICENSE +0 -0
- {pyglove-0.4.5.dev202501050808.dist-info → pyglove-0.4.5.dev202501060809.dist-info}/top_level.txt +0 -0
@@ -11,16 +11,14 @@
|
|
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.Dict."""
|
15
|
-
|
16
14
|
import copy
|
17
15
|
import inspect
|
18
16
|
import io
|
19
17
|
import pickle
|
20
18
|
import unittest
|
21
19
|
|
22
|
-
from pyglove.core import object_utils
|
23
20
|
from pyglove.core import typing as pg_typing
|
21
|
+
from pyglove.core import utils
|
24
22
|
from pyglove.core.symbolic import base
|
25
23
|
from pyglove.core.symbolic import flags
|
26
24
|
from pyglove.core.symbolic import inferred
|
@@ -31,7 +29,7 @@ from pyglove.core.symbolic.pure_symbolic import NonDeterministic
|
|
31
29
|
from pyglove.core.symbolic.pure_symbolic import PureSymbolic
|
32
30
|
|
33
31
|
|
34
|
-
MISSING_VALUE =
|
32
|
+
MISSING_VALUE = utils.MISSING_VALUE
|
35
33
|
|
36
34
|
|
37
35
|
class DictTest(unittest.TestCase):
|
@@ -799,7 +797,7 @@ class DictTest(unittest.TestCase):
|
|
799
797
|
self.assertTrue(sd.sym_has('y.z'))
|
800
798
|
self.assertTrue(sd.sym_has('[1].a'))
|
801
799
|
self.assertTrue(sd.sym_has('y[2]'))
|
802
|
-
self.assertTrue(sd.sym_has(
|
800
|
+
self.assertTrue(sd.sym_has(utils.KeyPath.parse('y.z')))
|
803
801
|
self.assertFalse(sd.sym_has('x.z'))
|
804
802
|
|
805
803
|
def test_sym_get(self):
|
@@ -1267,7 +1265,7 @@ class DictTest(unittest.TestCase):
|
|
1267
1265
|
self.assertEqual(sd.x.a.sym_path, 'x.a')
|
1268
1266
|
self.assertEqual(sd.y[0].b.sym_path, 'y[0].b')
|
1269
1267
|
|
1270
|
-
sd.sym_setpath(
|
1268
|
+
sd.sym_setpath(utils.KeyPath('a'))
|
1271
1269
|
self.assertEqual(sd.sym_path, 'a')
|
1272
1270
|
self.assertEqual(sd.x.sym_path, 'a.x')
|
1273
1271
|
self.assertEqual(sd.x.a.sym_path, 'a.x.a')
|
@@ -1724,96 +1722,112 @@ class RebindTest(unittest.TestCase):
|
|
1724
1722
|
'd': 'foo', # Unchanged.
|
1725
1723
|
'e': 'bar'
|
1726
1724
|
})
|
1727
|
-
self.assertEqual(
|
1728
|
-
|
1729
|
-
|
1730
|
-
|
1731
|
-
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
1743
|
-
|
1744
|
-
|
1745
|
-
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
|
1750
|
-
|
1751
|
-
|
1752
|
-
|
1753
|
-
|
1754
|
-
|
1755
|
-
|
1756
|
-
|
1757
|
-
|
1758
|
-
|
1759
|
-
|
1760
|
-
|
1761
|
-
|
1762
|
-
|
1763
|
-
|
1764
|
-
|
1765
|
-
|
1766
|
-
|
1767
|
-
|
1768
|
-
|
1769
|
-
|
1770
|
-
|
1771
|
-
|
1772
|
-
|
1773
|
-
|
1774
|
-
|
1775
|
-
|
1776
|
-
|
1777
|
-
|
1778
|
-
|
1779
|
-
|
1780
|
-
|
1781
|
-
|
1782
|
-
|
1783
|
-
|
1784
|
-
|
1785
|
-
|
1786
|
-
|
1787
|
-
|
1788
|
-
|
1789
|
-
|
1790
|
-
|
1791
|
-
|
1792
|
-
|
1793
|
-
|
1794
|
-
|
1795
|
-
|
1796
|
-
|
1797
|
-
|
1798
|
-
|
1799
|
-
|
1800
|
-
|
1801
|
-
|
1802
|
-
|
1803
|
-
|
1804
|
-
|
1805
|
-
|
1806
|
-
|
1807
|
-
|
1808
|
-
|
1809
|
-
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
1813
|
-
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1725
|
+
self.assertEqual(
|
1726
|
+
updates,
|
1727
|
+
[
|
1728
|
+
{ # Notification to `sd.c[0]`.
|
1729
|
+
'p': base.FieldUpdate(
|
1730
|
+
utils.KeyPath.parse('c[0].p'),
|
1731
|
+
target=sd.c[0],
|
1732
|
+
field=None,
|
1733
|
+
old_value=1,
|
1734
|
+
new_value=MISSING_VALUE,
|
1735
|
+
),
|
1736
|
+
'q': base.FieldUpdate(
|
1737
|
+
utils.KeyPath.parse('c[0].q'),
|
1738
|
+
target=sd.c[0],
|
1739
|
+
field=None,
|
1740
|
+
old_value=MISSING_VALUE,
|
1741
|
+
new_value=2,
|
1742
|
+
),
|
1743
|
+
},
|
1744
|
+
{ # Notification to `sd.c`.
|
1745
|
+
'[0].p': base.FieldUpdate(
|
1746
|
+
utils.KeyPath.parse('c[0].p'),
|
1747
|
+
target=sd.c[0],
|
1748
|
+
field=None,
|
1749
|
+
old_value=1,
|
1750
|
+
new_value=MISSING_VALUE,
|
1751
|
+
),
|
1752
|
+
'[0].q': base.FieldUpdate(
|
1753
|
+
utils.KeyPath.parse('c[0].q'),
|
1754
|
+
target=sd.c[0],
|
1755
|
+
field=None,
|
1756
|
+
old_value=MISSING_VALUE,
|
1757
|
+
new_value=2,
|
1758
|
+
),
|
1759
|
+
},
|
1760
|
+
{ # Notification to `sd.b.y`.
|
1761
|
+
'z': base.FieldUpdate(
|
1762
|
+
utils.KeyPath.parse('b.y.z'),
|
1763
|
+
target=sd.b.y,
|
1764
|
+
field=None,
|
1765
|
+
old_value=MISSING_VALUE,
|
1766
|
+
new_value=1,
|
1767
|
+
),
|
1768
|
+
},
|
1769
|
+
{ # Notification to `sd.b`.
|
1770
|
+
'x': base.FieldUpdate(
|
1771
|
+
utils.KeyPath.parse('b.x'),
|
1772
|
+
target=sd.b,
|
1773
|
+
field=None,
|
1774
|
+
old_value=1,
|
1775
|
+
new_value=2,
|
1776
|
+
),
|
1777
|
+
'y.z': base.FieldUpdate(
|
1778
|
+
utils.KeyPath.parse('b.y.z'),
|
1779
|
+
target=sd.b.y,
|
1780
|
+
field=None,
|
1781
|
+
old_value=MISSING_VALUE,
|
1782
|
+
new_value=1,
|
1783
|
+
),
|
1784
|
+
},
|
1785
|
+
{ # Notification to `sd`.
|
1786
|
+
'a': base.FieldUpdate(
|
1787
|
+
utils.KeyPath.parse('a'),
|
1788
|
+
target=sd,
|
1789
|
+
field=None,
|
1790
|
+
old_value=1,
|
1791
|
+
new_value=2,
|
1792
|
+
),
|
1793
|
+
'b.x': base.FieldUpdate(
|
1794
|
+
utils.KeyPath.parse('b.x'),
|
1795
|
+
target=sd.b,
|
1796
|
+
field=None,
|
1797
|
+
old_value=1,
|
1798
|
+
new_value=2,
|
1799
|
+
),
|
1800
|
+
'b.y.z': base.FieldUpdate(
|
1801
|
+
utils.KeyPath.parse('b.y.z'),
|
1802
|
+
target=sd.b.y,
|
1803
|
+
field=None,
|
1804
|
+
old_value=MISSING_VALUE,
|
1805
|
+
new_value=1,
|
1806
|
+
),
|
1807
|
+
'c[0].p': base.FieldUpdate(
|
1808
|
+
utils.KeyPath.parse('c[0].p'),
|
1809
|
+
target=sd.c[0],
|
1810
|
+
field=None,
|
1811
|
+
old_value=1,
|
1812
|
+
new_value=MISSING_VALUE,
|
1813
|
+
),
|
1814
|
+
'c[0].q': base.FieldUpdate(
|
1815
|
+
utils.KeyPath.parse('c[0].q'),
|
1816
|
+
target=sd.c[0],
|
1817
|
+
field=None,
|
1818
|
+
old_value=MISSING_VALUE,
|
1819
|
+
new_value=2,
|
1820
|
+
),
|
1821
|
+
'e': base.FieldUpdate(
|
1822
|
+
utils.KeyPath.parse('e'),
|
1823
|
+
target=sd,
|
1824
|
+
field=None,
|
1825
|
+
old_value=MISSING_VALUE,
|
1826
|
+
new_value='bar',
|
1827
|
+
),
|
1828
|
+
},
|
1829
|
+
],
|
1830
|
+
)
|
1817
1831
|
|
1818
1832
|
def test_rebind_with_fn(self):
|
1819
1833
|
sd = Dict(a=1, b=dict(x=2, y='foo', z=[0, 1, 2]))
|
@@ -2096,7 +2110,7 @@ class FormatTest(unittest.TestCase):
|
|
2096
2110
|
|
2097
2111
|
def test_compact_python_format(self):
|
2098
2112
|
self.assertEqual(
|
2099
|
-
|
2113
|
+
utils.format(
|
2100
2114
|
self._dict, compact=True, python_format=True, markdown=True
|
2101
2115
|
),
|
2102
2116
|
"`{'a1': 1, 'a2': {'b1': {'c1': [{'d1': MISSING_VALUE, "
|
@@ -2106,9 +2120,12 @@ class FormatTest(unittest.TestCase):
|
|
2106
2120
|
|
2107
2121
|
def test_noncompact_python_format(self):
|
2108
2122
|
self.assertEqual(
|
2109
|
-
|
2110
|
-
self._dict,
|
2111
|
-
|
2123
|
+
utils.format(
|
2124
|
+
self._dict,
|
2125
|
+
compact=False,
|
2126
|
+
verbose=False,
|
2127
|
+
python_format=True,
|
2128
|
+
markdown=True,
|
2112
2129
|
),
|
2113
2130
|
inspect.cleandoc("""
|
2114
2131
|
```
|
pyglove/core/symbolic/diff.py
CHANGED
@@ -15,8 +15,8 @@
|
|
15
15
|
|
16
16
|
from typing import Any, Callable, Optional, Sequence, Tuple, Union
|
17
17
|
|
18
|
-
from pyglove.core import object_utils
|
19
18
|
from pyglove.core import typing as pg_typing
|
19
|
+
from pyglove.core import utils
|
20
20
|
from pyglove.core.symbolic import base
|
21
21
|
from pyglove.core.symbolic import list as pg_list
|
22
22
|
from pyglove.core.symbolic import object as pg_object
|
@@ -112,8 +112,7 @@ class Diff(PureSymbolic, pg_object.Object, tree_view.HtmlTreeView.Extension):
|
|
112
112
|
return 'No diff'
|
113
113
|
# When there is no diff, but the same value needs to be displayed
|
114
114
|
# we simply return the value.
|
115
|
-
return
|
116
|
-
self.value, compact, verbose, root_indent, **kwargs)
|
115
|
+
return utils.format(self.value, compact, verbose, root_indent, **kwargs)
|
117
116
|
if self.is_leaf:
|
118
117
|
exclude_keys = kwargs.pop('exclude_keys', None)
|
119
118
|
exclude_keys = exclude_keys or set()
|
@@ -129,7 +128,7 @@ class Diff(PureSymbolic, pg_object.Object, tree_view.HtmlTreeView.Extension):
|
|
129
128
|
verbose=verbose,
|
130
129
|
root_indent=root_indent,
|
131
130
|
cls_name='',
|
132
|
-
bracket_type=
|
131
|
+
bracket_type=utils.BracketType.SQUARE,
|
133
132
|
**kwargs,
|
134
133
|
)
|
135
134
|
if self.left is self.right:
|
@@ -141,7 +140,7 @@ class Diff(PureSymbolic, pg_object.Object, tree_view.HtmlTreeView.Extension):
|
|
141
140
|
verbose=verbose,
|
142
141
|
root_indent=root_indent,
|
143
142
|
cls_name=cls_name,
|
144
|
-
bracket_type=
|
143
|
+
bracket_type=utils.BracketType.ROUND,
|
145
144
|
**kwargs,
|
146
145
|
)
|
147
146
|
|
@@ -155,7 +154,7 @@ class Diff(PureSymbolic, pg_object.Object, tree_view.HtmlTreeView.Extension):
|
|
155
154
|
max_summary_len_for_str: int = 80,
|
156
155
|
**kwargs,
|
157
156
|
) -> Optional[tree_view.Html]:
|
158
|
-
|
157
|
+
# pytype: enable=annotation-type-mismatch
|
159
158
|
if not bool(self):
|
160
159
|
v = self.value
|
161
160
|
if (isinstance(v, (int, float, bool, type(None)))
|
@@ -199,11 +198,11 @@ class Diff(PureSymbolic, pg_object.Object, tree_view.HtmlTreeView.Extension):
|
|
199
198
|
*,
|
200
199
|
view: tree_view.HtmlTreeView,
|
201
200
|
parent: Any = None,
|
202
|
-
root_path: Optional[
|
201
|
+
root_path: Optional[utils.KeyPath] = None,
|
203
202
|
css_classes: Optional[Sequence[str]] = None,
|
204
|
-
**kwargs
|
203
|
+
**kwargs,
|
205
204
|
) -> tree_view.Html:
|
206
|
-
root_path = root_path or
|
205
|
+
root_path = root_path or utils.KeyPath()
|
207
206
|
if not bool(self):
|
208
207
|
if self.value == Diff.MISSING:
|
209
208
|
root = tree_view.Html.element(
|
@@ -353,7 +352,8 @@ def diff(
|
|
353
352
|
right: Any,
|
354
353
|
flatten: bool = False,
|
355
354
|
collapse: Union[bool, str, Callable[[Any, Any], bool]] = 'same_type',
|
356
|
-
mode: str = 'diff'
|
355
|
+
mode: str = 'diff',
|
356
|
+
) -> utils.Nestable[Diff]:
|
357
357
|
"""Inspect the symbolic diff between two objects.
|
358
358
|
|
359
359
|
For example::
|
@@ -479,7 +479,7 @@ def diff(
|
|
479
479
|
assert isinstance(container, base.Symbolic)
|
480
480
|
return container.sym_hasattr, container.sym_getattr, container.sym_items
|
481
481
|
|
482
|
-
def _diff(x, y) -> Tuple[
|
482
|
+
def _diff(x, y) -> Tuple[utils.Nestable[Diff], bool]:
|
483
483
|
if x is y or x == y:
|
484
484
|
return (Diff(x, y), False)
|
485
485
|
if not _should_collapse(x, y):
|
@@ -533,5 +533,5 @@ def diff(
|
|
533
533
|
if not has_diff and mode == 'diff':
|
534
534
|
diff_value = Diff()
|
535
535
|
if flatten:
|
536
|
-
diff_value =
|
536
|
+
diff_value = utils.flatten(diff_value)
|
537
537
|
return diff_value
|
pyglove/core/symbolic/flags.py
CHANGED
pyglove/core/symbolic/functor.py
CHANGED
@@ -22,14 +22,14 @@ import types
|
|
22
22
|
import typing
|
23
23
|
from typing import Any, Callable, Dict, List, Optional, Set, Tuple, Type, Union
|
24
24
|
|
25
|
-
from pyglove.core import object_utils
|
26
25
|
from pyglove.core import typing as pg_typing
|
26
|
+
from pyglove.core import utils
|
27
27
|
from pyglove.core.symbolic import base
|
28
28
|
from pyglove.core.symbolic import flags
|
29
29
|
from pyglove.core.symbolic import object as pg_object
|
30
30
|
|
31
31
|
|
32
|
-
class Functor(pg_object.Object,
|
32
|
+
class Functor(pg_object.Object, utils.Functor):
|
33
33
|
"""Symbolic functions (Functors).
|
34
34
|
|
35
35
|
A symbolic function is a symbolic class with a ``__call__`` method, whose
|
@@ -124,7 +124,7 @@ class Functor(pg_object.Object, object_utils.Functor):
|
|
124
124
|
if not hasattr(cls, '__orig_init__'):
|
125
125
|
setattr(cls, '__orig_init__', cls.__init__)
|
126
126
|
|
127
|
-
@
|
127
|
+
@utils.explicit_method_override
|
128
128
|
@functools.wraps(pseudo_init)
|
129
129
|
def _init(self, *args, **kwargs):
|
130
130
|
self.__class__.__orig_init__(self, *args, **kwargs)
|
@@ -148,14 +148,15 @@ class Functor(pg_object.Object, object_utils.Functor):
|
|
148
148
|
return instance()
|
149
149
|
return instance
|
150
150
|
|
151
|
-
@
|
151
|
+
@utils.explicit_method_override
|
152
152
|
def __init__(
|
153
153
|
self,
|
154
154
|
*args,
|
155
|
-
root_path: Optional[
|
155
|
+
root_path: Optional[utils.KeyPath] = None,
|
156
156
|
override_args: bool = False,
|
157
157
|
ignore_extra_args: bool = False,
|
158
|
-
**kwargs
|
158
|
+
**kwargs,
|
159
|
+
):
|
159
160
|
"""Constructor.
|
160
161
|
|
161
162
|
Args:
|
@@ -182,8 +183,8 @@ class Functor(pg_object.Object, object_utils.Functor):
|
|
182
183
|
varargs = list(args[len(signature.args) :])
|
183
184
|
args = args[: len(signature.args)]
|
184
185
|
else:
|
185
|
-
arg_phrase =
|
186
|
-
was_phrase =
|
186
|
+
arg_phrase = utils.auto_plural(len(signature.args), 'argument')
|
187
|
+
was_phrase = utils.auto_plural(len(args), 'was', 'were')
|
187
188
|
raise TypeError(
|
188
189
|
f'{signature.id}() takes {len(signature.args)} '
|
189
190
|
f'positional {arg_phrase} but {len(args)} {was_phrase} given.'
|
@@ -257,8 +258,7 @@ class Functor(pg_object.Object, object_utils.Functor):
|
|
257
258
|
# pylint: enable=protected-access
|
258
259
|
return typing.cast(Functor, other)
|
259
260
|
|
260
|
-
def _on_change(
|
261
|
-
self, field_updates: Dict[object_utils.KeyPath, base.FieldUpdate]):
|
261
|
+
def _on_change(self, field_updates: Dict[utils.KeyPath, base.FieldUpdate]):
|
262
262
|
"""Custom handling field change to update bound args."""
|
263
263
|
for relative_path, update in field_updates.items():
|
264
264
|
assert relative_path
|
@@ -406,8 +406,8 @@ class Functor(pg_object.Object, object_utils.Functor):
|
|
406
406
|
if ignore_extra_args:
|
407
407
|
args = args[: len(signature.args)]
|
408
408
|
else:
|
409
|
-
arg_phrase =
|
410
|
-
was_phrase =
|
409
|
+
arg_phrase = utils.auto_plural(len(signature.args), 'argument')
|
410
|
+
was_phrase = utils.auto_plural(len(args), 'was', 'were')
|
411
411
|
raise TypeError(
|
412
412
|
f'{signature.id}() takes {len(signature.args)} '
|
413
413
|
f'positional {arg_phrase} but {len(args)} {was_phrase} given.'
|
@@ -483,9 +483,10 @@ class Functor(pg_object.Object, object_utils.Functor):
|
|
483
483
|
missing_required_arg_names.append(arg.name)
|
484
484
|
|
485
485
|
if missing_required_arg_names:
|
486
|
-
arg_phrase =
|
487
|
-
len(missing_required_arg_names), 'argument'
|
488
|
-
|
486
|
+
arg_phrase = utils.auto_plural(
|
487
|
+
len(missing_required_arg_names), 'argument'
|
488
|
+
)
|
489
|
+
args_str = utils.comma_delimited_str(missing_required_arg_names)
|
489
490
|
raise TypeError(
|
490
491
|
f'{signature.id}() missing {len(missing_required_arg_names)} '
|
491
492
|
f'required positional {arg_phrase}: {args_str}.'
|
@@ -11,15 +11,13 @@
|
|
11
11
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
|
-
"""Tests for pyglove.Functor."""
|
15
|
-
|
16
14
|
import inspect
|
17
15
|
import io
|
18
16
|
import typing
|
19
17
|
import unittest
|
20
18
|
|
21
|
-
from pyglove.core import object_utils
|
22
19
|
from pyglove.core import typing as pg_typing
|
20
|
+
from pyglove.core import utils
|
23
21
|
from pyglove.core.symbolic import flags
|
24
22
|
from pyglove.core.symbolic.base import from_json_str as pg_from_json_str
|
25
23
|
from pyglove.core.symbolic.dict import Dict
|
@@ -31,7 +29,7 @@ from pyglove.core.symbolic.object import members as pg_members
|
|
31
29
|
from pyglove.core.symbolic.object import Object
|
32
30
|
|
33
31
|
|
34
|
-
MISSING_VALUE =
|
32
|
+
MISSING_VALUE = utils.MISSING_VALUE
|
35
33
|
|
36
34
|
|
37
35
|
class FunctorTest(unittest.TestCase):
|
@@ -14,8 +14,8 @@
|
|
14
14
|
"""Common inferential values."""
|
15
15
|
|
16
16
|
from typing import Any, Tuple
|
17
|
-
from pyglove.core import object_utils
|
18
17
|
from pyglove.core import typing as pg_typing
|
18
|
+
from pyglove.core import utils
|
19
19
|
from pyglove.core.symbolic import base
|
20
20
|
from pyglove.core.symbolic.object import Object
|
21
21
|
|
@@ -65,7 +65,7 @@ class ValueFromParentChain(InferredValue):
|
|
65
65
|
if v == pg_typing.MISSING_VALUE:
|
66
66
|
if parent is None:
|
67
67
|
raise AttributeError(
|
68
|
-
|
68
|
+
utils.message_on_path(
|
69
69
|
(
|
70
70
|
f'`{self.inference_key}` is not found under its context '
|
71
71
|
'(along its symbolic parent chain).'
|