diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 9a1a676775..3cd7b8388e 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -200,7 +200,7 @@ def __init__( self.sa_relationship_kwargs = sa_relationship_kwargs -@dataclass +@dataclass(unsafe_hash=True) class FieldInfoMetadata: primary_key: bool | UndefinedType = Undefined nullable: bool | UndefinedType = Undefined diff --git a/tests/test_field_info_metadata_hashable.py b/tests/test_field_info_metadata_hashable.py new file mode 100644 index 0000000000..da32a1b6b6 --- /dev/null +++ b/tests/test_field_info_metadata_hashable.py @@ -0,0 +1,29 @@ +from typing import Annotated + +from sqlmodel import Field +from sqlmodel.main import FieldInfoMetadata + + +def test_field_info_metadata_is_hashable(): + """FieldInfoMetadata must be hashable so that Annotated types containing it + can be used in sets (e.g. FastAPI's OpenAPI schema generation).""" + meta = FieldInfoMetadata(primary_key=True) + hash(meta) + + +def test_annotated_with_field_info_metadata_in_set(): + """Annotated types carrying FieldInfoMetadata must work inside a set, + which is required by FastAPI's get_definitions().""" + t = Annotated[int, FieldInfoMetadata(unique=True)] + s = {t} + assert t in s + + +def test_annotated_field_type_in_set(): + """Realistic scenario: custom Annotated field aliases used in a set.""" + PositiveInt = Annotated[int, Field(ge=0)] + ShortStr = Annotated[str, Field(max_length=32)] + + s = {PositiveInt, ShortStr} + assert PositiveInt in s + assert ShortStr in s