Skip to content

Commit

Permalink
fix dataclass annotated before validator called twice (#6998)
Browse files Browse the repository at this point in the history
  • Loading branch information
davidhewitt committed Aug 2, 2023
1 parent bd725c7 commit adc657a
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 5 deletions.
6 changes: 1 addition & 5 deletions pydantic/fields.py
Expand Up @@ -419,11 +419,7 @@ def _from_dataclass_field(cls, dc_field: DataclassField[Any]) -> typing_extensio

# use the `Field` function so in correct kwargs raise the correct `TypeError`
dc_field_metadata = {k: v for k, v in dc_field.metadata.items() if k in _FIELD_ARG_NAMES}
field = Field(default=default, default_factory=default_factory, repr=dc_field.repr, **dc_field_metadata)

field.annotation, annotation_metadata = cls._extract_metadata(dc_field.type)
field.metadata += annotation_metadata
return field
return Field(default=default, default_factory=default_factory, repr=dc_field.repr, **dc_field_metadata)

@classmethod
def _extract_metadata(cls, annotation: type[Any] | None) -> tuple[type[Any] | None, list[Any]]:
Expand Down
21 changes: 21 additions & 0 deletions tests/test_dataclasses.py
Expand Up @@ -18,6 +18,7 @@
import pydantic
from pydantic import (
BaseModel,
BeforeValidator,
ConfigDict,
FieldValidationInfo,
GenerateSchema,
Expand Down Expand Up @@ -2466,3 +2467,23 @@ class Model:
__pydantic_config__ = ConfigDict(schema_generator=LaxStrGenerator)

assert Model(x=1).x == '1'


@pytest.mark.parametrize('decorator1', **dataclass_decorators())
def test_annotated_before_validator_called_once(decorator1):
count = 0

def convert(value: int) -> str:
nonlocal count
count += 1
return str(value)

IntToStr = Annotated[str, BeforeValidator(convert)]

@decorator1
class A:
a: IntToStr

assert count == 0
TypeAdapter(A).validate_python({'a': 123})
assert count == 1

0 comments on commit adc657a

Please sign in to comment.