pyglove 0.4.5.dev202411020808__py3-none-any.whl → 0.4.5.dev202411040809__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.

Potentially problematic release.


This version of pyglove might be problematic. Click here for more details.

@@ -2612,35 +2612,53 @@ class Union(Generic, ValueSpecBase):
2612
2612
  ],
2613
2613
  root_path: object_utils.KeyPath) -> typing.Any:
2614
2614
  """Union specific apply."""
2615
+ # Match strong-typed candidates first.
2616
+ if not self.type_resolved:
2617
+ return value
2618
+
2615
2619
  for c in self._candidates:
2616
- if (c.type_resolved
2617
- and (c.value_type is None or isinstance(value, c.value_type))):
2620
+ if c.value_type is not None and isinstance(value, c.value_type):
2618
2621
  return c.apply(
2619
2622
  value,
2620
2623
  allow_partial=allow_partial,
2621
2624
  child_transform=child_transform,
2622
- root_path=root_path)
2625
+ root_path=root_path
2626
+ )
2627
+
2628
+ def _try_candidate(c, value) -> typing.Tuple[typing.Any, bool]:
2629
+ try:
2630
+ return c.apply(
2631
+ value, allow_partial=allow_partial,
2632
+ child_transform=child_transform, root_path=root_path
2633
+ ), True
2634
+ except TypeError:
2635
+ return value, False
2636
+
2637
+ # Match non-strong-typed candidates (e.g. Callable).
2638
+ for c in self._candidates:
2639
+ if c.value_type is None:
2640
+ value, success = _try_candidate(c, value)
2641
+ if success:
2642
+ return value
2623
2643
 
2624
2644
  # NOTE(daiyip): This code is to support consider A as B scenario when there
2625
2645
  # is a converter from A to B (converter may return value that is not B). A
2626
2646
  # use case is that tf.Variable is not a tf.Tensor, but value spec of
2627
2647
  # tf.Tensor should be able to accept tf.Variable.
2628
- matched_candidate = None
2629
2648
  for c in self._candidates:
2630
- if c.type_resolved and type_conversion.get_converter(
2631
- type(value), c.value_type) is not None:
2632
- matched_candidate = c
2633
- break
2634
-
2635
- if self.type_resolved:
2636
- # `_apply` is entered only when there is a type match or conversion path.
2637
- assert matched_candidate is not None
2638
- return matched_candidate.apply(
2639
- value, allow_partial, child_transform, root_path)
2640
-
2641
- # Return value directly if the forward declaration of the current union
2642
- # is unsolved.
2643
- return value
2649
+ if c.value_type is None:
2650
+ continue
2651
+ converter = type_conversion.get_converter(type(value), c.value_type)
2652
+ if converter is not None:
2653
+ return c.apply(
2654
+ converter(value),
2655
+ allow_partial=allow_partial,
2656
+ child_transform=child_transform,
2657
+ root_path=root_path
2658
+ )
2659
+ raise TypeError(
2660
+ f'{value!r} does not match any candidate of {self!r}.'
2661
+ )
2644
2662
 
2645
2663
  def _extend(self, base: 'Union') -> None:
2646
2664
  """Union specific extension."""
