From f41e8470260ff538a824f686b4e577957d5e36a9 Mon Sep 17 00:00:00 2001 From: Cadu Date: Mon, 2 May 2022 21:35:16 -0300 Subject: [PATCH] Added suport for Optional[T] in @hybrid_property's type annotation inference. --- graphene_sqlalchemy/converter.py | 12 ++++++++++++ graphene_sqlalchemy/tests/models.py | 8 +++++++- graphene_sqlalchemy/tests/test_converter.py | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/graphene_sqlalchemy/converter.py b/graphene_sqlalchemy/converter.py index a2e03694..a9da6231 100644 --- a/graphene_sqlalchemy/converter.py +++ b/graphene_sqlalchemy/converter.py @@ -331,6 +331,18 @@ def convert_sqlalchemy_hybrid_property_type_time(arg): return Time +@convert_sqlalchemy_hybrid_property_type.register(lambda x: getattr(x, '__origin__', None) == typing.Union) +def convert_sqlalchemy_hybrid_property_type_option_t(arg): + # Option is actually Union[T, ] + + # Just get the T out of the list of arguments by filtering out the NoneType + internal_type = next(filter(lambda x: not type(None) == x, arg.__args__)) + + graphql_internal_type = convert_sqlalchemy_hybrid_property_type(internal_type) + + return graphql_internal_type + + @convert_sqlalchemy_hybrid_property_type.register(lambda x: getattr(x, '__origin__', None) in [list, typing.List]) def convert_sqlalchemy_hybrid_property_type_list_t(arg): # type is either list[T] or List[T], generic argument at __args__[0] diff --git a/graphene_sqlalchemy/tests/models.py b/graphene_sqlalchemy/tests/models.py index bda5a863..bda46e1c 100644 --- a/graphene_sqlalchemy/tests/models.py +++ b/graphene_sqlalchemy/tests/models.py @@ -3,7 +3,7 @@ import datetime import enum from decimal import Decimal -from typing import List, Tuple +from typing import List, Optional, Tuple from sqlalchemy import (Column, Date, Enum, ForeignKey, Integer, String, Table, func, select) @@ -217,3 +217,9 @@ def hybrid_prop_self_referential(self) -> 'ShoppingCart': @hybrid_property def hybrid_prop_self_referential_list(self) -> List['ShoppingCart']: return [ShoppingCart(id=1)] + + # Optional[T] + + @hybrid_property + def hybrid_prop_optional_self_referential(self) -> Optional['ShoppingCart']: + return None diff --git a/graphene_sqlalchemy/tests/test_converter.py b/graphene_sqlalchemy/tests/test_converter.py index 4b9e74ed..70e11713 100644 --- a/graphene_sqlalchemy/tests/test_converter.py +++ b/graphene_sqlalchemy/tests/test_converter.py @@ -452,6 +452,8 @@ class Meta: # Self Referential List "hybrid_prop_self_referential": ShoppingCartType, "hybrid_prop_self_referential_list": List(ShoppingCartType), + # Optionals + "hybrid_prop_optional_self_referential": ShoppingCartType, } assert sorted(list(ShoppingCartType._meta.fields.keys())) == sorted([