classification
Title: dataclass signatures and docstrings w/future-annotations
Type: Stage:
Components: Versions:
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: BTaskaya, eric.smith, gvanrossum, lukasz.langa, yselivanov
Priority: normal Keywords:

Created on 2020-05-27 12:48 by BTaskaya, last changed 2020-05-27 15:50 by vstinner.

Files
File name Uploaded Description Edit
script.py BTaskaya, 2020-05-27 12:48
Messages (12)
msg370073 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python triager) Date: 2020-05-27 12:48
While I was working on making 'future annotations' default, I noticed that dataclasses acts differently under the annotation feature. One example would be the file [signature.py]:

[ without future import]
 $ python t.py
X(a: int, b: int)
[ with future import]
 $ python t.py
X(a: '_type_a', b: '_type_b') -> '_return_type'

This is causing too much test to fail,
AssertionError: '_return_type' is not None

- C(x:'_type_x')->'_return_type'
+ C(x:collections.deque)

- C(x:'_type_x'=<factory>)->'_return_type'
+ C(x:collections.deque=<factory>)

- C(x:'_type_x')->'_return_type'
+ C(x:List[int])

(and more)
msg370078 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-05-27 13:42
It,sounds like you are trying to get the effect of putting 'from __future__ import dataclasses' at the top of dataclasses'.py, right? Are you saying that without this, the output of the test script is correct?
msg370079 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python triager) Date: 2020-05-27 13:45
> It,sounds like you are trying to get the effect of putting 'from __future__ import dataclasses' at the top of dataclasses'.py, right?

Yes, since compile will automatically inherit the flags of the current frame to the compiled code I'm basically inserting a 'future annotations' import at the top of the file. 

> Are you saying that without this, the output of the test script is correct?

Yes.
msg370083 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-05-27 13:50
Have you come up with a fix yet? (Preferably a fix that can be applied locally to dataclasses.py.)
msg370084 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python triager) Date: 2020-05-27 13:51
> Have you come up with a fix yet? (Preferably a fix that can be applied locally to dataclasses.py.)

I'm working on it, but no luck so far.
msg370085 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-05-27 13:56
Hmm. That's a regression, at least from 3.7, which is the only version I have ready access to:

$ python3
Python 3.7.3 (default, Mar 27 2019, 13:36:35) 
[GCC 9.0.1 20190227 (Red Hat 9.0.1-0.8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dataclasses
>>> @dataclasses.dataclass
... class X:
...   a: int
...   b:int
... 
>>> X.__doc__
'X(a: int, b: int)'
>>> 

$ python3
Python 3.7.3 (default, Mar 27 2019, 13:36:35) 
[GCC 9.0.1 20190227 (Red Hat 9.0.1-0.8)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from __future__ import annotations
>>> import dataclasses
>>> @dataclasses.dataclass
... class X:
...   a: int
...   b:int
... 
>>> X.__doc__
"X(a: 'int', b: 'int')"
msg370086 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python triager) Date: 2020-05-27 14:22
> Hmm. That's a regression, at least from 3.7, which is the only version I have ready access to:

That is the same behavior with the current master, the problem I am having is related to using annotations feature on dataclasses itself rather than the program that imports it. I've tested script.py on 3.7.5 and it gives the same output.
msg370090 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-05-27 14:58
To clarify, for Eric: what Batuhan did is effectively adding `from __future__ import annotations` to the top of dataclasses.py.

I believe the root cause is that dataclasses creates functions by synthesizing `def` statements (in _create_fn()) and the annotations there are references to variables in a dedicated namespace. Maybe we should patch the __annotations__ attribute of the result before sticking it into the class?
msg370092 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-05-27 15:14
I see. Not sure how I overlooked that. Thanks.

At first blush, I think your approach would work.
msg370095 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python triager) Date: 2020-05-27 15:37
I have applied Guido's suggestion and it looks like it is working.
msg370096 - (view) Author: Batuhan Taskaya (BTaskaya) * (Python triager) Date: 2020-05-27 15:37
(I applied it to my own branch, don't know if a seperate PR needed)
msg370097 - (view) Author: Guido van Rossum (gvanrossum) * (Python committer) Date: 2020-05-27 15:42
You can do this as part of your mega-PR to turn on `from __future__ import annotations` by default.
History
Date User Action Args
2020-05-27 15:50:39vstinnersetnosy: - vstinner
2020-05-27 15:42:49gvanrossumsetmessages: + msg370097
2020-05-27 15:37:35BTaskayasetmessages: + msg370096
2020-05-27 15:37:04BTaskayasetmessages: + msg370095
2020-05-27 15:14:42eric.smithsetmessages: + msg370092
2020-05-27 14:58:41gvanrossumsetmessages: + msg370090
2020-05-27 14:22:42BTaskayasetmessages: + msg370086
2020-05-27 13:56:09eric.smithsetmessages: + msg370085
2020-05-27 13:51:57BTaskayasetmessages: + msg370084
2020-05-27 13:50:54gvanrossumsetmessages: + msg370083
2020-05-27 13:45:29BTaskayasetmessages: + msg370079
2020-05-27 13:42:39gvanrossumsetmessages: + msg370078
2020-05-27 13:30:48vstinnersetnosy: + gvanrossum, vstinner, lukasz.langa, yselivanov
2020-05-27 12:48:52BTaskayacreate