-
Notifications
You must be signed in to change notification settings - Fork 16
Poc to demonstrate using pydantic for requests/responses #149
Poc to demonstrate using pydantic for requests/responses #149
Conversation
After digging more into the usage of pydantic, my personal preference would be not to use it. Major reason is in two parts:
|
I'm coming to the same conclusion as Kushal, I'm afraid. It looks like it might be difficult to integrate A bigger problem for me is that incoming data can be altered to fit the model specification, particularly considering the purpose of this project. I think it would be OK for the SDK to double-check the data it's moving, as a backup for the validation happening in the server or workstation, but it should never be silently truncating numeric values or converting between types. It's a conduit. We have seen problems where a value of the wrong type makes its way into a column, thanks to quirks of the combination of SQLAlchemy and SQLite. The last thing we need is a new validation library being itself a source of those bugs. 🙁 If you have integrated |
This will be my last post on this PR/issue as this was just a proposal, but here is another example from the SDK code.
I think that the code to parse the response is a lot easier to read in 2) and less prone to coding mistakes. Also adding a new field to the response will be a lot easier. Lastly, to reply to some of your comments and describe my thoughts a bit more:
I would argue that data types/formats being "100% same and accurate for this, or else it will raise exceptions" is exactly the behavior that you want. With a wrong data type, the runtime will then be operating on wrong assumptions; it might work for some time or in some cases, but there will definitely be bugs at some point. These bugs will probably be tricky to troubleshoot because the bugs will be side-effects of the initially-wrong assumptions.
I've used pydantic extensively with SQLAlchemy and didn't run into problems. I have not used with Flask tho. That's all for pydantic... Ultimately it is of course not up to me to make a decision on this. My personal experience of using pydantic has been great, but perhaps there are better approaches for the securedrop projects. |
Thanks for the thought you've put into this. I understand not wanting to sink more time into something that we don't seem likely to adopt, so don't feel obligated to respond.
Is any of that work public? I'd like to see how you integrated them.
I agree with all of that. But ideally, this SDK should either convey values verbatim, or raise an exception. It's not obvious to me how to avoid |
Our go-to web stack at work has evolved throughout the years and is now falcon + pydantic + sqlalchemy. Unfortunately, none of this code is public. The code base we have with this stack is pretty big tho. As for the type coercion done by pydantic, I guess I don't see it as a big problem? The main thing when using pydantic is that the types in the message format/class should not be considered as "type hints", but as the source of truth, and therefore must be correct. |
Since this was just a POC, I've converted this into an issue at freedomofpress/securedrop-client#1750. |
Related to freedomofpress/securedrop-client#1766 (and freedomofpress/securedrop-client#1765 and freedomofpress/securedrop-client#1764), this is to demonstrate the usage of pydantic for defining requests and responses.
Why pydantic:
I made the change to the User object only, and if this approach is approved I could do the rest of the objects.
Other objects are going to be tricky tho due to freedomofpress/securedrop-client#1764 . For example right now the Source and Reply objects are used both to parse a response returned by the server, and to pass around a UUID when trying to fetch an object from the server (where the rest of the fields are set to a dummy value). This approach is visible here for example: #32.
So I might have to do API-breaking changes to properly fix this, but I don't know if that's an option or not.