From 435ad5304847cc266a9ce80c93523d51ddab5bf0 Mon Sep 17 00:00:00 2001 From: bolu61 Date: Tue, 29 Oct 2024 18:22:13 -0400 Subject: [PATCH 1/5] support PEP 593 for relationships --- sqlmodel/main.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 3532e81a8e..434ff05d10 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -52,7 +52,7 @@ from sqlalchemy.orm.instrumentation import is_instrumented from sqlalchemy.sql.schema import MetaData from sqlalchemy.sql.sqltypes import LargeBinary, Time, Uuid -from typing_extensions import Literal, TypeAlias, deprecated, get_origin +from typing_extensions import Annotated, Literal, TypeAlias, deprecated, get_args, get_origin from ._compat import ( # type: ignore[attr-defined] IS_PYDANTIC_V2, @@ -475,6 +475,16 @@ def Relationship( return relationship_info +def get_annotated_relationshipinfo(t: Type) -> RelationshipInfo | None: + """Get the first RelationshipInfo from Annotated or None if not Annotated with RelationshipInfo.""" + if get_origin(t) is not Annotated: + return None + for a in get_args(t): + if isinstance(a, RelationshipInfo): + return a + return None + + @__dataclass_transform__(kw_only_default=True, field_descriptors=(Field, FieldInfo)) class SQLModelMetaclass(ModelMetaclass, DeclarativeMeta): __sqlmodel_relationships__: Dict[str, RelationshipInfo] @@ -515,7 +525,12 @@ def __new__( else: dict_for_pydantic[k] = v for k, v in original_annotations.items(): - if k in relationships: + # check for `field: Annotated[Any, Relationship()]` + t = get_annotated_relationshipinfo(v) + if t: + relationships[k] = t + relationship_annotations[k] = get_args(v)[0] + elif k in relationships: relationship_annotations[k] = v else: pydantic_annotations[k] = v From c5d7df863ea1b936abd7672bba19cd54ff9719a8 Mon Sep 17 00:00:00 2001 From: bolu61 Date: Tue, 29 Oct 2024 18:34:25 -0400 Subject: [PATCH 2/5] Fix formatting --- sqlmodel/main.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 434ff05d10..88f0fea15d 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -52,7 +52,14 @@ from sqlalchemy.orm.instrumentation import is_instrumented from sqlalchemy.sql.schema import MetaData from sqlalchemy.sql.sqltypes import LargeBinary, Time, Uuid -from typing_extensions import Annotated, Literal, TypeAlias, deprecated, get_args, get_origin +from typing_extensions import ( + Annotated, + Literal, + TypeAlias, + deprecated, + get_args, + get_origin, +) from ._compat import ( # type: ignore[attr-defined] IS_PYDANTIC_V2, From 9f356db8826389e8e3a72c88dea9df18bf4fddef Mon Sep 17 00:00:00 2001 From: bolu61 Date: Tue, 29 Oct 2024 18:41:17 -0400 Subject: [PATCH 3/5] Use Optional instead of `|` --- sqlmodel/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 88f0fea15d..01acfcdb6e 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -482,7 +482,7 @@ def Relationship( return relationship_info -def get_annotated_relationshipinfo(t: Type) -> RelationshipInfo | None: +def get_annotated_relationshipinfo(t: Type) -> Optional[RelationshipInfo]: """Get the first RelationshipInfo from Annotated or None if not Annotated with RelationshipInfo.""" if get_origin(t) is not Annotated: return None From 33604b4fb540e67734dafca293bf9d0291b9e64b Mon Sep 17 00:00:00 2001 From: bolu61 Date: Tue, 29 Oct 2024 18:45:11 -0400 Subject: [PATCH 4/5] Fix type annotation --- sqlmodel/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 01acfcdb6e..04a7f3ccd5 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -482,7 +482,7 @@ def Relationship( return relationship_info -def get_annotated_relationshipinfo(t: Type) -> Optional[RelationshipInfo]: +def get_annotated_relationshipinfo(t: type[Any]) -> Optional[RelationshipInfo]: """Get the first RelationshipInfo from Annotated or None if not Annotated with RelationshipInfo.""" if get_origin(t) is not Annotated: return None From 25340990206331e55ff3eb454fdc60c057554a2f Mon Sep 17 00:00:00 2001 From: bolu61 Date: Tue, 29 Oct 2024 18:47:59 -0400 Subject: [PATCH 5/5] Use Any instead of type[Any] --- sqlmodel/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sqlmodel/main.py b/sqlmodel/main.py index 04a7f3ccd5..127b3db7c6 100644 --- a/sqlmodel/main.py +++ b/sqlmodel/main.py @@ -482,7 +482,7 @@ def Relationship( return relationship_info -def get_annotated_relationshipinfo(t: type[Any]) -> Optional[RelationshipInfo]: +def get_annotated_relationshipinfo(t: Any) -> Optional[RelationshipInfo]: """Get the first RelationshipInfo from Annotated or None if not Annotated with RelationshipInfo.""" if get_origin(t) is not Annotated: return None