Skip to content

Instantly share code, notes, and snippets.

@Conchylicultor
Last active April 20, 2022 13:04
Show Gist options
  • Save Conchylicultor/d41f3637e44be7dcd361af37b597451d to your computer and use it in GitHub Desktop.
Save Conchylicultor/d41f3637e44be7dcd361af37b597451d to your computer and use it in GitHub Desktop.
PEP 649 - ForwardRef
import dataclasses
import typing
from typing import *
TypeAlias = Any
# ******* Implementation *******
@dataclasses.dataclass
class ForwardRef:
resolve: Callable[[], Any]
def type_hints(cls):
return {
k: resolve_forward_ref(v) for k, v in cls.__annotations__.items()
}
def resolve_forward_ref(hint: TypeAlias):
origin = typing.get_origin(hint)
return _ORIGIN_TO_RESOLVER[origin](hint)
def _list_resolver(hint: TypeAlias):
(item_hint,) = typing.get_args(hint)
return list[resolve_forward_ref(item_hint)]
def _union_resolver(hint: TypeAlias):
item_hints = typing.get_args(hint)
return Union[tuple(resolve_forward_ref(i) for i in item_hints)]
def _default_resolver(hint: TypeAlias):
if isinstance(hint, ForwardRef):
return hint.resolve()
return hint
_ORIGIN_TO_RESOLVER = {
list: _list_resolver,
typing.Union: _union_resolver,
None: _default_resolver,
}
# ******* Example *******
@dataclasses.dataclass
class User:
name: str
group: ForwardRef(lambda: Group)
@dataclasses.dataclass
class Group:
name: str
admins: list[ForwardRef(lambda: User)]
def fn():
@dataclasses.dataclass
class User0:
name: str
group: ForwardRef(lambda: Group0)
@dataclasses.dataclass
class Group0:
name: str
admins: list[ForwardRef(lambda: User0)]
return User0, Group0
cls0, cls1 = fn()
print(type_hints(User))
print(type_hints(Group))
print(type_hints(cls0))
print(type_hints(cls1))
@Conchylicultor
Copy link
Author

This display:

{'name': <class 'str'>, 'group': <class '__main__.Group'>}
{'name': <class 'str'>, 'admins': list[__main__.User]}
{'name': <class 'str'>, 'group': <class '__main__.fn.<locals>.Group0'>}
{'name': <class 'str'>, 'admins': list[__main__.fn.<locals>.User0]}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment