datamodel-code-generator icon indicating copy to clipboard operation
datamodel-code-generator copied to clipboard

`multipleOf` and `number` translations yield unstable Pydantic models.

Open tpanum opened this issue 9 months ago • 2 comments
trafficstars

Describe the bug Pydantic has an underlying bug when using multiple_of with float, and is covered here. To my knowledge, Decimal is more stable in this regard.

To Reproduce Here is a small program to showcase the instability of float vs. Decimal.

from decimal import Decimal

import pydantic
from pydantic import BaseModel, Field


class A(BaseModel):
    a: float = Field(multiple_of=0.1)


class B(BaseModel):
    a: Decimal = Field(multiple_of=0.1)


def test_class(cls):
    error_value = None
    for i in range(100):
        v = (i - 50) / 10
        try:
            cls(a=v)
        except pydantic.ValidationError:
            error_value = v
            break

    if error_value:
        print(f"Got validation error with value: {error_value}")
    else:
        print("No validation errors")


def main():
    print("Testing float with `multiple_of``")
    test_class(A)

    print("Testing Decimal with `multiple_of`")
    test_class(B)


if __name__ == "__main__":
    main()

Example schema:

...
    Energy: {type: number, format: realenergy, multipleOf: 0.1, minimum: -9.99999999E7,
      maximum: 9.99999999E7, example: 1200.7}
...

Will map to:

class Energy(RootModel[confloat(ge=-99999999.9, le=99999999.9, multiple_of=0.1)]):
    root: confloat(ge=-99999999.9, le=99999999.9, multiple_of=0.1) = Field(
        ...,
        examples=[1200.7],
    )

I think it would be more sane to map to Decimal as soon as multipleOf is a requirement.

tpanum avatar Jan 28 '25 11:01 tpanum

This would be a breaking change though, no?

gaborbernat avatar Feb 06 '25 20:02 gaborbernat

Yes, it would. It is unfortunately non-trivial how to progress from here.

tpanum avatar Mar 04 '25 09:03 tpanum

I'd also be interested in having the ability to translate multipleOf float as Decimal. Maybe it could take the form of an option?

npfp avatar Sep 08 '25 20:09 npfp