@@ -11,9 +11,8 @@
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.core.typing.value_specs."""
15
-
16
14
  import contextlib
15
+ import datetime
17
16
  import inspect
18
17
  import sys
19
18
  import typing
@@ -3141,6 +3140,15 @@ class UnionTest(ValueSpecTest):
3141
3140
  with self.assertRaisesRegex(TypeError, 'Expect .* but encountered .*'):
3142
3141
  _ = v.apply('foo')
3143
3142
 
3143
+ # Union with strong-type and non-strong-type candidates.
3144
+ self.assertEqual(
3145
+ vs.Union([typing.Callable[[int], int], str]).apply('foo'), 'foo'
3146
+ )
3147
+ # Union with type conversion.
3148
+ self.assertIsInstance(
3149
+ vs.Union([int, str]).apply(datetime.datetime.now()), int
3150
+ )
3151
+
3144
3152
  # Bad cases.
3145
3153
  with self.assertRaisesRegex(ValueError, 'Value cannot be None'):
3146
3154
  vs.Union([vs.Int(), vs.Str()]).apply(None)
@@ -3149,6 +3157,11 @@ class UnionTest(ValueSpecTest):
3149
3157
  TypeError, 'Expect \\(.*\\) but encountered <(type|class) \'list\'>.'):
3150
3158
  vs.Union([vs.Int(), vs.Str()]).apply([])
3151
3159
 
3160
+ with self.assertRaisesRegex(
3161
+ TypeError, '1 does not match any candidate of .*'
3162
+ ):
3163
+ vs.Union([typing.Callable[[int], int], str]).apply(1)
3164
+
3152
3165
  def test_is_compatible(self):
3153
3166
  self.assertTrue(
3154
3167
  vs.Union([vs.Int(), vs.Bool()]).is_compatible(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyglove
3
- Version: 0.4.5.dev202411020808
3
+ Version: 0.4.5.dev202411040809
4
4
  Summary: PyGlove: A library for manipulating Python objects.
5
5
  Home-page: https://github.com/google/pyglove
6
6
  Author: PyGlove Authors
@@ -137,8 +137,8 @@ pyglove/core/typing/type_conversion.py,sha256=mOkp2LP2O9C5k8Q6r-CFwk9P_-oy4u26DI
137
137
  pyglove/core/typing/type_conversion_test.py,sha256=AH7HTOfWcF7cpWi49EG6UmB_xfCsdz7HS1U0Bg8o-PI,5295
138
138
  pyglove/core/typing/typed_missing.py,sha256=5lzkrd-DqJDT8eoW1d8p6mxV3mvy5X78zFon7qEqPIA,2784
139
139
  pyglove/core/typing/typed_missing_test.py,sha256=3k_s0JBYBJ_6xoOuPSMrQzqas6QHD0PHux0T9NlTBZc,2381
140
- pyglove/core/typing/value_specs.py,sha256=8GdhOP0WLJR7cdmW6rjYrCStCT8bEBdzSXpez88TJs0,99420
141
- pyglove/core/typing/value_specs_test.py,sha256=Z1VcD4s8XgxiADDyTrSHUZTCtDBe4f_84cSfHL6H_Xw,122287
140
+ pyglove/core/typing/value_specs.py,sha256=V6m4RhCc4yi6H8X1LoptSk5gsa7ko8HgLYDSfVsMBtQ,99874
141
+ pyglove/core/typing/value_specs_test.py,sha256=kKwoEmGIXtM5JikhtbhcE4Ds-wSyYAsMTozHVa2Lpbc,122707
142
142
  pyglove/core/views/__init__.py,sha256=hPqM3agvS3skQmLmZyV-5ai9vkhzJI65RLXmS9P-mOI,928
143
143
  pyglove/core/views/base.py,sha256=yuDHX5g1MgqyeVJLJPpWeh33opEafPygV1fjIOshWLE,26163
144
144
  pyglove/core/views/base_test.py,sha256=F6nou7reS_Kmr2H57MUgcnc1bIp9Z3BWCvHOvMqjGkQ,16642
@@ -186,8 +186,8 @@ pyglove/ext/scalars/randoms.py,sha256=LkMIIx7lOq_lvJvVS3BrgWGuWl7Pi91-lA-O8x_gZs
186
186
  pyglove/ext/scalars/randoms_test.py,sha256=nEhiqarg8l_5EOucp59CYrpO2uKxS1pe0hmBdZUzRNM,2000
187
187
  pyglove/ext/scalars/step_wise.py,sha256=IDw3tuTpv0KVh7AN44W43zqm1-E0HWPUlytWOQC9w3Y,3789
188
188
  pyglove/ext/scalars/step_wise_test.py,sha256=TL1vJ19xVx2t5HKuyIzGoogF7N3Rm8YhLE6JF7i0iy8,2540
189
- pyglove-0.4.5.dev202411020808.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
190
- pyglove-0.4.5.dev202411020808.dist-info/METADATA,sha256=OFXogc-n-WTnIvBpoY6reTyUuXwvVN0ZyWGPWxkRBSY,6666
191
- pyglove-0.4.5.dev202411020808.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
192
- pyglove-0.4.5.dev202411020808.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
193
- pyglove-0.4.5.dev202411020808.dist-info/RECORD,,
189
+ pyglove-0.4.5.dev202411040809.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
190
+ pyglove-0.4.5.dev202411040809.dist-info/METADATA,sha256=PIAhj3B5lKnusm1pN4l9UmtRfS2T8KHfU6flxqQJ9-E,6666
191
+ pyglove-0.4.5.dev202411040809.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
192
+ pyglove-0.4.5.dev202411040809.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
193
+ pyglove-0.4.5.dev202411040809.dist-info/RECORD,,