pyglove 0.4.5.dev20240319__py3-none-any.whl → 0.4.5.dev202501132210__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 (145) hide show
  1. pyglove/core/__init__.py +54 -20
  2. pyglove/core/coding/__init__.py +42 -0
  3. pyglove/core/coding/errors.py +111 -0
  4. pyglove/core/coding/errors_test.py +98 -0
  5. pyglove/core/coding/execution.py +309 -0
  6. pyglove/core/coding/execution_test.py +333 -0
  7. pyglove/core/{object_utils/codegen.py → coding/function_generation.py} +10 -4
  8. pyglove/core/{object_utils/codegen_test.py → coding/function_generation_test.py} +5 -7
  9. pyglove/core/coding/parsing.py +153 -0
  10. pyglove/core/coding/parsing_test.py +150 -0
  11. pyglove/core/coding/permissions.py +100 -0
  12. pyglove/core/coding/permissions_test.py +93 -0
  13. pyglove/core/geno/base.py +54 -41
  14. pyglove/core/geno/base_test.py +2 -4
  15. pyglove/core/geno/categorical.py +37 -28
  16. pyglove/core/geno/custom.py +19 -16
  17. pyglove/core/geno/numerical.py +20 -17
  18. pyglove/core/geno/space.py +4 -5
  19. pyglove/core/hyper/base.py +6 -6
  20. pyglove/core/hyper/categorical.py +94 -55
  21. pyglove/core/hyper/custom.py +7 -7
  22. pyglove/core/hyper/custom_test.py +9 -10
  23. pyglove/core/hyper/derived.py +30 -22
  24. pyglove/core/hyper/derived_test.py +2 -4
  25. pyglove/core/hyper/dynamic_evaluation.py +5 -6
  26. pyglove/core/hyper/evolvable.py +57 -46
  27. pyglove/core/hyper/numerical.py +48 -24
  28. pyglove/core/hyper/numerical_test.py +9 -9
  29. pyglove/core/hyper/object_template.py +58 -46
  30. pyglove/core/io/__init__.py +1 -0
  31. pyglove/core/io/file_system.py +17 -7
  32. pyglove/core/io/file_system_test.py +2 -0
  33. pyglove/core/io/sequence.py +299 -0
  34. pyglove/core/io/sequence_test.py +124 -0
  35. pyglove/core/logging_test.py +0 -2
  36. pyglove/core/patching/object_factory.py +4 -4
  37. pyglove/core/patching/pattern_based.py +4 -4
  38. pyglove/core/patching/rule_based.py +17 -5
  39. pyglove/core/patching/rule_based_test.py +27 -4
  40. pyglove/core/symbolic/__init__.py +2 -7
  41. pyglove/core/symbolic/base.py +320 -183
  42. pyglove/core/symbolic/base_test.py +123 -19
  43. pyglove/core/symbolic/boilerplate.py +7 -13
  44. pyglove/core/symbolic/boilerplate_test.py +25 -23
  45. pyglove/core/symbolic/class_wrapper.py +48 -45
  46. pyglove/core/symbolic/class_wrapper_test.py +2 -2
  47. pyglove/core/symbolic/compounding.py +9 -15
  48. pyglove/core/symbolic/compounding_test.py +2 -4
  49. pyglove/core/symbolic/dict.py +154 -110
  50. pyglove/core/symbolic/dict_test.py +238 -130
  51. pyglove/core/symbolic/diff.py +199 -10
  52. pyglove/core/symbolic/diff_test.py +226 -0
  53. pyglove/core/symbolic/flags.py +1 -1
  54. pyglove/core/symbolic/functor.py +29 -26
  55. pyglove/core/symbolic/functor_test.py +102 -50
  56. pyglove/core/symbolic/inferred.py +2 -2
  57. pyglove/core/symbolic/list.py +81 -50
  58. pyglove/core/symbolic/list_test.py +119 -97
  59. pyglove/core/symbolic/object.py +225 -113
  60. pyglove/core/symbolic/object_test.py +320 -108
  61. pyglove/core/symbolic/origin.py +17 -14
  62. pyglove/core/symbolic/origin_test.py +4 -2
  63. pyglove/core/symbolic/pure_symbolic.py +4 -3
  64. pyglove/core/symbolic/ref.py +108 -21
  65. pyglove/core/symbolic/ref_test.py +93 -0
  66. pyglove/core/symbolic/symbolize_test.py +10 -2
  67. pyglove/core/tuning/local_backend.py +2 -2
  68. pyglove/core/tuning/protocols.py +3 -3
  69. pyglove/core/tuning/sample_test.py +3 -3
  70. pyglove/core/typing/__init__.py +14 -5
  71. pyglove/core/typing/annotation_conversion.py +43 -27
  72. pyglove/core/typing/annotation_conversion_test.py +23 -0
  73. pyglove/core/typing/callable_ext.py +241 -3
  74. pyglove/core/typing/callable_ext_test.py +255 -0
  75. pyglove/core/typing/callable_signature.py +510 -66
  76. pyglove/core/typing/callable_signature_test.py +619 -99
  77. pyglove/core/typing/class_schema.py +229 -154
  78. pyglove/core/typing/class_schema_test.py +149 -95
  79. pyglove/core/typing/custom_typing.py +5 -4
  80. pyglove/core/typing/inspect.py +63 -0
  81. pyglove/core/typing/inspect_test.py +39 -0
  82. pyglove/core/typing/key_specs.py +10 -11
  83. pyglove/core/typing/key_specs_test.py +7 -4
  84. pyglove/core/typing/type_conversion.py +4 -5
  85. pyglove/core/typing/type_conversion_test.py +12 -12
  86. pyglove/core/typing/typed_missing.py +6 -7
  87. pyglove/core/typing/typed_missing_test.py +7 -8
  88. pyglove/core/typing/value_specs.py +604 -362
  89. pyglove/core/typing/value_specs_test.py +328 -90
  90. pyglove/core/utils/__init__.py +164 -0
  91. pyglove/core/{object_utils → utils}/common_traits.py +3 -67
  92. pyglove/core/utils/common_traits_test.py +36 -0
  93. pyglove/core/{object_utils → utils}/docstr_utils.py +23 -0
  94. pyglove/core/{object_utils → utils}/docstr_utils_test.py +36 -4
  95. pyglove/core/{object_utils → utils}/error_utils.py +78 -9
  96. pyglove/core/{object_utils → utils}/error_utils_test.py +61 -5
  97. pyglove/core/utils/formatting.py +464 -0
  98. pyglove/core/utils/formatting_test.py +453 -0
  99. pyglove/core/{object_utils → utils}/hierarchical.py +23 -25
  100. pyglove/core/{object_utils → utils}/hierarchical_test.py +3 -5
  101. pyglove/core/{object_utils → utils}/json_conversion.py +177 -52
  102. pyglove/core/{object_utils → utils}/json_conversion_test.py +97 -16
  103. pyglove/core/{object_utils → utils}/missing.py +3 -3
  104. pyglove/core/{object_utils → utils}/missing_test.py +2 -4
  105. pyglove/core/utils/text_color.py +128 -0
  106. pyglove/core/utils/text_color_test.py +94 -0
  107. pyglove/core/{object_utils → utils}/thread_local_test.py +1 -3
  108. pyglove/core/utils/timing.py +236 -0
  109. pyglove/core/utils/timing_test.py +154 -0
  110. pyglove/core/{object_utils → utils}/value_location.py +275 -6
  111. pyglove/core/utils/value_location_test.py +707 -0
  112. pyglove/core/views/__init__.py +32 -0
  113. pyglove/core/views/base.py +804 -0
  114. pyglove/core/views/base_test.py +580 -0
  115. pyglove/core/views/html/__init__.py +27 -0
  116. pyglove/core/views/html/base.py +547 -0
  117. pyglove/core/views/html/base_test.py +830 -0
  118. pyglove/core/views/html/controls/__init__.py +35 -0
  119. pyglove/core/views/html/controls/base.py +275 -0
  120. pyglove/core/views/html/controls/label.py +207 -0
  121. pyglove/core/views/html/controls/label_test.py +157 -0
  122. pyglove/core/views/html/controls/progress_bar.py +183 -0
  123. pyglove/core/views/html/controls/progress_bar_test.py +97 -0
  124. pyglove/core/views/html/controls/tab.py +320 -0
  125. pyglove/core/views/html/controls/tab_test.py +87 -0
  126. pyglove/core/views/html/controls/tooltip.py +99 -0
  127. pyglove/core/views/html/controls/tooltip_test.py +99 -0
  128. pyglove/core/views/html/tree_view.py +1517 -0
  129. pyglove/core/views/html/tree_view_test.py +1461 -0
  130. {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/METADATA +18 -4
  131. pyglove-0.4.5.dev202501132210.dist-info/RECORD +214 -0
  132. {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/WHEEL +1 -1
  133. pyglove/core/object_utils/__init__.py +0 -154
  134. pyglove/core/object_utils/common_traits_test.py +0 -82
  135. pyglove/core/object_utils/formatting.py +0 -234
  136. pyglove/core/object_utils/formatting_test.py +0 -223
  137. pyglove/core/object_utils/value_location_test.py +0 -385
  138. pyglove/core/symbolic/schema_utils.py +0 -327
  139. pyglove/core/symbolic/schema_utils_test.py +0 -57
  140. pyglove/core/typing/class_schema_utils.py +0 -202
  141. pyglove/core/typing/class_schema_utils_test.py +0 -194
  142. pyglove-0.4.5.dev20240319.dist-info/RECORD +0 -185
  143. /pyglove/core/{object_utils → utils}/thread_local.py +0 -0
  144. {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/LICENSE +0 -0
  145. {pyglove-0.4.5.dev20240319.dist-info → pyglove-0.4.5.dev202501132210.dist-info}/top_level.txt +0 -0
@@ -18,6 +18,261 @@ from pyglove.core.typing import annotation_conversion # pylint: disable=unused
18
18
  from pyglove.core.typing import callable_ext
19
19
 
20
20
 
21
+ class PresetArgValueTest(unittest.TestCase):
22
+ """Tests for typing.PresetArgValue."""
23
+
24
+ def test_basics(self):
25
+ v = callable_ext.PresetArgValue()
26
+ self.assertFalse(v.has_default)
27
+ v = callable_ext.PresetArgValue(default=1)
28
+ self.assertTrue(v.has_default)
29
+ self.assertEqual(v.default, 1)
30
+ self.assertEqual(repr(v), 'PresetArgValue(default=1)')
31
+ self.assertEqual(str(v), 'PresetArgValue(\n default=1\n)')
32
+ self.assertEqual(
33
+ callable_ext.PresetArgValue(), callable_ext.PresetArgValue()
34
+ )
35
+ self.assertEqual(
36
+ callable_ext.PresetArgValue(1), callable_ext.PresetArgValue(1)
37
+ )
38
+ self.assertNotEqual(
39
+ callable_ext.PresetArgValue(), callable_ext.PresetArgValue(default=1)
40
+ )
41
+
42
+ def test_inspect(self):
43
+
44
+ def foo(
45
+ x=callable_ext.PresetArgValue(),
46
+ y=1,
47
+ *,
48
+ z=callable_ext.PresetArgValue(default=2)
49
+ ):
50
+ return x + y + z
51
+
52
+ self.assertEqual(
53
+ callable_ext.PresetArgValue.inspect(foo),
54
+ dict(
55
+ x=callable_ext.PresetArgValue(),
56
+ z=callable_ext.PresetArgValue(default=2)
57
+ )
58
+ )
59
+
60
+ def bar(x, y=1):
61
+ return x + y
62
+
63
+ self.assertEqual(
64
+ callable_ext.PresetArgValue.inspect(bar),
65
+ {}
66
+ )
67
+
68
+ def test_resolve_args(self):
69
+ # Both positional and keyword arguments are from preset.
70
+ self.assertEqual(
71
+ callable_ext.PresetArgValue.resolve_args(
72
+ call_args=[],
73
+ call_kwargs=dict(),
74
+ positional_arg_names=['x', 'y'],
75
+ arg_defaults={
76
+ 'x': callable_ext.PresetArgValue(),
77
+ 'z': callable_ext.PresetArgValue(default=2),
78
+ },
79
+ preset_kwargs=dict(x=1, y=2, z=3, w=4)
80
+ ),
81
+ ([1], dict(z=3))
82
+ )
83
+ # Both positional and keyword arguments are absent and use the default.
84
+ self.assertEqual(
85
+ callable_ext.PresetArgValue.resolve_args(
86
+ call_args=[],
87
+ call_kwargs=dict(),
88
+ positional_arg_names=['x', 'y'],
89
+ arg_defaults={
90
+ 'x': callable_ext.PresetArgValue(default=1),
91
+ 'y': 0,
92
+ 'z': callable_ext.PresetArgValue(default=2),
93
+ },
94
+ preset_kwargs=dict()
95
+ ),
96
+ ([1, 0], dict(z=2))
97
+ )
98
+ # Positional args from preset, keyword argument use preset default.
99
+ self.assertEqual(
100
+ callable_ext.PresetArgValue.resolve_args(
101
+ call_args=[],
102
+ call_kwargs=dict(),
103
+ positional_arg_names=['x', 'y'],
104
+ arg_defaults={
105
+ 'x': callable_ext.PresetArgValue(),
106
+ 'y': 0,
107
+ 'z': callable_ext.PresetArgValue(default=2),
108
+ },
109
+ preset_kwargs=dict(x=1, y=2)
110
+ ),
111
+ ([1, 0], dict(z=2))
112
+ )
113
+ # Postional argument provided by user, which should take precedence over
114
+ # the preset value.
115
+ self.assertEqual(
116
+ callable_ext.PresetArgValue.resolve_args(
117
+ call_args=[2],
118
+ call_kwargs={},
119
+ positional_arg_names=['x', 'y'],
120
+ arg_defaults={
121
+ 'x': callable_ext.PresetArgValue(),
122
+ 'y': 0,
123
+ 'z': callable_ext.PresetArgValue(default=2),
124
+ },
125
+ preset_kwargs=dict(x=1, y=2, z=3, w=4)
126
+ ),
127
+ ([2, 0], dict(z=3))
128
+ )
129
+ # Postional argument provided in keyword.
130
+ self.assertEqual(
131
+ callable_ext.PresetArgValue.resolve_args(
132
+ call_args=[],
133
+ call_kwargs=dict(x=2),
134
+ positional_arg_names=['x', 'y'],
135
+ arg_defaults={
136
+ 'x': callable_ext.PresetArgValue(),
137
+ 'y': 0,
138
+ 'z': callable_ext.PresetArgValue(default=2),
139
+ },
140
+ preset_kwargs=dict(x=1, y=2, z=3, w=4)
141
+ ),
142
+ ([2, 0], dict(z=3))
143
+ )
144
+ # Postional argument provided in keyword, and there are more args
145
+ # (due to varargs)
146
+ self.assertEqual(
147
+ callable_ext.PresetArgValue.resolve_args(
148
+ call_args=[1, 2, 3],
149
+ call_kwargs=dict(x=2),
150
+ positional_arg_names=['x', 'y'],
151
+ arg_defaults={
152
+ 'x': callable_ext.PresetArgValue(),
153
+ 'y': 0,
154
+ 'z': callable_ext.PresetArgValue(default=2),
155
+ },
156
+ preset_kwargs=dict(x=1, y=2, z=3, w=4)
157
+ ),
158
+ ([1, 2, 3], dict(z=3))
159
+ )
160
+ # Required preset argument is not provided.
161
+ with self.assertRaisesRegex(ValueError, 'Argument .* is not present.'):
162
+ callable_ext.PresetArgValue.resolve_args(
163
+ call_args=[],
164
+ call_kwargs=dict(),
165
+ positional_arg_names=['x'],
166
+ arg_defaults={
167
+ 'x': callable_ext.PresetArgValue(),
168
+ },
169
+ preset_kwargs=dict()
170
+ )
171
+
172
+ # Include all preset kwargs.
173
+ self.assertEqual(
174
+ callable_ext.PresetArgValue.resolve_args(
175
+ call_args=[],
176
+ call_kwargs=dict(),
177
+ positional_arg_names=['x', 'y'],
178
+ arg_defaults={
179
+ 'x': callable_ext.PresetArgValue(),
180
+ 'y': 0,
181
+ 'z': callable_ext.PresetArgValue(default=2),
182
+ },
183
+ preset_kwargs=dict(x=1, y=2, z=3, w=4),
184
+ include_all_preset_kwargs=True,
185
+ ),
186
+ ([1, 0], dict(z=3, w=4))
187
+ )
188
+
189
+ def test_preset_args(self):
190
+ @callable_ext.enable_preset_args()
191
+ def foo(
192
+ x=callable_ext.PresetArgValue(),
193
+ y=1,
194
+ *args,
195
+ z=callable_ext.PresetArgValue(default=2)
196
+ ):
197
+ del args
198
+ return x + y + z
199
+
200
+ with self.assertRaisesRegex(ValueError, 'Argument \'x\' is not present.'):
201
+ foo()
202
+
203
+ with callable_ext.preset_args(dict(x=1)):
204
+ self.assertEqual(foo(), 1 + 1 + 2)
205
+
206
+ # `y`` should not take precedence over the non-preset default.
207
+ with callable_ext.preset_args(dict(x=1, y=2)):
208
+ self.assertEqual(foo(), 1 + 1 + 2)
209
+
210
+ with callable_ext.preset_args(dict(x=1, y=2, z=3)):
211
+ self.assertEqual(foo(3), 3 + 1 + 3)
212
+
213
+ with callable_ext.preset_args(dict(x=1, y=2, z=3)):
214
+ self.assertEqual(foo(3, 3, z=4), 3 + 3 + 4)
215
+
216
+ def test_enable_preset_args(self):
217
+
218
+ # No side-effect if function does not have PresetArgValue.
219
+ def bar(x, y):
220
+ return x + y
221
+ self.assertIs(bar, callable_ext.enable_preset_args()(bar))
222
+
223
+ # `include_all_preset_kwargs` sets to False.
224
+ @callable_ext.enable_preset_args()
225
+ def baz(x, y=callable_ext.PresetArgValue(default=1), **kwargs):
226
+ return x + y + sum(kwargs.values())
227
+
228
+ with callable_ext.preset_args(dict(z=3, p=4)):
229
+ self.assertEqual(baz(1), 1 + 1)
230
+
231
+ # `include_all_prset_kwargs` is effective only when there is varkw.
232
+ @callable_ext.enable_preset_args(include_all_preset_kwargs=True)
233
+ def foo(x, y=callable_ext.PresetArgValue(default=1), **kwargs):
234
+ return x + y + sum(kwargs.values())
235
+
236
+ with callable_ext.preset_args(dict(z=3, p=4)):
237
+ self.assertEqual(foo(1), 1 + 1 + 3 + 4)
238
+
239
+ # `include_all_preset_kwargs` should be ignored if there is no varkw.
240
+ @callable_ext.enable_preset_args(include_all_preset_kwargs=True)
241
+ def fuz(x, y=callable_ext.PresetArgValue(default=1)):
242
+ return x + y
243
+
244
+ with callable_ext.preset_args(dict(y=2, z=3)):
245
+ self.assertEqual(fuz(1), 1 + 2)
246
+
247
+ def test_preset_args_nesting(self):
248
+ @callable_ext.enable_preset_args()
249
+ def foo(
250
+ x=callable_ext.PresetArgValue(),
251
+ y=1,
252
+ *,
253
+ z=callable_ext.PresetArgValue(default=2)
254
+ ):
255
+ return x + y + z
256
+
257
+ def bar(inherit_preset: bool = False, **kwargs):
258
+ with callable_ext.preset_args(
259
+ {k: v + 1 for k, v in kwargs.items()},
260
+ inherit_preset=inherit_preset
261
+ ):
262
+ return foo()
263
+
264
+ with callable_ext.preset_args(dict(x=1)):
265
+ self.assertEqual(foo(), 1 + 1 + 2)
266
+
267
+ self.assertEqual(bar(x=1), 2 + 1 + 2)
268
+ self.assertEqual(bar(x=1, z=2), 2 + 1 + 3)
269
+ self.assertEqual(bar(x=1, z=3), 2 + 1 + 4)
270
+
271
+ with self.assertRaisesRegex(ValueError, 'Argument \'x\' is not present.'):
272
+ bar()
273
+ self.assertEqual(bar(inherit_preset=True), 1 + 1 + 2)
274
+
275
+
21
276
  class CallWithOptionalKeywordArgsTest(unittest.TestCase):
22
277
  """Tests for typing.CallWithOptionalKeywordArgs."""
23
278