Title: PEP 585 and ForwardRef
Type: behavior Stage: patch review
Components: Versions: Python 3.9
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: BTaskaya, eric.smith, gvanrossum, joperez, kj, levkivskyi, lukasz.langa, miss-islington
Priority: normal Keywords: patch

Created on 2020-07-22 20:16 by joperez, last changed 2021-04-19 15:28 by wyz23x2.

Pull Requests
URL Status Linked Edit
PR 25183 merged kj, 2021-04-04 14:43
PR 25184 merged miss-islington, 2021-04-04 15:14
Messages (6)
msg374105 - (view) Author: Joseph Perez (joperez) * Date: 2020-07-22 20:16
PEP 585 current implementation (3.10.0a0) differs from current Generic implementation about ForwardRef, as illustrated bellow:
from dataclasses import dataclass, field
from typing import get_type_hints, List, ForwardRef

class Node:
    children: list["Node"] = field(default_factory=list)
    children2: List["Node"] = field(default_factory=list)

assert get_type_hints(Node) == {"children": list["Node"], "children2": List[Node]}
assert List["Node"].__args__ == (ForwardRef("Node"),)
assert list["Node"].__args__ == ("Node",) # No ForwardRef here, so no evaluation by get_type_hints
There is indeed no kind of ForwardRef for `list` arguments. As shown in the example, this affects the result of get_type_hints for recursive types handling.

He could be "fixed" in 2 lines in `typing._eval_type` with something like this :
def _eval_type(t, globalns, localns, recursive_guard=frozenset()):
    if isinstance(t, str):
        t = ForwardRef(t)
    if isinstance(t, ForwardRef):
but it's kind of hacky/dirty.

It's true that this issue will not concern legacy code, 3.9 still being not released. So developers of libraries using get_type_hints could add in their documentation that `from __future__ import annotations` is mandatory for recursive types with PEP 585 (I think I will do it).

By the way, Guido has quickly given his opinion about it in PR 21553: "We probably will not ever support this: importing ForwardRef from the built-in generic alias code would be problematic, and once from __future__ import annotations is always on there's no need to quote the argument anyway." (So feel free to close this issue)
msg374107 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-07-22 20:19
I think mentioning this in the docs is the best we can do in 3.9, and for 3.10 the point will be moot. The next release is release candidate 1, so we're well past the point where we can implement new functionality.
msg374109 - (view) Author: Joseph Perez (joperez) * Date: 2020-07-22 20:38
However, PEP 563 will not solve the recursive type alias issue like `A = list["A"]` but this is a minor concern.
msg374291 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-07-25 22:08
Hm, recursive type aliases are an interesting issue. We may be able to do better there for 3.10, even if we can't fix it for 3.9 (or at least not for 3.9.0).

But in the meantime maybe you can come up with a PR that adds a note to the typing docs in 3.10 explaining that `list["int"]` will not be resolved to `list[int]`, even though it works for `List["int"]`?
msg390194 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2021-04-04 15:14
New changeset 2b5913b4ee5852a28ca1509478f5582beb3aff7b by Ken Jin in branch 'master':
bpo-41370: Add note about ForwardRefs and PEP585 generic types in docs (#25183)
msg390196 - (view) Author: miss-islington (miss-islington) Date: 2021-04-04 15:36
New changeset d56bcf915b8d5a6afe4555cb6813c8210824e751 by Miss Islington (bot) in branch '3.9':
[3.9] bpo-41370: Add note about ForwardRefs and PEP585 generic types in docs (GH-25183) (GH-25184)
Date User Action Args
2021-04-19 15:28:28wyz23x2setnosy: - wyz23x2
2021-04-04 15:36:33miss-islingtonsetmessages: + msg390196
2021-04-04 15:14:59miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request23926
2021-04-04 15:14:55gvanrossumsetmessages: + msg390194
2021-04-04 14:43:24kjsetnosy: + kj
pull_requests: + pull_request23925
2020-09-10 11:58:46wyz23x2setpull_requests: - pull_request21248
2020-09-10 11:53:35wyz23x2setpull_requests: + pull_request21248
2020-09-10 11:52:55wyz23x2setpull_requests: - pull_request21247
2020-09-10 11:30:17wyz23x2setpull_requests: + pull_request21247
2020-09-10 11:28:59wyz23x2setpull_requests: - pull_request21245
2020-09-10 11:24:23wyz23x2setkeywords: + patch
nosy: + wyz23x2

pull_requests: + pull_request21245
stage: patch review
2020-08-03 23:39:26vstinnersetnosy: - vstinner
2020-07-25 22:08:37gvanrossumsetmessages: + msg374291
2020-07-22 20:38:41joperezsetmessages: + msg374109
2020-07-22 20:19:34gvanrossumsetmessages: + msg374107
2020-07-22 20:16:14joperezcreate