bpo-38605: Make postponed evaluation of annotations default by isidentical · Pull Request #20434 · python/cpython (original) (raw)

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Conversation61 Commits18 Checks0 Files changed

Conversation

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters

[ Show hidden characters]({{ revealButtonHref }})

isidentical

[This is a draft for my public work in progress PoC, feel free to create another PR if you can successfully pass the test suite with the least breakage]
Todo:

https://bugs.python.org/issue38605

vstinner

vstinner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, the whole change looks like the right approach. I will wait until the PR is not marked as draft to review it in depth. Thanks for working on this issue!

@isidentical

Overall, the whole change looks like the right approach. I will wait until the PR is not marked as draft to review it in depth.

Thanks! As far as I'm aware there are only 2 things that currently hold me from marking this PR as ready to review, one is some silly typing failures (will look them) and the other one is issue 40794.

@isidentical

gvanrossum

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is in part on me -- I started a review but never finished it. IIRC there were also some unresolved problems, but I don't know if they are still unresolved.

Anyway, here are my (very old) review comments that I never sent out.

@isidentical

I think this is in part on me -- I started a review but never finished it. IIRC there were also some unresolved problems, but I don't know if they are still unresolved.

I'm giving a rebase right now, and try to merge the latest typing changes on get_type_hints etc with current version. Please do not review until I push the latest changes (at worst tomorrow)

@isidentical

@isidentical

Found a different example for double-stringified sources in dataclasses (this used to work, but now it can't get parsed by the static regex in the dataclasses module since now there are extra quotes);

import typing
from dataclasses import dataclass

@dataclass
class T:
    a: "typing.ClassVar[int]"

T()

We can either handle it like how we do in the ForwardRef, or solve these all problems completely in the compiler level by doing something like this;

+++ b/Python/compile.c @@ -2016,7 +2016,15 @@ error: static int compiler_visit_annexpr(struct compiler *c, expr_ty annotation) {

Any suggestions @gvanrossum?

@gvanrossum

I don't think that solves it completely, does it? ISTM we still get double quotes when the annotation contains a string literal as a generic parameter (e.g., list["int"]). And it doesn't produce the same result with the future import in 3.9. It also seems quite inconsistent to say "annotations get stringified except if they are already strings" -- this makes it impossible to reconstruct the original annotation by un-stringifying.

I'd rather fix this in dataclasses.py and backport the fix to 3.9.1 (since it's clearly too late for 3.9.0 :-).

@isidentical

gvanrossum

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry that people do introspection on dataclasses and will be confused by finding strings instead of type objects. But I don't know what else to do. I somehow think not too many people outside Facebook have been using from __future__ import annotations... :-(

I also worry about the change in behavior in the inspect module. But I think you're over the hump and we can soon land this...

@isidentical

As a side effect, this now folds into Optional[int]

@dataclass class C: x: Union[int, type(None)] = None

@isidentical

@isidentical

gvanrossum

@gvanrossum

As a side effect, this now folds into Optional[int]

@dataclass class C: x: Union[int, type(None)] = None

But note that type(None) is invalid according to PEP 484 -- it should just be None.

@isidentical

But note that type(None) is invalid according to PEP 484 -- it should just be None.

I just copied over the test case, my point was we are changing the shape of a declaration;

>>> from typing import *
>>> def x(a: Union[int, None]): pass
... 
>>> inspect.signature(x)
<Signature (a: Optional[int])>

But it is not much of a big deal, I guess, just wanted to mention about it

@gvanrossum

But note that type(None) is invalid according to PEP 484 -- it should just be None.

I just copied over the test case, my point was we are changing the shape of a declaration;

>>> from typing import *
>>> def x(a: Union[int, None]): pass
... 
>>> inspect.signature(x)
<Signature (a: Optional[int])>

But it is not much of a big deal, I guess, just wanted to mention about it

Hm, your comment was not linked to any particular line of code.

FWIW that behavior is built into typing.Union:

import typing typing.Union[int, None] typing.Optional[int]

@isidentical

@isidentical

gvanrossum

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Slight wording changes. I'll apply these and then hopefully the test flake will go away, and then I'll land it. Fingers crossed! And thanks for all the work put into this -- I betcha you didn't expect it to be this subtle. (I know I didn't.)

@gvanrossum

@isidentical

I betcha you didn't expect it to be this subtle. (I know I didn't.)

Indeed!

@vstinner

shihai1991 added a commit to shihai1991/cpython that referenced this pull request

Oct 9, 2020

@shihai1991

xzy3 pushed a commit to xzy3/cpython that referenced this pull request

Oct 18, 2020

@isidentical

…honGH-20434)

The hard part was making all the tests pass; there are some subtle issues here, because apparently the future import wasn't tested very thoroughly in previous Python versions.

For example, inspect.signature() returned type objects normally (except for forward references), but strings with the future import. We changed it to try and return type objects by calling typing.get_type_hints(), but fall back on returning strings if that function fails (which it may do if there are future references in the annotations that require passing in a specific namespace to resolve).

Reviewers

@gvanrossum gvanrossum gvanrossum approved these changes

@ericvsmith ericvsmith Awaiting requested review from ericvsmith

@ilevkivskyi ilevkivskyi Awaiting requested review from ilevkivskyi

@rhettinger rhettinger Awaiting requested review from rhettinger

@vstinner vstinner Awaiting requested review from vstinner