Skip to content
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 to Pydantic v2 #319

Closed
wants to merge 2 commits into from
Closed

Upgrade to Pydantic v2 #319

wants to merge 2 commits into from

Conversation

jaykv
Copy link
Contributor

@jaykv jaykv commented Jul 2, 2023

This will have to be tested more thoroughly of course, but I hope this is a good start to move towards pydantic v2 :)

Changes:

  • New BaseModel method names, decorators, and config dict:
    • model.parse_obj -> model.model_validate
    • model.dict -> model.model_dump(mode="json")
    • @root_validator -> @model_validator
    • @validator -> @field_validator
    • parse_raw(raw_stuff) -> model_validate(json.loads(raw_stuff))
    • schema -> model_json_schema
    • json -> model_dump_json
    • class Config: ... -> model_config = ConfigDict(...)
  • BaseModel subclasses using __root__ switched to subclass RootModel with root annotation
  • New fields for ValidationErrorElement: input and url
  • Updated custom type definition for BaseFile (thanks to flask-openapi3's implementation)
  • Response on ValidationError updated to use err.json(indent=2) instead of jsonify(err.errors()) to avoid TypeError: _ is not JSONSerializable errors from the new input field (indent=2 to keep response consistent to current)
  • Update model schema definitions key from definitions -> $defs
  • req_validation_error.model.__name__ -> req_validation_error.title
  • pydantic.EmailStr.validate -> pydantic.validate_email

@@ -22,7 +22,8 @@ classifiers = [
"Topic :: Software Development :: Libraries :: Python Modules",
]
dependencies = [
"pydantic>=1.9.1",
"pydantic>=2.0",
"pydantic-settings"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"pydantic-settings"
"pydantic-settings",

@@ -6,10 +6,11 @@
setup(
name="spectree",
install_requires=[
"pydantic>=1.2",
"pydantic>=2.0",
"pydantic-settings"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"pydantic-settings"
"pydantic-settings",

Copy link
Member

@kemingy kemingy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for your contribution.

Pydantic v2 has too many breaking changes that lots of 3rd libraries are not able to upgrade in a short time.

This PR is not backward compatible (due to pydantic breaking changes). I'm not sure if we should make this library compatible with both pydantic v1 & v2. Or maybe we should add another abstract layer so that we can make it possible to support pydantic v1 & v2 and msgspec (ref #307)

@yedpodtrzitko
Copy link
Collaborator

That's a huge contribution, your effort is really appreciated.

Pydantic v2 however still have some bugs and the ecosystem hasnt adapted yet, so I think it's too early to merge this at this moment.

@jaykv
Copy link
Contributor Author

jaykv commented Jul 3, 2023

I understand of course, this is definitely just here to get the conversation started and test the waters.

So is the ideal separation of layers for future spectree this?

  1. Request/response model validation (pydantic v1/v2, msgspec)
  2. OpenAPI schema generation
  3. Route parsing, generation and validation integration into backends (flask, falcon, starlette, quart)
  4. Apidocs (swagger, redoc)

@kemingy
Copy link
Member

kemingy commented Jul 4, 2023

I understand of course, this is definitely just here to get the conversation started and test the waters.

So is the ideal separation of layers for future spectree this?

1. Request/response model validation (pydantic v1/v2, msgspec)

2. OpenAPI schema generation

3. Route parsing, generation and validation integration into backends (flask, falcon, starlette, quart)

4. Apidocs (swagger, redoc)

Yeah. I wonder if we can detect the model (pydantic v1/v2, megspec) automatically. This layer should be used to validate the request/response and generate the OpenAPI model schema.

@AndreiDrang
Copy link
Contributor

Hi
Perhaps it makes sense to just make a separate library? Smth like spectreeV2?

@kemingy
Copy link
Member

kemingy commented Jul 5, 2023

Hi Perhaps it makes sense to just make a separate library? Smth like spectreeV2?

You can use pip install git+https://github.com/0b01001001/spectree.git@refs/pull/319/head directly.

@DanCardin
Copy link

At least for v2, pydantic appears to be including a v1 backport under pydantic.v1 inside the v2 versions. That may or may not be useful in terms of converting internal usage or making it cross-compatible.

But it seems like it might make it possible for the library at current moment to "simply" alias all of its imports to pydantic to the v1 version. Such that I, as a user of pydantic (that doesn't necessarily stop at API models) could upgrade to v2 without impacting the spectree-compatible v1 API models.

@kemingy
Copy link
Member

kemingy commented Jul 7, 2023

At least for v2, pydantic appears to be including a v1 backport under pydantic.v1 inside the v2 versions. That may or may not be useful in terms of converting internal usage or making it cross-compatible.

But it seems like it might make it possible for the library at current moment to "simply" alias all of its imports to pydantic to the v1 version. Such that I, as a user of pydantic (that doesn't necessarily stop at API models) could upgrade to v2 without impacting the spectree-compatible v1 API models.

This sounds like a good temporary solution.

@jaykv
Copy link
Contributor Author

jaykv commented Jul 9, 2023

At least for v2, pydantic appears to be including a v1 backport under pydantic.v1 inside the v2 versions. That may or may not be useful in terms of converting internal usage or making it cross-compatible.

But it seems like it might make it possible for the library at current moment to "simply" alias all of its imports to pydantic to the v1 version. Such that I, as a user of pydantic (that doesn't necessarily stop at API models) could upgrade to v2 without impacting the spectree-compatible v1 API models.

I've seen this approach used specifically with just:

try:
    from pydantic import v1 as pydantic
except ImportError:
    import pydantic

I didn't explore this yet, but could be worth looking into since it's a smaller change and also less likely to break for current v1 users. The only downside is spectree internally would still be using the v1 API instead of the v2 API. Although, that might not even matter since the long-term plan is to rehaul the internals to support msgspec anyways.

#324 is exploring the reverse approach for fun and upgrading the code to v2 API and creating backports for v1 and version-specific logic to handle the breaking changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants