Skip to content

Add python validators for decimal constraints (max_digits and decimal_places) - #10506

Merged
sydney-runkle merged 13 commits into
mainfrom
add-decimal-validators
Sep 27, 2024
Merged

sydney-runkle merged 13 commits into
mainfrom
add-decimal-validators

Conversation

@sydney-runkle

@sydney-runkle sydney-runkle commented Sep 27, 2024 •

Copy link
Copy Markdown
Contributor

Closes #10498

This specifically addresses issues where there is annotated metadata applied between the type and the decimal constraints.

For this sample:

import decimal
from pydantic import BaseModel, Field, BeforeValidator, ValidationError
from typing import Annotated

DecimalAnnotation = Annotated[decimal.Decimal, BeforeValidator(lambda v: v)]


class ExampleSchema(BaseModel):
    example_value: Annotated[DecimalAnnotation, Field(max_digits=10, decimal_places=4)] | None

e = ExampleSchema(example_value=decimal.Decimal('123.4567'))

try:
    ExampleSchema(example_value=decimal.Decimal('123.45678'))
except ValidationError as e:
    print(e)
    """
    example_value
    Decimal input should have no more than 4 decimal places [type=decimal_max_places, input_value=Decimal('123.45678'), input_type=Decimal]
        For further information visit https://errors.pydantic.dev/2.10/v/decimal_max_places
    """

try:
    ExampleSchema(example_value=decimal.Decimal('12345678.901'))
except ValidationError as e:
    print(e)
    """
    example_value
    Decimal input should have no more than 10 digits in total [type=decimal_max_digits, input_value=Decimal('12345678.901'), input_type=Decimal]
        For further information visit https://errors.pydantic.dev/2.10/v/decimal_max_digits
    """

The output used to be:

  File "/Users/programming/pydantic_work/pydantic/pydantic/_internal/_known_annotated_metadata.py", line 293, in apply_known_metadata
    raise RuntimeError(f"Unable to apply constraint '{constraint}' to schema of type '{schema_type}'")
RuntimeError: Unable to apply constraint 'max_digits' to schema of type 'function-before'

@github-actions github-actions Bot added the relnotes-fix Used for bugfixes. label Sep 27, 2024
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 27, 2024 •

Copy link
Copy Markdown

Deploying pydantic-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: 9adef0c
Status: ✅  Deploy successful!
Preview URL: https://99e28bdc.pydantic-docs.pages.dev
Branch Preview URL: https://add-decimal-validators.pydantic-docs.pages.dev

View logs

@sydney-runkle sydney-runkle added relnotes-feature and removed relnotes-fix Used for bugfixes. labels Sep 27, 2024
@codspeed

codspeed Bot commented Sep 27, 2024 •

Copy link
Copy Markdown

CodSpeed Performance Report

Merging #10506 will not alter performance

Comparing add-decimal-validators (9adef0c) with main (1f74db2)

Summary

✅ 38 untouched benchmarks

@github-actions

github-actions Bot commented Sep 27, 2024 •

Copy link
Copy Markdown
Contributor

Coverage report

Click to see where and how coverage changed

FileStatementsMissingCoverageCoverage
(new stmts)
Lines missing
  pydantic/_internal
  _known_annotated_metadata.py 298-300
  _validators.py 351, 385, 400
Project Total  

This report was generated by python-coverage-comment-action

@sydney-runkle sydney-runkle added relnotes-fix Used for bugfixes. and removed relnotes-feature labels Sep 27, 2024
Comment thread pydantic/_internal/_validators.py Outdated
Comment thread pydantic/_internal/_validators.py Outdated
Comment thread pydantic/_internal/_validators.py Outdated
Comment thread pydantic/_internal/_validators.py Outdated
Comment thread pydantic/_internal/_validators.py Outdated
Comment thread tests/test_internal.py Outdated
Comment thread pydantic/_internal/_validators.py
@sydney-runkle

Copy link
Copy Markdown
Contributor Author

I think it's alright if I merge this (given the approval and iterations on feedback), but if there's anything left unaddressed, happy to open another PR on Monday!

@sydney-runkle
sydney-runkle merged commit 01b5929 into main Sep 27, 2024
@sydney-runkle
sydney-runkle deleted the add-decimal-validators branch September 27, 2024 21:10
@Viicos

Viicos commented Sep 29, 2024

Copy link
Copy Markdown
Member

I'm wondering: why is the Python validation only called when a validator is already present? Can we avoid duplication between pydantic-core and here?

Other thing, seems like allow_inf_nan suffers from the same issue.

@sydney-runkle

Copy link
Copy Markdown
Contributor Author

I'm wondering: why is the Python validation only called when a validator is already present? Can we avoid duplication between pydantic-core and here?

Good question. I think this issue helps to explain things: #10036

Specifically, we use these Python validators for cases where it'd violate our promise to maintain the order of annotations if we directly applied the constraint to the core schema. But, the validator is still compatible with the type after the custom validator is called, so we can use these python wrappers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

relnotes-fix Used for bugfixes.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Optional[Decimal] with field constraints error: Unable to apply constraint 'max_digits' to schema of type 'function-after'

4 participants