Skip to content
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 and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

default_factory field fails with inherited stdlib dataclass #2424

Closed
3 tasks done
ahirner opened this issue Feb 28, 2021 · 5 comments · Fixed by #2557
Closed
3 tasks done

default_factory field fails with inherited stdlib dataclass #2424

ahirner opened this issue Feb 28, 2021 · 5 comments · Fixed by #2557
Labels
bug V1 Bug related to Pydantic V1.X

Comments

@ahirner
Copy link
Contributor

ahirner commented Feb 28, 2021

Checks

  • I added a descriptive title to this issue
  • I have searched (google, github) for similar issues and couldn't find anything
  • I have read and followed the docs and still think this is a bug

Bug

Output of python -c "import pydantic.utils; print(pydantic.utils.version_info())":

             pydantic version: 1.8
            pydantic compiled: True
                 install path: /Users/dafcok/miniconda3/lib/python3.6/site-packages/pydantic
               python version: 3.6.8 |Anaconda, Inc.| (default, Dec 29 2018, 19:04:46)  [GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)]
                     platform: Darwin-19.6.0-x86_64-i386-64bit
     optional deps. installed: ['devtools', 'dotenv', 'email-validator', 'typing-extensions'
$ pip freeze |grep 'dataclasses\|typing'
dataclasses==0.8
typing==3.6.6
typing-extensions==3.7.4.3
from dataclasses import dataclass, field

from pydantic.dataclasses import dataclass as validated_dataclass

@dataclass
class Base:
    x: str

# doesn't fail
@dataclass
class Thing(Base):
    y: str = field(default_factory=str)

# fails
@validated_dataclass
class ValidatedThing(Base):
    y: str = field(default_factory=str)

dataclasses tries to delete y attribute which isn't set.

tests/test_resources.py:12: in <module>
    class ValidatedThing(Base):
pydantic/dataclasses.py:255: in pydantic.dataclasses.dataclass
    ???
pydantic/dataclasses.py:250: in pydantic.dataclasses.dataclass.wrap
    ???
pydantic/dataclasses.py:158: in pydantic.dataclasses._process_class
    ???
~/lib/python3.6/site-packages/dataclasses.py:958: in dataclass
    return wrap(_cls)
~/lib/python3.6/site-packages/dataclasses.py:950: in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash, frozen)
~/lib/python3.6/site-packages/dataclasses.py:817: in _process_class
    delattr(cls, f.name)
E   AttributeError: y

Also fails on 1.7.1 but not on 1.7. Any ideas? I'd be happy to author a fix.

@ahirner ahirner added the bug V1 Bug related to Pydantic V1.X label Feb 28, 2021
@ahirner
Copy link
Contributor Author

ahirner commented Mar 25, 2021

@PrettyWood What's your take on tackling this issue? AFAICS one has to dig deeper into dynamic type creation from there.

@PrettyWood
Copy link
Member

PrettyWood commented Mar 25, 2021

@ahirner Please have a look at the linked PR. I forgot to add this issue to the list ;)

@troiganto
Copy link

Any development on this? I am currently evaluating pydantic for a project and ran into this issue myself.

Minimal reproduction:

import dataclasses as dc
import typing as t
import pydantic

print(pydantic.utils.version_info())

@pydantic.dataclasses.dataclass
class Example:
    count: int = pydantic.Field(0)
    names: t.List[str] = pydantic.Field(default_factory=list)
print(Example())

@dc.dataclass
class Example:
    count: int = dc.field(default=0)
    names: t.List[str] = dc.field(default_factory=list)
print(Example())

Example = pydantic.dataclasses.dataclass(Example)
print(Example())

Output:

             pydantic version: 1.9.0
            pydantic compiled: True
                 install path: /opt/venvs/default/lib/python3.7/site-packages/pydantic
               python version: 3.7.10 (default, Mar 30 2022, 21:45:23)  [GCC 12.0.1 20220308 (Red Hat 12.0.1-0)]
                     platform: Linux-5.17.1-300.fc36.x86_64-x86_64-with-fedora-36-Thirty_Six
     optional deps. installed: ['typing-extensions']
Example(count=0, names=[])
Example(count=0, names=[])
Traceback (most recent call last):
  File "pydantic_test.py", line 19, in <module>
    Example = pydantic.dataclasses.dataclass(Example)
  File "pydantic/dataclasses.py", line 255, in pydantic.dataclasses.dataclass
    f'repr={self.repr!r},'
  File "pydantic/dataclasses.py", line 250, in pydantic.dataclasses.dataclass.wrap
    f'name={self.name!r},'
  File "pydantic/dataclasses.py", line 159, in pydantic.dataclasses._process_class
    # in the function signature of dataclasses' constructors.
  File "/opt/pyenv/versions/3.7.10/lib/python3.7/dataclasses.py", line 1010, in dataclass
    return wrap(_cls)
  File "/opt/pyenv/versions/3.7.10/lib/python3.7/dataclasses.py", line 1002, in wrap
    return _process_class(cls, init, repr, eq, order, unsafe_hash, frozen)
  File "/opt/pyenv/versions/3.7.10/lib/python3.7/dataclasses.py", line 921, in _process_class
    globals,
  File "/opt/pyenv/versions/3.7.10/lib/python3.7/dataclasses.py", line 491, in _init_fn
    raise TypeError(f'non-default argument {f.name!r} '
TypeError: non-default argument 'names' follows default argument

I've already confirmed that #2557 fixes this issue. Using that PR, the output is as expected:

             pydantic version: 1.9.0a1
            pydantic compiled: False
                 install path: /opt/venvs/default/lib/python3.7/site-packages/pydantic
               python version: 3.7.10 (default, Mar 30 2022, 21:45:23)  [GCC 12.0.1 20220308 (Red Hat 12.0.1-0)]
                     platform: Linux-5.17.1-300.fc36.x86_64-x86_64-with-fedora-36-Thirty_Six
     optional deps. installed: ['typing-extensions']
Example(count=0, names=[])
Example(count=0, names=[])
Example(count=0, names=[])

I've further confirmed that the snippet in the original post runs successfully with the PR but fails on published Pydantic 1.9.0.

@samuelcolvin
Copy link
Member

@troiganto looks like this is still an issue. I'll be something deep in the way we convert dataclasses.

@PrettyWood
Copy link
Member

@samuelcolvin #2557 fixes this issue. I'll try to work again on this so we can merge it for v1.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug V1 Bug related to Pydantic V1.X
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants