Skip to main content

Bump Pydantic ♻️

PyPI - Version PyPI - Python Version

Bump Pydantic is a tool to help you migrate your code from Pydantic V1 to V2.

Table of contents


Installation

The installation is as simple as:

pip install bump-pydantic

Usage

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/
    └── <python source files>

Then you'll want to do:

cd /path/to/repository
bump-pydantic my_package

Check diff before applying changes

To check the diff before applying the changes, you can run:

bump-pydantic --diff <path>

Apply changes

To apply the changes, you can run:

bump-pydantic <path>

Rules

You can find below the list of rules that are applied by bump-pydantic.

It's also possible to disable rules by using the --disable option.

BP001: Add default None to Optional[T], Union[T, None] and Any fields

  • ✅ Add default None to Optional[T] fields.

The following code will be transformed:

class User(BaseModel):
    name: Optional[str]

Into:

class User(BaseModel):
    name: Optional[str] = None

BP002: Replace Config class by model_config attribute

  • ✅ Replace Config class by model_config = ConfigDict().
  • ✅ Rename old Config attributes to new model_config attributes.
  • ✅ Add a TODO comment in case the transformation can't be done automatically.
  • ✅ Replace Extra enum by string values.

The following code will be transformed:

from pydantic import BaseModel, Extra


class User(BaseModel):
    name: str

    class Config:
        extra = Extra.forbid

Into:

from pydantic import ConfigDict, BaseModel


class User(BaseModel):
    name: str

    model_config = ConfigDict(extra="forbid")

BP003: Replace Field old parameters to new ones

  • ✅ Replace Field old parameters to new ones.
  • ✅ Replace field: Enum = Field(Enum.VALUE, const=True) by field: Literal[Enum.VALUE] = Enum.VALUE.

The following code will be transformed:

from typing import List

from pydantic import BaseModel, Field


class User(BaseModel):
    name: List[str] = Field(..., min_items=1)

Into:

from typing import List

from pydantic import BaseModel, Field


class User(BaseModel):
    name: List[str] = Field(..., min_length=1)

BP004: Replace imports

  • ✅ Replace BaseSettings from pydantic to pydantic_settings.
  • ✅ Replace Color and PaymentCardNumber from pydantic to pydantic_extra_types.

BP005: Replace GenericModel by BaseModel

  • ✅ Replace GenericModel by BaseModel.

The following code will be transformed:

from typing import Generic, TypeVar
from pydantic.generics import GenericModel

T = TypeVar('T')

class User(GenericModel, Generic[T]):
    name: str

Into:

from typing import Generic, TypeVar
from pydantic import BaseModel

T = TypeVar('T')

class User(BaseModel, Generic[T]):
    name: str

BP006: Replace __root__ by RootModel

  • ✅ Replace __root__ by RootModel.

The following code will be transformed:

from typing import List

from pydantic import BaseModel

class User(BaseModel):
    age: int
    name: str

class Users(BaseModel):
    __root__ = List[User]

Into:

from typing import List

from pydantic import RootModel, BaseModel

class User(BaseModel):
    age: int
    name: str

class Users(RootModel[List[User]]):
    pass

BP007: Replace decorators

  • ✅ Replace @validator by @field_validator.
  • ✅ Replace @root_validator by @model_validator.

The following code will be transformed:

from pydantic import BaseModel, validator, root_validator


class User(BaseModel):
    name: str

    @validator('name', pre=True)
    def validate_name(cls, v):
        return v

    @root_validator(pre=True)
    def validate_root(cls, values):
        return values

Into:

from pydantic import BaseModel, field_validator, model_validator


class User(BaseModel):
    name: str

    @field_validator('name', mode='before')
    def validate_name(cls, v):
        return v

    @model_validator(mode='before')
    def validate_root(cls, values):
        return values

BP008: Replace con* functions by Annotated versions

  • ✅ Replace constr(*args) by Annotated[str, StringConstraints(*args)].
  • ✅ Replace conint(*args) by Annotated[int, Field(*args)].
  • ✅ Replace confloat(*args) by Annotated[float, Field(*args)].
  • ✅ Replace conbytes(*args) by Annotated[bytes, Field(*args)].
  • ✅ Replace condecimal(*args) by Annotated[Decimal, Field(*args)].
  • ✅ Replace conset(T, *args) by Annotated[Set[T], Field(*args)].
  • ✅ Replace confrozenset(T, *args) by Annotated[Set[T], Field(*args)].
  • ✅ Replace conlist(T, *args) by Annotated[List[T], Field(*args)].

The following code will be transformed:

from pydantic import BaseModel, constr


class User(BaseModel):
    name: constr(min_length=1)

Into:

from pydantic import BaseModel, StringConstraints
from typing_extensions import Annotated


class User(BaseModel):
    name: Annotated[str, StringConstraints(min_length=1)]

BP009: Mark Pydantic "protocol" functions in custom types with proper TODOs

  • ✅ 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:

class SomeThing:
    @classmethod
    def __get_validators__(cls):
        yield from []

    @classmethod
    def __modify_schema__(cls, field_schema, field):
        if field:
            field_schema['example'] = "Weird example"

Into:

class SomeThing:
    @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):
        yield from []

    @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):
        if field:
            field_schema['example'] = "Weird example"

License

This project is licensed under the terms of the MIT license.

Metadata

Release files for bump-pydantic 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for bump-pydantic 0.8.0
File Size Uploaded Provenance
bump_pydantic-0.8.0.tar.gz 28.9 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for bump-pydantic 0.8.0
File Interpreter ABI Platform
bump_pydantic-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 56.4 kB

Release files / bump_pydantic-0.8.0.tar.gz

Download URL bump_pydantic-0.8.0.tar.gz
Size 28.9 kB
Tags Source
SHA-256 checksum
How to use checksums
6092e61930e85619e74eeb04131b4387feda16f02d8bb2e3cf9507fa492c69e9
BLAKE2b-256 checksum
How to use checksums
4e867a74e7d4a76941b9be0c8938dec64ec56d8ba3f4e27a337b85ddbe0de78b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.2 CPython/3.11.7

Release files / bump_pydantic-0.8.0-py3-none-any.whl

Download URL bump_pydantic-0.8.0-py3-none-any.whl
Size 27.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6cbb4deb5869a69baa5a477f28f3e2d8fb09b687e114c018bd54470590ae7bf7
BLAKE2b-256 checksum
How to use checksums
0e3a0092e7b523307b71a203c6c6a6608dbee2a92c2616c264fd7fdf561279b5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/4.0.2 CPython/3.11.7

Security for bump-pydantic 0.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page