pyglove 0.4.5.dev202502050809__py3-none-any.whl → 0.4.5.dev202502070809__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.
@@ -195,24 +195,64 @@ def annotation_from_str(
195
195
  return t_id
196
196
 
197
197
  def _resolve(type_id: str):
198
+
199
+ def _as_forward_ref() -> typing.ForwardRef:
200
+ return typing.ForwardRef(type_id, False, parent_module) # pytype: disable=not-callable
201
+
198
202
  def _resolve_name(name: str, parent_obj: typing.Any):
199
203
  if name == 'None':
200
- return None
204
+ return None, True
201
205
  if parent_obj is not None and hasattr(parent_obj, name):
202
- return getattr(parent_obj, name)
206
+ return getattr(parent_obj, name), False
203
207
  if hasattr(builtins, name):
204
- return getattr(builtins, name)
208
+ return getattr(builtins, name), True
205
209
  if type_id == '...':
206
- return ...
207
- return utils.MISSING_VALUE
208
- parent_obj = parent_module
209
- for name in type_id.split('.'):
210
- parent_obj = _resolve_name(name, parent_obj)
211
- if parent_obj == utils.MISSING_VALUE:
212
- return typing.ForwardRef( # pytype: disable=not-callable
213
- type_id, False, parent_module
214
- )
215
- return parent_obj
210
+ return ..., True
211
+ return utils.MISSING_VALUE, False
212
+
213
+ names = type_id.split('.')
214
+ if len(names) == 1:
215
+ reference, is_builtin = _resolve_name(names[0], parent_module)
216
+ if is_builtin:
217
+ return reference
218
+ if not is_builtin and (
219
+ # When reference is not found, we should treat it as a forward
220
+ # reference.
221
+ reference == utils.MISSING_VALUE
222
+ # When module is being reloaded, we should treat all non-builtin
223
+ # references as forward references.
224
+ or getattr(parent_module, '__reloading__', False)
225
+ ):
226
+ return _as_forward_ref()
227
+ return reference
228
+
229
+ root_obj, _ = _resolve_name(names[0], parent_module)
230
+ # When root object is not found, we should treat it as a forward reference.
231
+ if root_obj == utils.MISSING_VALUE:
232
+ return _as_forward_ref()
233
+
234
+ parent_obj = root_obj
235
+ # When root object is a module, we should treat reference to its children
236
+ # as non-forward references.
237
+ if inspect.ismodule(root_obj):
238
+ for name in names[1:]:
239
+ parent_obj, _ = _resolve_name(name, parent_obj)
240
+ if parent_obj == utils.MISSING_VALUE:
241
+ raise TypeError(f'{type_id!r} does not exist.')
242
+ return parent_obj
243
+ # When root object is non-module variable of current module, and when the
244
+ # module is being reloaded, we should treat reference to its children as
245
+ # forward references.
246
+ elif getattr(parent_module, '__reloading__', False):
247
+ return _as_forward_ref()
248
+ # When root object is non-module variable of current module, we should treat
249
+ # unresolved reference to its children as forward references.
250
+ else:
251
+ for name in names[1:]:
252
+ parent_obj, _ = _resolve_name(name, parent_obj)
253
+ if parent_obj == utils.MISSING_VALUE:
254
+ return _as_forward_ref()
255
+ return parent_obj
216
256
 
217
257
  root = _maybe_union()
218
258
  if _pos() != len(s):
@@ -27,7 +27,8 @@ from pyglove.core.typing.class_schema import ValueSpec
27
27
 
28
28
 
29
29
  class Foo:
30
- pass
30
+ class Bar:
31
+ pass
31
32
 
32
33
 
33
34
  _MODULE = sys.modules[__name__]
@@ -58,6 +59,18 @@ class AnnotationFromStrTest(unittest.TestCase):
58
59
  annotation_conversion.annotation_from_str('tuple[int, str]'),
59
60
  tuple[int, str]
60
61
  )
62
+ self.assertEqual(
63
+ annotation_conversion.annotation_from_str('list[Foo]', _MODULE),
64
+ list[Foo]
65
+ )
66
+ self.assertEqual(
67
+ annotation_conversion.annotation_from_str('list[Foo.Bar]', _MODULE),
68
+ list[Foo.Bar]
69
+ )
70
+ self.assertEqual(
71
+ annotation_conversion.annotation_from_str('list[Foo.Baz]', _MODULE),
72
+ list[typing.ForwardRef('Foo.Baz', False, _MODULE)]
73
+ )
61
74
 
