🐍

Pydanticの拡張クラスで小文字化まで行う

2024/10/24に公開

始めに

PydanticでEmailStrを拡張するという記事を書きました。今回の記事では、PydanticでEmailStrを拡張するで行ったことをさらに拡張して、大文字小文字のどちらでもパラメータを受け取りつつ、小文字化してアプリケーションで受け取れるようにさらに拡張します。

環境

  • Python
    • 3.12.7
  • Pydantic
    • 2.9.2

実装

以前に追加したロジックでvalidate_half_and_full_emailのレスポンスを小文字化します。

from typing import Type, Any
import re

from pydantic import EmailStr, validator, GetCoreSchemaHandler
from pydantic_core import core_schema


class CustomEmailStr(EmailStr):

    @classmethod
    def validate_half_and_full_email(cls, value: str) -> str:
        if not re.search(r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", value):
            raise ValueError("ERROR.EMAIL_VALIDATION")
        return value.lower() # ここだけ変更

    @classmethod
    def __get_pydantic_core_schema__(cls, source_type: Type[Any], handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
        email_schema = handler.generate_schema(EmailStr)
        return core_schema.chain_schema(
            [
                email_schema,
                core_schema.no_info_after_validator_function(
                    cls.validate_half_and_full_email,
                    core_schema.str_schema()
                ),
            ]
        )

次のテストで大文字を小文字化できていることがわかります。

class _Test(BaseModel):
    email: CustomEmailStr

class TestIsValid:
    @pytest.mark.parametrize(
        "value",
        [
            ("aiueo@example.com"),
            ("AIUEO@example.com"),
        ],
    )
    def test_is_lower(self, value):
        assert _Test(email=value).email == value.lower()

ソースコード

終わりに

記事としてはEmailStrを継承しているのでユースケースとしてはかなり狭いのですが、他にも拡張した型を使用することがあると思うのでその時に役に立てばよいかと考えております。

類似情報

Discussion