Pydantic の SecretStr

ログ出力など通常の表示のための出力やデータダンプで隠蔽させたい
プロパティを定義するのに、Pydantic の SecretStr は有効な方法です。

from pydantic import BaseModel, SecretStr

class Item(BaseModel):
    password: SecretStr
item = Item(password='wse_013%#k')

print(f'__str__() = {item.__str__()}')
# dict 型でダンプ
item_dict = item.model_dump()
print(f'item_dict = {item_dict}')
# JSON ダンプ
print(f'item.model_dump_json() = {item.model_dump_json()}')
# print
print(f'item.password = {item.password}')

結果、固定長文字列 '**********' で出力される。

__str__() = password=SecretStr('**********')
item_dict = {'password': SecretStr('**********')}
item.model_dump_json() = {"password":"**********"}
item.password = **********

よって、この SecretStr の値を検証する時は、item.password 直接フィールド参照はダメで
get_secret_value() で、SecretStr の値を参照することになります。

print(f'item.password.get_secret_value() = {item.password.get_secret_value()}')
if item.password.get_secret_value() == 'wse_013%#k':
    print('match')
else:
    print('No match')

結果

item.password.get_secret_value() = wse_013%#k
match

JSONエンコードした時だけ、SecretStr に値を正しく復元するには
Config 設定として JSONエンコーダーの振る舞いをこの BaseModel のクラスで定義します。

from pydantic import BaseModel, SecretStr

class Item(BaseModel):
    password: SecretStr
    class Config:
        json_encoders = {
            SecretStr: lambda v: v.get_secret_value() if v else None
        }

すると、item.model_dump_json() は、

{"password":"wse_013%#k"}

となります。

SecretBytes でも同じことで、以下も同様です

class Item(BaseModel):
    password: SecretBytes
    class Config:
        json_encoders = {
            SecretBytes: lambda v: v.get_secret_value() if v else None
        }


item = Item(password=b'wse_013%#k')