ericvsmith / dataclasses

Apache License 2.0
584 stars 53 forks source link

TypeError: __new__() got multiple values for argument 'cls' #155

Closed omry closed 4 years ago

omry commented 4 years ago

Thanks for the dataclasses package. Using it on Python 3.6, I am hitting the following problem (which does not appear with native dataclasses in 3.7+):

@dataclass
class PluginConf1(Dict[str, Any]):
    cls: str

PluginConf1(cls="ff")

results in:

tests/test_utils.py:None (tests/test_utils.py)
test_utils.py:150: in <module>
    PluginConf1(cls="ff")
E   TypeError: __new__() got multiple values for argument 'cls'
omry commented 4 years ago

This is specific to extending Dict[str, Any]. (which may seem weird, but is really exactly what I need).

cgerum commented 4 years ago

Just hit the same error. Any news on this one?

ericvsmith commented 4 years ago

Sorry, all of my "volunteer" time has been taken up by bitbucket retiring mercurial. I'm still in the middle of abandoning bitbucket.

I'm not sure what can be done about this. help(PluginConf1) in 3.7 gives:

 |  ----------------------------------------------------------------------
 |  Static methods inherited from builtins.dict:
 |
 |  __new__(*args, **kwargs) from builtins.type
 |      Create and return a new object.  See help(type) for accurate signature.
 |  ----------------------------------------------------------------------

While 3.6 is:

 |  Static methods inherited from typing.Dict:
 |
 |  __new__(cls, *args, **kwds)
 |      Create and return a new object.  See help(type) for accurate signature.
 |
 |  ----------------------------------------------------------------------

I'm open to suggestions, but I don't see what dataclasses can do here.

cgerum commented 4 years ago

You are absolutely right. I think this cannot and should not be handled in dataclasses.

Thanks a lot for your help.

omry commented 4 years ago

Are you saying that inheriting from a Dict[str, Any] is broken in 3.6 regardless of the dataclasses backport?

cgerum commented 4 years ago

Yes the culprit is the parameter named cls here in typing: https://github.com/python/cpython/blob/93514bd24447d8dd1579ac838e2d8915a1bbc17f/Lib/typing.py#L2030 .

Just leave out the @dataclass from your example and it still fails with the same error. I will post some more details in https://github.com/facebookresearch/hydra/issues/721 shortly, but I think this ticket can be closed.

omry commented 4 years ago

Well shit. such bad luck clashing with the variable name there. Thanks for pointing it out. I will consider changing it (this is used by plugins so it's a bit disruptive).

I just created a repro:

from dataclasses import dataclass
from typing import Dict, Any

@dataclass
class PluginConf1(Dict[str, Any]):
    cls: str

try:
    PluginConf1(cls="ff")
except Exception as ex:
    print("PluginConf1 failed", ex)

class SimpleClass(Dict[str, Any]):
    def __init__(self, cls: str):
        self.cls = cls

try:
    SimpleClass(cls="ff")
except Exception as ex:
    print("SimpleClass failed", ex)
omry commented 4 years ago

Closing as this has nothing to do with your package. Thanks.

ericvsmith commented 4 years ago

Thanks.