Pydantic: Inherited dataclasses don't resolve forward refs

Created on 29 Jun 2020  路  6Comments  路  Source: samuelcolvin/pydantic

Bug

pydantic version: 1.5.1
python version: 3.8.2

a.py:

from __future__ import annotations
from uuid import UUID
from pydantic.dataclasses import dataclass

@dataclass
class A:
    uuid: UUID

    # workaround
    # def __post_init__(self):
    #     self.__pydantic_model__.update_forward_refs(**globals())

b.py:

from __future__ import annotations
from uuid import uuid4
from pydantic.dataclasses import dataclass
from a import A

@dataclass
class B(A):
    pass

B(uuid=uuid4())

B(uuid=uuid4()) throws field "uuid" not yet prepared so type is still a ForwardRef, you might need to call B.update_forward_refs().

bug

All 6 comments

Hello @laevilgenius
I can't reproduce with your example. See https://repl.it/@EricJ1/pydantic-issue-1668.
Could you please give us more information on how to reproduce the bug please?

@PrettyWood it fails only when from __future__ import annotations is present: https://repl.it/repls/WaterySlimDehardwarization.

I can duplicate this bug in a single file

from __future__ import annotations

from dataclasses import dataclass
from typing import Literal

from pydantic import BaseModel


@dataclass
class Base:
    literal: Literal[1, 2]


class What(BaseModel):
    base: Base


What(base=Base(literal=1))

I guess this is using stdlib dataclasses though

Hello guys
Sorry I forgot to come back on this issue.
So yes the issue is related to this

If from __future__ import annotations is used in Python 3.7 or later, annotations are not evaluated at function definition time. Instead, they are stored as strings in __annotations__, This makes it unnecessary to use quotes around the annotation. (see PEP 563).

So it's not really a bug but more a feature to support new behaviour of annotations.
And I reckon we'll probably need to dig into it quite soon!

Hi guys! Just took some time to check out this issue. I just opened a PR with the fix. Feedback more than welcome :)
Merry Christmas and happy holidays 馃巺

Hello! I came here from this problem. A class depends on a type that is not yet declared:

>>> from pydantic.dataclasses import dataclass
>>> @dataclass
... class A:
...     b: "B"
>>> @dataclass
... class B:
...     c: str

So, when I instantiated it, it threw an error, which is understandable:

>>> a=A(b={'c':'hi'})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 4, in __init__
  File "pydantic/dataclasses.py", line 105, in pydantic.dataclasses._process_class._pydantic_post_init
  File "pydantic/main.py", line 960, in pydantic.main.validate_model
pydantic.errors.ConfigError: field "b" not yet prepared so type is still a ForwardRef, you might need to call A.update_forward_refs().

field "b" not yet prepared so type is still a ForwardRef, you might need to call A.update_forward_refs().

So, it says about calling A.update_forward_refs(). However, if I do it, it fails:

>>> A.update_forward_refs()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'A' has no attribute 'update_forward_refs'

type object 'A' has no attribute 'update_forward_refs'

In the docs it's not clear how to do that if you're using a pydantic dataclass and not a BaseModel.

Thanks to this issue I found the solution:

>>> A.__pydantic_model__.update_forward_refs()
>>> a=A(b={'c':'hi'})
>>> a
A(b=B(c='hi'))

I think that:

  1. The error message should be fixed, because it asks you to call a function that doesn't exist.
  2. The docs should include an example for a dataclass.
Was this page helpful?
0 / 5 - 0 ratings

Related issues

gangefors picture gangefors  路  3Comments

bartekbrak picture bartekbrak  路  3Comments

drpoggi picture drpoggi  路  3Comments

ashears picture ashears  路  3Comments

krzysieqq picture krzysieqq  路  3Comments