62
75
  def test_generic_types(self):
63
76
  self.assertEqual(
@@ -139,6 +152,28 @@ class AnnotationFromStrTest(unittest.TestCase):
139
152
  ]
140
153
  )
141
154
 
155
+ def test_reloading(self):
156
+ setattr(_MODULE, '__reloading__', True)
157
+ self.assertEqual(
158
+ annotation_conversion.annotation_from_str(
159
+ 'typing.List[Foo]', _MODULE),
160
+ typing.List[
161
+ typing.ForwardRef(
162
+ 'Foo', False, _MODULE
163
+ )
164
+ ]
165
+ )
166
+ self.assertEqual(
167
+ annotation_conversion.annotation_from_str(
168
+ 'typing.List[Foo.Bar]', _MODULE),
169
+ typing.List[
170
+ typing.ForwardRef(
171
+ 'Foo.Bar', False, _MODULE
172
+ )
173
+ ]
174
+ )
175
+ delattr(_MODULE, '__reloading__')
176
+
142
177
  def test_bad_annotation(self):
143
178
  with self.assertRaisesRegex(SyntaxError, 'Expected type identifier'):
144
179
  annotation_conversion.annotation_from_str('typing.List[]')
@@ -152,6 +187,9 @@ class AnnotationFromStrTest(unittest.TestCase):
152
187
  with self.assertRaisesRegex(SyntaxError, 'Expected "]"'):
153
188
  annotation_conversion.annotation_from_str('typing.Callable[[x')
154
189
 
190
+ with self.assertRaisesRegex(TypeError, '.* does not exist'):
191
+ annotation_conversion.annotation_from_str('typing.Foo', _MODULE)
192
+
155
193
 
156
194
  class FieldFromAnnotationTest(unittest.TestCase):
157
195
  """Tests for Field.fromAnnotation."""
@@ -100,7 +100,6 @@ class ForwardRef(utils.Formattable):
100
100
  def __init__(self, module: types.ModuleType, qualname: str):
101
101
  self._module = module
102
102
  self._qualname = qualname
103
- self._resolved_value = None
104
103
 
105
104
  @property
106
105
  def module(self) -> types.ModuleType:
@@ -129,9 +128,7 @@ class ForwardRef(utils.Formattable):
129
128
  @property
130
129
  def resolved(self) -> bool:
131
130
  """Returns True if the symbol for the name is resolved.."""
132
- if self._resolved_value is None:
133
- self._resolved_value = self._resolve()
134
- return self._resolved_value is not None
131
+ return self._resolve() is not None
135
132
 
136
133
  def _resolve(self) -> Optional[Any]:
137
134
  names = self._qualname.split('.')
@@ -150,14 +147,13 @@ class ForwardRef(utils.Formattable):
150
147
  @property
151
148
  def cls(self) -> Type[Any]:
152
149
  """Returns the resolved reference class.."""
153
- if self._resolved_value is None:
154
- self._resolved_value = self._resolve()
155
- if self._resolved_value is None:
156
- raise TypeError(
157
- f'{self.qualname!r} does not exist in '
158
- f'module {self.module.__name__!r}'
159
- )
160
- return self._resolved_value
150
+ reference = self._resolve()
151
+ if reference is None:
152
+ raise TypeError(
153
+ f'{self.qualname!r} does not exist in '
154
+ f'module {self.module.__name__!r}'
155
+ )
156
+ return reference
161
157
 
