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

Update to supporting Pydantic V2 #203

Merged
merged 81 commits into from
Jan 22, 2024
Merged

Conversation

candleindark
Copy link
Member

@candleindark candleindark commented Nov 20, 2023

This PR migrates Pydantic from V1 to V2. It closes #176.

This PR deprecates the following APIs:

  1. dandischema.models.DandiBaseModel.json_dict
    1. It can now be replaced by pydantic.BaseModel.model_dump(mode='json', exclude_none=True)
  2. dandischema.models,DandiBaseModel.unvalidated
    1. It can be replaced with pydantic.BaseModel.model_construct

Additional notes regarding changes entailed by Pydantic V2:

  1. When using dandischema.models.CommonModel.repository in APIs which expect a str, use str() to convert the attribute to a str.
    1. For more information, visit Url and Dsn types in pydantic.networks no longer inherit from str.
  2. Pydantic V2 generates a slightly different JSON schema for the same Pydantic model compared to Pydantic V1. In particular, the JSON schemas for Optional fields now indicate that the value null is allowed. Because this change in behavior is incompatible with required tests for dandi-schema, dandischema.utils.TransitionalGenerateJsonSchema has been defined to revert the behavior of the JSON schema generation for Optional fields back to the behavior exhibited by Pydantic V1.
    1. To generate the JSON schema for a model without the indication of the null value as for Pydantic V1, initiate the generation with Model.model_json_schema(schema_generator=TransitionalGenerateJsonSchema).
    2. For more information about the use of a GenerateJsonSchema class, please checkout these examples.
  3. Other changes in JSON schema generation in Pydantic V2 in comparison to Pydantic V1 that do not break current required tests for dandi-schema are the following:
    1. "definitions" is now "$defs"
    2. "default" is added for fields that have a default value
    3. "acknowledgement" in CommonModel now has "description" instead of "descriptions" due to a typo correction I put in. (This is not a change entailed by Pydantic V2 but from a correction I put in the code.)
    4. "maxLength" is no longer included in the JSON schema for a field of the type AnyHttpUrl. This is possibly due to the fact that all URL types in Pydantic V2 no longer inherit from str and there is no max length restriction.
    5. For a field of a Literal type of a single value, the "type" key is no longer specified in the corresponding JSON schema. For example, the JSON schema for a field of the type Literal["Asset"] no longer contains the "type" key with the value of "string". This change affects fields such as BareAsset.schemaKey.
    6. For an Enum subclass that has str values for corresponding choices, the new JSON schema will include a "type" key with the value of "string". This change affects pretty much all the Enum subclasses defined in this project.
    7. The docstring is no longer inherited from a parent Pydantic model and used as the value for the "description" key in the JSON schema. For example, the JSON schema for Project no longer has the "description" key because its parent, Activity, has a docstring, """Information about the Project activity""".

Note: This PR contains the "minimum" changes needed to support Pydantic V2. Other improvements to the project enabled by Pydantic V2 will come as subsequent PRs.

TODOs:

@jwodder jwodder added the minor Increment the minor version when merged label Nov 20, 2023
Replace its use with
`pydantic.BaseModel.model_dump(mode='json', exclude_none=True)`
Its use can be replaced with `pydantic.BaseModel.model_construct`
@yarikoptic
Copy link
Member

This PR removes the following APIs.

  1. DandiBaseModel.json_dict

    1. Its use can now be replaced by pydantic.BaseModel.model_dump(mode='json', exclude_none=True)
  2. DandiBaseModel.unvalidated

    1. Its use can be replaced with pydantic.BaseModel.model_construct

Even if for "practice" I think it might good to provide a proper deprecation cycle for those happen there is a tool using dandischema directly and not using any "pydantic specifics": please keep those in API, but make them raise DeprecationWarning and let's schedule to drop those entirely in e.g. 4-6 months after the entire migration to pydantic 2.0 "settles down".

@candleindark
Copy link
Member Author

candleindark commented Nov 22, 2023

This PR removes the following APIs.

  1. DandiBaseModel.json_dict

    1. Its use can now be replaced by pydantic.BaseModel.model_dump(mode='json', exclude_none=True)
  2. DandiBaseModel.unvalidated

    1. Its use can be replaced with pydantic.BaseModel.model_construct

Even if for "practice" I think it might good to provide a proper deprecation cycle for those happen there is a tool using dandischema directly and not using any "pydantic specifics": please keep those in API, but make them raise DeprecationWarning and let's schedule to drop those entirely in e.g. 4-6 months after the entire migration to pydantic 2.0 "settles down".

@satra I think @yarikoptic's has a valid point. May be we should keep those APIs in place for a while instead of removing them now, as you said in Monday's meeting. I can keep those API in place by wrapping the new features provided by Pydantic 2.0.

@satra
Copy link
Member

satra commented Nov 22, 2023

@candleindark - i'm fine with a deprecation cycle. however, if nobody is using them, i'm also ok with the decision to remove. we will be doing a significant change anyway with pydantic 2. if there are significant changes made to other pieces (cli, server), then let's remove those functions. if not, we can put them into deprecated mode.

@yarikoptic
Copy link
Member

current state: I boosted schema version to 0.7.0 and we need to review if any upgrades to the dict serialization are needed in migrate function where I added a placeholder in the code

The logic of the result is equivalent to
the one before the modification
@satra
Copy link
Member

satra commented Jan 18, 2024

@candleindark - could you please address the linting error?

@yarikoptic - i'm assuming we are releasing without the CLI changes? shall we release once the linting error is fixed?

@jwodder
Copy link
Member

jwodder commented Jan 18, 2024

@satra No, we can't release yet, as the TODO item in this commit is still undone.

@satra
Copy link
Member

satra commented Jan 18, 2024

there hasn't been any data model changes, has there? and i'm assuming the migrate tests all pass? the only time a migration code change is required is if we change the data model.

dandischema/metadata.py Outdated Show resolved Hide resolved
@jwodder jwodder marked this pull request as draft January 18, 2024 19:32
@jwodder
Copy link
Member

jwodder commented Jan 18, 2024

I've converted this PR to a draft in order to prevent accidental merging until we can confirm and are sure that all necessary changes have been made.

There is no change in the data model
because of the Pydantic upgrade to V2
dandischema/metadata.py Outdated Show resolved Hide resolved
0.6.5 is more sensible since the changes
in the schema are not breaking changes,
and there is no change in the models and
the JSON serialization of these models
@satra satra marked this pull request as ready for review January 19, 2024 21:18
@candleindark
Copy link
Member Author

The test failed. It seems to be a github problem, but I don't have the option to re-run it.

@candleindark
Copy link
Member Author

The test failed. It seems to be a github problem, but I don't have the option to re-run it.

Did someone just re-ran the test for me. It just re-ran and succeeded.

@yarikoptic
Copy link
Member

I resolved merge conflict - trivial conflict in imports

@yarikoptic yarikoptic merged commit 7af9f3a into dandi:master Jan 22, 2024
34 of 44 checks passed
@candleindark candleindark deleted the pydantic-v2 branch January 26, 2024 22:01
candleindark referenced this pull request in dandi/dandi-archive Feb 10, 2024
Pydantic 2.0's JSON schema export no longer specifies a `type` field for
the `schemaKey` property, and leaves it undefined instead. This change
makes it so an undefined type also delegates it as a "basic schema",
meaning it will not be rendered as its own tab in the meditor.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
minor Increment the minor version when merged release Create a release when this pr is merged
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

FYI: Pydantic v2 is breaking things
4 participants