diff --git a/changes/4387-chbndrhnns.md b/changes/4387-chbndrhnns.md new file mode 100644 index 0000000000..f9f4900b2b --- /dev/null +++ b/changes/4387-chbndrhnns.md @@ -0,0 +1 @@ +Make `SecretStr` and `SecretBytes` hashable diff --git a/pydantic/types.py b/pydantic/types.py index fa25ddaa3c..ccc0586fa7 100644 --- a/pydantic/types.py +++ b/pydantic/types.py @@ -834,6 +834,9 @@ def __eq__(self, other: Any) -> bool: def __str__(self) -> str: return '**********' if self.get_secret_value() else '' + def __hash__(self) -> int: + return hash(self.get_secret_value()) + @abc.abstractmethod def get_secret_value(self) -> Any: # pragma: no cover ... diff --git a/tests/test_types.py b/tests/test_types.py index a8021ec31b..8a6d9006a8 100644 --- a/tests/test_types.py +++ b/tests/test_types.py @@ -2663,6 +2663,10 @@ class Foobar(BaseModel): assert m.password.get_secret_value() == '1234' +def test_secretstr_is_hashable(): + assert type(hash(SecretStr('secret'))) is int + + def test_secretstr_error(): class Foobar(BaseModel): password: SecretStr @@ -2755,6 +2759,10 @@ class Foobar(BaseModel): _ = Foobar(password=SecretBytes(b'1234')) +def test_secretbytes_is_hashable(): + assert type(hash(SecretBytes(b'secret'))) is int + + def test_secretbytes_error(): class Foobar(BaseModel): password: SecretBytes