162
158
  def format(
163
159
  self,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pyglove
3
- Version: 0.4.5.dev202502050809
3
+ Version: 0.4.5.dev202502070809
4
4
  Summary: PyGlove: A library for manipulating Python objects.
5
5
  Home-page: https://github.com/google/pyglove
6
6
  Author: PyGlove Authors
@@ -109,14 +109,14 @@ pyglove/core/tuning/sample_test.py,sha256=JqwDPy3EPC_VjU9dipk90jj1kovZB3Zb9hAjAl
109
109
  pyglove/core/typing/__init__.py,sha256=MwraQ-6K8NYI_xk4V3oaVSkrPqiU9InDtAgXPSRBvik,14494
110
110
  pyglove/core/typing/annotated.py,sha256=llaajIDj9GK-4kUGJoO4JsHU6ESPOra2SZ-jG6xmsOQ,3203
111
111
  pyglove/core/typing/annotated_test.py,sha256=p1qid3R-jeiOTTxOVq6hXW8XFvn-h1cUzJWISPst2l8,2484
112
- pyglove/core/typing/annotation_conversion.py,sha256=8q4-7uo12DZj1_AnDzF4UWQoplmHHtZ0lYIOlY8xVXo,13889
113
- pyglove/core/typing/annotation_conversion_test.py,sha256=Zl0LSL6z8exwgflb4kDJW2QfrvbixJMW4_7lXcHMl14,16271
112
+ pyglove/core/typing/annotation_conversion.py,sha256=7aMxv5AhC5oYteBtVTRp1no16dFgfGFCLbmxVasrdzQ,15557
113
+ pyglove/core/typing/annotation_conversion_test.py,sha256=tOUM7k_VNiGfBlSy_r6vMKk0lD8gRNT6dqnzBzvhul4,17422
114
114
  pyglove/core/typing/annotation_future_test.py,sha256=ZVLU3kheO2V-nrp-m5jrGMLgGMs4S6RWnJbyD9KbHl4,3746
115
115
  pyglove/core/typing/callable_ext.py,sha256=PiBQWPeUAH7Lgmf2xKCZqgK7N0OSrTdbnEkV8Ph31OA,9127
116
116
  pyglove/core/typing/callable_ext_test.py,sha256=TnWKU4_ZjvpbHZFtFHgFvCMDiCos8VmLlODcM_7Xg8M,10156
117
117
  pyglove/core/typing/callable_signature.py,sha256=DRpt7aShfkn8pb3SCiZzS_27eHbkQ_d2UB8BUhJjs0Q,27176
118
118
  pyglove/core/typing/callable_signature_test.py,sha256=iQmHsKPhJPQlMikDhEyxKyq7yWyXI9juKCLYgKhrH3U,25145
119
- pyglove/core/typing/class_schema.py,sha256=Xf3koEnx150Prqw3WDOP04xr1H8bEkUfMb4AKZcPg3M,54683
119
+ pyglove/core/typing/class_schema.py,sha256=dKmF1dwv-7RmCjnAb412AciYZL3LJCToU5WTJWYLj3Y,54482
120
120
  pyglove/core/typing/class_schema_test.py,sha256=RurRdCyPuypKJ7izgcq9zW3JNHgODiJdQvDn0BDZDjU,29353
121
121
  pyglove/core/typing/custom_typing.py,sha256=qdnIKHWNt5kZAAFdpQXra8bBu6RljMbbJ_YDG2mhAUA,2205
122
122
  pyglove/core/typing/inspect.py,sha256=VLSz1KAunNm2hx0eEMjiwxKLl9FHlKr9nHelLT25iEA,7726
@@ -212,8 +212,8 @@ pyglove/ext/scalars/randoms.py,sha256=LkMIIx7lOq_lvJvVS3BrgWGuWl7Pi91-lA-O8x_gZs
212
212
  pyglove/ext/scalars/randoms_test.py,sha256=nEhiqarg8l_5EOucp59CYrpO2uKxS1pe0hmBdZUzRNM,2000
213
213
  pyglove/ext/scalars/step_wise.py,sha256=IDw3tuTpv0KVh7AN44W43zqm1-E0HWPUlytWOQC9w3Y,3789
214
214
  pyglove/ext/scalars/step_wise_test.py,sha256=TL1vJ19xVx2t5HKuyIzGoogF7N3Rm8YhLE6JF7i0iy8,2540
215
- pyglove-0.4.5.dev202502050809.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
216
- pyglove-0.4.5.dev202502050809.dist-info/METADATA,sha256=IiiuFK9RRBh8I9xh9WW4GM8el-96GLZI9uDK6IAVwho,7067
217
- pyglove-0.4.5.dev202502050809.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
218
- pyglove-0.4.5.dev202502050809.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
219
- pyglove-0.4.5.dev202502050809.dist-info/RECORD,,
215
+ pyglove-0.4.5.dev202502070809.dist-info/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
216
+ pyglove-0.4.5.dev202502070809.dist-info/METADATA,sha256=Z2hvG4oC_XncqvRRXEPayvW1hpjB_PTOUuN55aU2LwQ,7067
217
+ pyglove-0.4.5.dev202502070809.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
218
+ pyglove-0.4.5.dev202502070809.dist-info/top_level.txt,sha256=wITzJSKcj8GZUkbq-MvUQnFadkiuAv_qv5qQMw0fIow,8
219
+ pyglove-0.4.5.dev202502070809.dist-info/RECORD,,