-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
✨ Add JSON-compatible float constraints for NaN and Inf #3994
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
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
NaNandInf(+inf,-inf).Full discussion in FastAPI: fastapi/fastapi#4589
Short example
Then:
That creates an
InternalServerErrorwithValueError: Out of range float values are not JSON compliant.Reason
Pydantic parses for a
floatfield 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
floatwould 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 afloatto 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
floatin Python has those caveats, and it might be better to use the new Pydantic'sJSONFloatthat ensures compatibility with JSON.Change the default behavior of
floatCurrently, 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 currentlyDecimalsare 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: fastapi/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>.mdfile added describing change(see changes/README.md for details)