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
✨ Add JSON-compatible float constraints for NaN and Inf #3994
Conversation
please review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise I'm happy with this idea, needs some docs.
pydantic/pydantic-core#224 to remind us we need to update core to support this.
pydantic/fields.py
Outdated
allow_nan: bool = None, | ||
allow_inf: bool = None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My only question is: do we need both of these options?
I can't imagine a scenario where we want to allow inf
but not nan
or visa. versa.???
I would say we should have one allow_nan_inf
argument for clarity.
@tiangolo what do you think?
please update. |
To match pydantic/pydantic-core#228, we need one option |
@tiangolo you get special treatment, I'll try to fix this for you today. NoticeSee twitter 🐦, I've you'd like this to be included in V1.10, please fix it and request a review TODAY. Or if you need this in V1.10 but don't have time to complete it (or aren't the author), please comment here and on #4324. |
should be mostly there, just needs some docs. @tiangolo @PrettyWood please review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM! Should we add also this option at config level? I feel like it's something you often want enabled or disabled for the whole model
Good point, I'll do that now. It'll also match V2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great
def float_finite_validator(v: 'Number', field: 'ModelField', config: 'BaseConfig') -> 'Number': | ||
allow_inf_nan = getattr(field.type_, 'allow_inf_nan', None) | ||
if allow_inf_nan is None: | ||
allow_inf_nan = config.allow_inf_nan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Amazing! Thanks for taking over it @samuelcolvin! 🙇 LGTM 🚀
thanks again for this. |
Change Summary
✨ Add JSON-compatible float constraints for
NaN
andInf
(+inf
,-inf
).Full discussion in FastAPI: tiangolo/fastapi#4589
Short example
Then:
That creates an
InternalServerError
withValueError: Out of range float values are not JSON compliant
.Reason
Pydantic parses for a
float
field any string that could be parsed by Python'sfloat
, including"NaN"
. But Starlette encodes JSON responses withjson.dumps(allow_nan=False)
. This means that Pydantic will "successfully" parse the"NaN"
string as a Pythonfloat
(which is not valid JSON but is valid Python and valid JavaScript), but then the response will not be able to convert the values back to JSON.Alternatives
Change the response in Starlette/FastAPI
Changing the behavior in the response in Starlette (or FastAPI) to use
json.dumps(allow_nan=True)
(the default) would convert thosefloat("nan")
values to JSONnull
, the equivalent of PythonNone
.But that would mean that any type annotated as
float
would implicitly actually beUnion[float, None]
when converted to JSON. But that would be counterintuitive as static analysis (mypy, the editor, autocompletion, inline errors, TypeScript automatically generated clients, etc) would expect afloat
to be justfloat
, not that in a corner case it could beNone
/null
.Accept this PR and have the new Pydantic types
If this PR is accepted, then my plan would be to document in FastAPI that using
float
in Python has those caveats, and it might be better to use the new Pydantic'sJSONFloat
that ensures compatibility with JSON.Change the default behavior of
float
Currently, there are no tests about how
float('NaN')
,float('+inf')
, andfloat('-inf')
should behave (although there's the current implicit behavior of accepting them).There could be the option to require floats to not be
NaN
,+inf
, or-inf
, the same way that currentlyDecimals
are treated. Currently, there are even tests that check thatDecimal('NaN')
is disallowed. So it might not be crazy to replicate the same behavior for floats.Related issue number
Related to this issue: #1779 in particular to this comment: #1779 (comment)
I wouldn't say this directly closes that issue, but it's indeed related.
It is also related to this FastAPI issue: tiangolo/fastapi#4589
Next
I want to gauge the interest/acceptability of this or the alternatives before writing the docs.
Checklist
changes/<pull request or issue id>-<github username>.md
file added describing change(see changes/README.md for details)