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

fix "extra fields not permitted" error when dataclass with Extra.forbid is validated multiple times #4354

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions changes/4343-detachhead.md
@@ -0,0 +1 @@
fix "extra fields not permitted" error when dataclass with `Extra.forbid` is validated multiple times
4 changes: 4 additions & 0 deletions pydantic/dataclasses.py
Expand Up @@ -385,6 +385,10 @@ def create_pydantic_model_from_dataclass(


def _dataclass_validate_values(self: 'Dataclass') -> None:
# validation errors can occur if this function is called twice on an already initialised dataclass.
# for example if Extra.forbid is enabled, it would consider __pydantic_initialised__ an invalid extra property
if getattr(self, '__pydantic_initialised__'):
return
if getattr(self, '__pydantic_has_field_info_default__', False):
# We need to remove `FieldInfo` values since they are not valid as input
# It's ok to do that because they are obviously the default values!
Expand Down
24 changes: 24 additions & 0 deletions tests/test_dataclasses.py
Expand Up @@ -1360,3 +1360,27 @@ class A:
A(1, '')

assert A(b='hi').b == 'hi'


def test_extra_forbid_list_no_error():
@pydantic.dataclasses.dataclass(config=dict(extra=Extra.forbid))
class Bar:
...

@pydantic.dataclasses.dataclass
class Foo:
a: List[Bar]

assert isinstance(Foo(a=[Bar()]).a[0], Bar)


def test_extra_forbid_list_error():
@pydantic.dataclasses.dataclass(config=dict(extra=Extra.forbid))
class Bar:
...

with pytest.raises(TypeError, match=re.escape("__init__() got an unexpected keyword argument 'a'")):

@pydantic.dataclasses.dataclass
class Foo:
a: List[Bar(a=1)]