Skip to content

Commit c584480

Browse files
committed
fix: handle forward ref when python 3.10 and lower
1 parent 4e0b5a6 commit c584480

2 files changed

Lines changed: 30 additions & 3 deletions

File tree

mode/utils/objects.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,20 @@ def _detect_main_name() -> str: # pragma: no cover
257257
return ".".join([*seen, path.stem])
258258

259259

260+
def _normalize_forwardref(t):
261+
if isinstance(t, str):
262+
return t
263+
origin = getattr(t, "__origin__", None)
264+
args = getattr(t, "__args__", None)
265+
if origin and args:
266+
if origin is ClassVar:
267+
return origin[_normalize_forwardref(args[0])]
268+
return origin[tuple(_normalize_forwardref(a) for a in args)]
269+
if hasattr(t, "__qualname__") and "<locals>" in t.__qualname__:
270+
return t.__name__
271+
return t
272+
273+
260274
def annotations(
261275
cls: type,
262276
*,
@@ -325,7 +339,12 @@ def annotations(
325339
localns=localns,
326340
)
327341
)
328-
return fields, defaults
342+
343+
# Normalize all field types for forward refs
344+
normalized_fields = {
345+
k: _normalize_forwardref(v) for k, v in fields.items()
346+
}
347+
return normalized_fields, defaults
329348

330349

331350
def local_annotations(

tests/unit/utils/test_objects.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
InvalidAnnotation,
1616
KeywordReduce,
1717
Unordered,
18+
_normalize_forwardref,
1819
_remove_optional,
1920
_restore_from_keywords,
2021
annotations,
@@ -186,13 +187,17 @@ class X:
186187

187188
fields, defaults = annotations(X, globalns=globals(), localns=locals())
188189

189-
assert fields == {
190+
expected = {
190191
"Foo": ClassVar[int],
191192
"foo": int,
192193
"bar": list[X],
193194
"baz": Union[list[X], str],
194195
"mas": int,
195196
}
197+
198+
norm_fields = {k: _normalize_forwardref(v) for k, v in fields.items()}
199+
norm_expected = {k: _normalize_forwardref(v) for k, v in expected.items()}
200+
assert norm_fields == norm_expected
196201
assert defaults["mas"] == 3
197202

198203

@@ -208,12 +213,15 @@ class X:
208213
X, globalns=globals(), localns=locals(), skip_classvar=True
209214
)
210215

211-
assert fields == {
216+
expected = {
212217
"foo": int,
213218
"bar": list[X],
214219
"baz": Union[list[X], str],
215220
"mas": int,
216221
}
222+
norm_fields = {k: _normalize_forwardref(v) for k, v in fields.items()}
223+
norm_expected = {k: _normalize_forwardref(v) for k, v in expected.items()}
224+
assert norm_fields == norm_expected
217225
assert defaults["mas"] == 3
218226

219227

0 commit comments

Comments
 (0)