-
Notifications
You must be signed in to change notification settings - Fork 32
⬆️ Upgrade API Server service (Pydantic v2) #6580
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
⬆️ Upgrade API Server service (Pydantic v2) #6580
Conversation
| workspace_id: WorkspaceID | None | ||
| folder_id: FolderID | None | ||
| permalink: ProjectPermalink | None = FieldNotRequired() | ||
| workspace_id: WorkspaceID | None = 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.
@matusdrobuliak66 confirmed that workspace_id and folder_id are optional
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.
these are only for jsonschema generation right? what confuses me is when you say "optional" this does not mean with a default of None
| ) | ||
|
|
||
| model_config = ConfigDict( | ||
| frozen=False |
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.
Superclass is frozen and the behaviour was inherited.
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.
thanks! I guess these went off with the re-creation of the branch. how did you find that out? in the warnings of pytest??
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.
In a test there was a direct assignment of a field in that model.
| modified: datetime | ||
|
|
||
| model_config = ConfigDict( | ||
| frozen=False |
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.
Superclass is frozen and the behaviour was inherited.
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.
same question
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.
In a test there was a direct assignment of a field in that model.
| # specification of the used openapi-generator-cli (see also https://github.com/ITISFoundation/openapi-generator) | ||
| OPENAPI_GENERATOR_NAME := itisfoundation/openapi-generator-cli-openapi-generator-v4.2.3 | ||
| OPENAPI_GENERATOR_TAG := v0 | ||
| OPENAPI_GENERATOR_NAME := openapitools/openapi-generator-cli |
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.
For OpenAPI Spec validation we use the official tool, our fork is obsolete and doesn't support OpenAPI Spec 3.1.x.
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.
@bisgaard-itis can you check now this openapi.json generates the client? Probably is going to force us to go to the next version of the generator
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.
I will give it a try
matusdrobuliak66
left a comment
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.
Thanks!
bisgaard-itis
left a comment
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.
Very cool! Thanks a lot for the effort. Just a few questions, mainly for my understanding
| minimum: int | float | None = None | ||
| anyOf: list["CapturedParameterSchema"] | None = None | ||
| allOf: list["CapturedParameterSchema"] | None = None | ||
| oneOf: list["CapturedParameterSchema"] | None = 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.
Out of curiosity: Why do these have default values now? I believe this is used quite extensively for our testing, so I would try to be as strict as possible in our model.
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.
but still. these were thought as "required" but can be "none" and now they are "non-required". we already had that discussion if I remember well. you showed that pydantic v1 was misbehaving. but still the intent was of having them "required". I would double check with @bisgaard-itis and @pcrespov here
| OPENAPI_GENERATOR_NAME := itisfoundation/openapi-generator-cli-openapi-generator-v4.2.3 | ||
| OPENAPI_GENERATOR_TAG := v0 | ||
| OPENAPI_GENERATOR_NAME := openapitools/openapi-generator-cli | ||
| OPENAPI_GENERATOR_TAG := latest |
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.
Would it make sense to pin the version? I believe this is used in the tests (checking compatibility of openapi specs) and not pinning the version creates a "loose end". If suddenly a bug/change is introduced in the tool we may start seeing strange compatibility failures in our ci
| async def backend_error_handler(request: Request, exc: Exception) -> JSONResponse: | ||
| assert request # nosec | ||
| assert isinstance(exc, BaseBackEndError) | ||
|
|
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.
Out of curiosity: What's the motivation for this change?
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.
mypy complained about function signature assigned to app.add_exception_handler.
sanderegg
left a comment
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.
thanks!
| workspace_id: WorkspaceID | None | ||
| folder_id: FolderID | None | ||
| permalink: ProjectPermalink | None = FieldNotRequired() | ||
| workspace_id: WorkspaceID | None = 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.
these are only for jsonschema generation right? what confuses me is when you say "optional" this does not mean with a default of None
| ) | ||
|
|
||
| model_config = ConfigDict( | ||
| frozen=False |
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.
thanks! I guess these went off with the re-creation of the branch. how did you find that out? in the warnings of pytest??
| modified: datetime | ||
|
|
||
| model_config = ConfigDict( | ||
| frozen=False |
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.
same question
| minimum: int | float | None = None | ||
| anyOf: list["CapturedParameterSchema"] | None = None | ||
| allOf: list["CapturedParameterSchema"] | None = None | ||
| oneOf: list["CapturedParameterSchema"] | None = 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.
but still. these were thought as "required" but can be "none" and now they are "non-required". we already had that discussion if I remember well. you showed that pydantic v1 was misbehaving. but still the intent was of having them "required". I would double check with @bisgaard-itis and @pcrespov here
| anyOf = values.get("anyOf") | ||
| allOf = values.get("allOf") | ||
| oneOf = values.get("oneOf") | ||
| type_ = values.type_ |
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.
this should be a root_validator or the pydantic v2 pendant instead. instead of playing with strings, you would have the self.pattern
| presigned_download_link, | ||
| ) | ||
| return RedirectResponse(presigned_download_link) | ||
| return RedirectResponse(f"{presigned_download_link}") |
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.
interesting that fastapi that is using pydantic v2 would not be compatible with new style URL? are you sure?
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.
At the end it would work, because internally there the Url is stringified... but type-checking complains.
src/simcore_service_api_server/api/routes/solvers_jobs_getters.py: note: In function "get_job_output_logfile":
src/simcore_service_api_server/api/routes/solvers_jobs_getters.py:337:33: error: Argument 1 to "RedirectResponse" has incompatible type "Url"; expected "str | URL" [arg-type]
Found 1 error in 1 file (checked 90 source files)
class RedirectResponse(
url: str | URL, # starlette.datastructures.URL
status_code: int = 307,
headers: Mapping[str, str] | None = None,
background: BackgroundTask | None = None
)| # NOTE: this is different from the resource JobInput (TBD) | ||
| values: KeywordArguments | ||
|
|
||
| # TODO: gibt es platz fuer metadata? |
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.
@pcrespov @bisgaard-itis German TODO... that is a good one
|
|
||
|
|
||
| class WalletGetWithAvailableCredits(WalletGet): | ||
| available_credits: Decimal |
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.
N.B. as discussed offline with @giancarloromeo pydantic 2 has a breaking change concerning how it deals with Decimals which will affect the behaviour of the server (pydantic/pydantic#7120 (comment)). That means once this PR gets merged users will receive, say {"my_decimal": "1.23"} instead of {"my_decimal": 1.23}. This will probably affect users who use the osparc client.
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.
Checking for solution to make this back-compatible with the old behavior 👌 I read that using json_encoders is discouraged, because it will change...
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.
This change solves our problems:
OpenAPI Spec file generated again using make openapi.json command.
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.
Very cool! Thanks a lot for the quick fix
…1/upgrade-api-server-service
…1/upgrade-api-server-service
|
39aed6a
into
ITISFoundation:pydantic_v2_migration_do_not_squash_updates



What do these changes do?
Upgrade the API Server service to Pydantic v2.
Related issue/s
How to test
Dev-ops checklist