Skip to content

Commit

Permalink
Relax signature checks to better support builtins and C extension fun…
Browse files Browse the repository at this point in the history
…ctions as validators (#7101)

Co-authored-by: David Montague <35119617+dmontagu@users.noreply.github.com>
  • Loading branch information
adriangb and dmontagu committed Aug 16, 2023
1 parent f2fd9b2 commit afe065f
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 5 deletions.
11 changes: 7 additions & 4 deletions pydantic/_internal/_decorators.py
Expand Up @@ -493,7 +493,7 @@ def build(model_dc: type[Any]) -> DecoratorInfos: # noqa: C901 (ignore complexi


def inspect_validator(validator: Callable[..., Any], mode: FieldValidatorModes) -> bool:
"""Look at a field or model validator function and determine if it whether it takes an info argument.
"""Look at a field or model validator function and determine whether it takes an info argument.
An error is raised if the function has an invalid signature.
Expand All @@ -504,10 +504,13 @@ def inspect_validator(validator: Callable[..., Any], mode: FieldValidatorModes)
Returns:
Whether the validator takes an info argument.
"""
if getattr(validator, '__module__', None) == 'builtins':
# int, str, etc.
try:
sig = signature(validator)
except ValueError:
# builtins and some C extensions don't have signatures
# assume that they don't take an info argument and only take a single argument
# e.g. `str.strip` or `datetime.datetime`
return False
sig = signature(validator)
n_positional = count_positional_params(sig)
if mode == 'wrap':
if n_positional == 3:
Expand Down
6 changes: 5 additions & 1 deletion tests/test_validators.py
Expand Up @@ -61,11 +61,15 @@ class Model(BaseModel):
def test_annotated_validator_builtin() -> None:
"""https://github.com/pydantic/pydantic/issues/6752"""
TruncatedFloat = Annotated[float, BeforeValidator(int)]
DateTimeFromIsoFormat = Annotated[datetime, BeforeValidator(datetime.fromisoformat)]

class Model(BaseModel):
x: TruncatedFloat
y: DateTimeFromIsoFormat

assert Model(x=1.234).x == 1
m = Model(x=1.234, y='2011-11-04T00:05:23')
assert m.x == 1
assert m.y == datetime(2011, 11, 4, 0, 5, 23)


def test_annotated_validator_plain() -> None:
Expand Down

0 comments on commit afe065f

Please sign in to comment.