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.

Author ARF1
Recipients ARF1, drhagen, eric.smith, lopek
Date 2020-11-19.09:25:33
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1605777934.42.0.570621585203.issue39442@roundup.psfhosted.org>
In-reply-to
Content
One problem I have with the current behaviour is that users of library code need to know the exact namespace in which a library has defined a dataclass.

An example is if a library writer had to deconflict the name of a type he used in a user-facing dataclass.

Below is a "typical" use case which will become very fragile to implement.(E.g. imagine the dataclass with dynamically generated fields, the implementation of which I have neglected for the sake of brevity.)


=== some_library_typing.py ===
mytype = str  # library author defines some type alias


=== some_library_module_a.py ===
from __future__ import annotations
import dataclasses
from some_library_typing import mytype as mytype_deconflicted

mytype = int

@dataclasses.dataclass
class MyClass:
    var1: mytype_deconflicted = 'foo'

    def method1(self, val: mytype) -> mytype:
        return val + 1


=== user_code.py ===
from __future__ import annotations
import dataclasses
from some_library_typing import mytype
from some_library_module_a import MyClass

inst = MyClass('bar')

for f in dataclasses.fields(inst):
    if f.type is mytype:
        print('mytype found')
        break
else:
    print('mytype not found')


The `if f.type is mytype` comparison obviously won't work any more. But neither will `if f.type == 'mytype'`. The user will have to be aware that the library author had to deconflict the identifier `mytype` to `mytype_deconflicted` to write his code.

Of course, the library writer could have written the following to make the code work:

=== some_library_module_a.py ===
from __future__ import annotations
import dataclasses
from some_library_typing import mytype as mytype_deconflicted

mytype = int

@dataclasses.dataclass
class MyClass:
    var1: mytype = 'foo'

    def method1(self, val: mytype)
        return val + 1

That is a phenomenally obscure and counter-intuitive way of writing code!

Whichever way one turns this, the current behaviour either seems to require library authors to take extraordinary care with their namespaces when defining dataclasses or forces them to write hard-to-read code or seems to require from users detailed knowledge about the implementation specifics of a library they use.

If this behaviour is kept as is, some clear warnings and guidance on how to deal with this in practice should be given in the docs. From what I can see in the 3.10 docs, that is not yet the case.
History
Date User Action Args
2020-11-19 09:25:34ARF1setrecipients: + ARF1, eric.smith, drhagen, lopek
2020-11-19 09:25:34ARF1setmessageid: <1605777934.42.0.570621585203.issue39442@roundup.psfhosted.org>
2020-11-19 09:25:34ARF1linkissue39442 messages
2020-11-19 09:25:33ARF1create