Skip to content

Differences between BaseModel and @dataclass not expected based on documentation #710

Closed
@SethMMorton

Description

Documentation Update Request

For bugs/questions:

  • OS: Linux
  • Python version: 3.7.3 | packaged by conda-forge
  • Pydantic version: 0.31.0

I liked the idea of using a dataclass instead of subclassing from BaseModel, so I tried changing the very first example from the docs to use dataclass instead of BaseModel and it fails.

from datetime import datetime
from typing import List
# from pydantic import BaseModel
from pydantic.dataclasses import dataclass

# class User(BaseModel):
@dataclass
class User:
    id: int
    name = 'John Doe'
    signup_ts: datetime = None
    friends: List[int] = []

external_data = {'id': '123', 'signup_ts': '2017-06-01 12:22', 'friends': [1, '2', b'3']}
user = User(**external_data)
print(user)
# > User id=123 name='John Doe' signup_ts=datetime.datetime(2017, 6, 1, 12, 22) friends=[1, 2, 3]
print(user.id)
# > 123

Result:

Traceback (most recent call last):
  File "my_pydantic_test.py", line 7, in <module>
    @dataclass
  File "pydantic/dataclasses.py", line 128, in pydantic.dataclasses.dataclass
    # +-------+-------+-------+--------+--------+
  File "pydantic/dataclasses.py", line 123, in pydantic.dataclasses.dataclass.wrap
    #    |       |       |
  File "pydantic/dataclasses.py", line 77, in pydantic.dataclasses._process_class
    #    +--- frozen= parameter
  File "/path/to/python/lib/python3.7/dataclasses.py", line 834, in _process_class
    for name, type in cls_annotations.items()]
  File "/path/to/python/lib/python3.7/dataclasses.py", line 834, in <listcomp>
    for name, type in cls_annotations.items()]
  File "/path/to/python/lib/python3.7/dataclasses.py", line 727, in _get_field
    raise ValueError(f'mutable default {type(f.default)} for field '
ValueError: mutable default <class 'list'> for field friends is not allowed: use default_factory

I realize that this error is coming from the Std. Lib. dataclasses module, not pydantic. However, based on the language in the dataclasses section of the documentation I had expected what anything I could do with BaseModel I could do with dataclass as well.

If you don’t want to use pydantic’s BaseModel you can instead get the same data validation on standard dataclasses (introduced in python 3.7).

You can use all the standard pydantic field types and the resulting dataclass will be identical to the one created by the standard library dataclass decorator.

Can I suggest that there be a note or warning to the user that there are certain restrictions associated with using a dataclass that are not present when using BaseModel (such as not being able to use mutable defaults, as well as #484 and #639)?

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions