- Notifications
You must be signed in to change notification settings - Fork28
Convert Pydantic from V1 to V2 ♻
License
pydantic/bump-pydantic
Folders and files
| Name | Name | Last commit message | Last commit date | |
|---|---|---|---|---|
Repository files navigation
Bump Pydantic is a tool to help you migrate your code from Pydantic V1 to V2.
Note
If you find bugs, please report them on theissue tracker.
- Bump Pydantic ♻️
- BP001: Add default
NonetoOptional[T],Union[T, None]andAnyfields - BP002: Replace
Configclass bymodel_configattribute - BP003: Replace
Fieldold parameters to new ones - BP004: Replace imports
- BP005: Replace
GenericModelbyBaseModel - BP006: Replace
__root__byRootModel - BP007: Replace decorators
- BP008: Replace
con*functions byAnnotatedversions - BP009: Mark pydantic "protocol" functions in custom types with proper TODOs
- BP001: Add default
The installation is as simple as:
pip install bump-pydantic
bump-pydantic is a CLI tool, hence you can use it from your terminal.
It's easy to use. If your project structure is:
repository/└── my_package/ └──<pythonsource files>
Then you'll want to do:
cd /path/to/repositorybump-pydantic my_packageTo check the diff before applying the changes, you can run:
bump-pydantic --diff<path>
To apply the changes, you can run:
bump-pydantic<path>
You can find below the list of rules that are applied bybump-pydantic.
It's also possible to disable rules by using the--disable option.
- ✅ Add default
NonetoOptional[T]fields.
The following code will be transformed:
classUser(BaseModel):name:Optional[str]
Into:
classUser(BaseModel):name:Optional[str]=None
- ✅ Replace
Configclass bymodel_config = ConfigDict(). - ✅ Rename old
Configattributes to newmodel_configattributes. - ✅ Add a TODO comment in case the transformation can't be done automatically.
- ✅ Replace
Extraenum by string values.
The following code will be transformed:
frompydanticimportBaseModel,ExtraclassUser(BaseModel):name:strclassConfig:extra=Extra.forbid
Into:
frompydanticimportConfigDict,BaseModelclassUser(BaseModel):name:strmodel_config=ConfigDict(extra="forbid")
- ✅ Replace
Fieldold parameters to new ones. - ✅ Replace
field: Enum = Field(Enum.VALUE, const=True)byfield: Literal[Enum.VALUE] = Enum.VALUE.
The following code will be transformed:
fromtypingimportListfrompydanticimportBaseModel,FieldclassUser(BaseModel):name:List[str]=Field(...,min_items=1)
Into:
fromtypingimportListfrompydanticimportBaseModel,FieldclassUser(BaseModel):name:List[str]=Field(...,min_length=1)
- ✅ Replace
BaseSettingsfrompydantictopydantic_settings. - ✅ Replace
ColorandPaymentCardNumberfrompydantictopydantic_extra_types.
- ✅ Replace
GenericModelbyBaseModel.
The following code will be transformed:
fromtypingimportGeneric,TypeVarfrompydantic.genericsimportGenericModelT=TypeVar('T')classUser(GenericModel,Generic[T]):name:str
Into:
fromtypingimportGeneric,TypeVarfrompydanticimportBaseModelT=TypeVar('T')classUser(BaseModel,Generic[T]):name:str
- ✅ Replace
__root__byRootModel.
The following code will be transformed:
fromtypingimportListfrompydanticimportBaseModelclassUser(BaseModel):age:intname:strclassUsers(BaseModel):__root__=List[User]
Into:
fromtypingimportListfrompydanticimportRootModel,BaseModelclassUser(BaseModel):age:intname:strclassUsers(RootModel[List[User]]):pass
- ✅ Replace
@validatorby@field_validator. - ✅ Replace
@root_validatorby@model_validator.
The following code will be transformed:
frompydanticimportBaseModel,validator,root_validatorclassUser(BaseModel):name:str@validator('name',pre=True)defvalidate_name(cls,v):returnv@root_validator(pre=True)defvalidate_root(cls,values):returnvalues
Into:
frompydanticimportBaseModel,field_validator,model_validatorclassUser(BaseModel):name:str@field_validator('name',mode='before')defvalidate_name(cls,v):returnv@model_validator(mode='before')defvalidate_root(cls,values):returnvalues
- ✅ Replace
constr(*args)byAnnotated[str, StringConstraints(*args)]. - ✅ Replace
conint(*args)byAnnotated[int, Field(*args)]. - ✅ Replace
confloat(*args)byAnnotated[float, Field(*args)]. - ✅ Replace
conbytes(*args)byAnnotated[bytes, Field(*args)]. - ✅ Replace
condecimal(*args)byAnnotated[Decimal, Field(*args)]. - ✅ Replace
conset(T, *args)byAnnotated[Set[T], Field(*args)]. - ✅ Replace
confrozenset(T, *args)byAnnotated[Set[T], Field(*args)]. - ✅ Replace
conlist(T, *args)byAnnotated[List[T], Field(*args)].
The following code will be transformed:
frompydanticimportBaseModel,constrclassUser(BaseModel):name:constr(min_length=1)
Into:
frompydanticimportBaseModel,StringConstraintsfromtyping_extensionsimportAnnotatedclassUser(BaseModel):name:Annotated[str,StringConstraints(min_length=1)]
- ✅ Mark
__get_validators__as to be replaced by__get_pydantic_core_schema__. - ✅ Mark
__modify_schema__as to be replaced by__get_pydantic_json_schema__.
The following code will be transformed:
classSomeThing:@classmethoddef__get_validators__(cls):yieldfrom []@classmethoddef__modify_schema__(cls,field_schema,field):iffield:field_schema['example']="Weird example"
Into:
classSomeThing:@classmethod# TODO[pydantic]: We couldn't refactor `__get_validators__`, please create the `__get_pydantic_core_schema__` manually.# Check https://docs.pydantic.dev/latest/migration/#defining-custom-types for more information.def__get_validators__(cls):yieldfrom []@classmethod# TODO[pydantic]: We couldn't refactor `__modify_schema__`, please create the `__get_pydantic_json_schema__` manually.# Check https://docs.pydantic.dev/latest/migration/#defining-custom-types for more information.def__modify_schema__(cls,field_schema,field):iffield:field_schema['example']="Weird example"
- ✅ Add type annotations based on the default value for a few types that can be inferred, like
bool,str,int,float. - ✅ Add
# TODO[pydantic]: add type annotationcomments to fields that can't be inferred.
The following code will be transformed:
frompydanticimportBaseModel,FieldclassPotato(BaseModel):name:stris_sale=Truetags= ["tag1","tag2"]price=10.5description="Some item"active=Field(default=True)ready=Field(True)age=Field(10,title="Age")
Into:
frompydanticimportBaseModel,FieldclassPotato(BaseModel):name:stris_sale:bool=True# TODO[pydantic]: add type annotationtags= ["tag1","tag2"]price:float=10.5description:str="Some item"active:bool=Field(default=True)ready:bool=Field(True)age:int=Field(10,title="Age")
This project is licensed under the terms of the MIT license.
About
Convert Pydantic from V1 to V2 ♻
Topics
Resources
License
Security policy
Uh oh!
There was an error while loading.Please reload this page.