This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: typing: forward references don't understand special type forms
Type: behavior Stage: resolved
Components: Library (Lib) Versions: Python 3.11, Python 3.10, Python 3.9
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: Nosy List: AlexWaygood, GBeauregard, JelleZijlstra, gvanrossum, kj, miss-islington, sobolevn
Priority: normal Keywords: patch

Created on 2022-01-26 20:30 by GBeauregard, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Pull Requests
URL Status Linked Edit
PR 30926 merged GBeauregard, 2022-01-26 20:31
PR 30946 merged miss-islington, 2022-01-27 03:18
PR 30947 merged miss-islington, 2022-01-27 03:18
Messages (8)
msg411790 - (view) Author: Gregory Beauregard (GBeauregard) * Date: 2022-01-26 20:30
Consider the following code on 3.11 main:

```
from typing import Annotated, ClassVar, get_type_hints

class DC:
    a: ClassVar[int] = 3
    b: ClassVar["int"] = 3
    c: "ClassVar[int]" = 3
    d: Annotated[ClassVar[int], (2, 5)] = 3
    e: Annotated[ClassVar["int"], (2, 5)] = 3
    f: "Annotated[ClassVar[int], (2, 5)]" = 3

class DC_Special_ForwardRef:
    g: Annotated["ClassVar[int]", (] = 3

# OK
assert get_type_hints(DC, globals(), locals()) == {
    "a": ClassVar[int],
    "b": ClassVar[int],
    "c": ClassVar[int],
    "d": ClassVar[int],
    "e": ClassVar[int],
    "f": ClassVar[int],
}

# TypeError: typing.ClassVar[int] is not valid as type argument
get_type_hints(DC_Special_ForwardRef, globals(), locals())
```

Currently, the `Annotated["ClassVar[int]", (2, 5)]` annotation raises at runtime when `get_type_hints` is called, but all the other forward reference annotations are okay.

My understanding is this is because when typing._type_check runs on a type where special forms are allowed it's possible for the typing._type_convert it calls it itself run a typing._type_check on contained forward references. However, if that forward reference was itself a special form then it's possible to get an error because typing._type_check doesn't pass on that special forms are allowed.

I have drafted a patch to pass on this information. This will become important in the future as more special forms are allowed to wrap each other, such as allowing Final and ClassVar to nest each other in dataclasses, or when Required and NotRequired land. In the future we may also want to reconsider runtime restrictions on special forms in `typing.py` entirely and instead choose to leave this to type checkers.

Is my analysis/patch approach okay? Forward references can be tricky. Should we be discussing runtime restrictions in typing.py more generally in the future?
msg411792 - (view) Author: Gregory Beauregard (GBeauregard) * Date: 2022-01-26 20:48
typo: the line is `g: Annotated["ClassVar[int]", (2, 5)] = 3` in the code sample. Somehow I left it at only `(` for the annotation instead of `(2,5)`
msg411794 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2022-01-26 21:23
I wonder if this is at all similar to bpo-41370.
msg411795 - (view) Author: Gregory Beauregard (GBeauregard) * Date: 2022-01-26 21:32
I did try the proposed patch in bpo-41370 and verified it didn't resolve the issue so I'm not certain they strictly overlap, but I also haven't had time to fully digest the underlying issues in bpo-41370 yet.

I think it does have relevance for changes we want to make for dataclasses re: Annotated, though: https://bugs.python.org/issue46511
msg411797 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2022-01-26 21:39
Agree it's not the same issue, but there's similarity -- both are due to putting a stringized annotation (presumably a forward ref) somewhere inside another construct. whether it's list["N"] or Annotated["ClassVar[int]"].
msg411828 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2022-01-27 03:12
New changeset ced50051bb752a7c1e616f4b0c001f37f0354f32 by Gregory Beauregard in branch 'main':
bpo-46539: Pass status of special typeforms to forward references (GH-30926)
https://github.com/python/cpython/commit/ced50051bb752a7c1e616f4b0c001f37f0354f32
msg411896 - (view) Author: miss-islington (miss-islington) Date: 2022-01-27 16:47
New changeset 37577033baadf5f4a30d0998bae7d26f11a694e2 by Miss Islington (bot) in branch '3.9':
bpo-46539: Pass status of special typeforms to forward references (GH-30926)
https://github.com/python/cpython/commit/37577033baadf5f4a30d0998bae7d26f11a694e2
msg411897 - (view) Author: miss-islington (miss-islington) Date: 2022-01-27 16:48
New changeset bfcb41420a326ec353740d8180ffbf402746fa33 by Miss Islington (bot) in branch '3.10':
bpo-46539: Pass status of special typeforms to forward references (GH-30926)
https://github.com/python/cpython/commit/bfcb41420a326ec353740d8180ffbf402746fa33
History
Date User Action Args
2022-04-11 14:59:55adminsetgithub: 90697
2022-01-27 23:11:52AlexWaygoodsetstatus: open -> closed
resolution: fixed
stage: patch review -> resolved
2022-01-27 16:48:12miss-islingtonsetmessages: + msg411897
2022-01-27 16:47:45miss-islingtonsetmessages: + msg411896
2022-01-27 03:18:57miss-islingtonsetpull_requests: + pull_request29126
2022-01-27 03:18:53miss-islingtonsetnosy: + miss-islington
pull_requests: + pull_request29125
2022-01-27 03:12:03gvanrossumsetmessages: + msg411828
2022-01-26 21:39:25gvanrossumsetmessages: + msg411797
2022-01-26 21:32:47GBeauregardsetmessages: + msg411795
2022-01-26 21:23:07gvanrossumsetmessages: + msg411794
2022-01-26 20:48:00GBeauregardsetmessages: + msg411792
2022-01-26 20:41:44GBeauregardsettype: behavior
2022-01-26 20:34:28AlexWaygoodsetnosy: + sobolevn, AlexWaygood
2022-01-26 20:31:13GBeauregardsetkeywords: + patch
stage: patch review
pull_requests: + pull_request29105
2022-01-26 20:30:38GBeauregardcreate