From 9d24474767eb83be099d5a08d218a8f993ae84dd Mon Sep 17 00:00:00 2001 From: M Aswin Kishore <60577077+mak626@users.noreply.github.com> Date: Thu, 10 Oct 2024 11:44:44 +0530 Subject: [PATCH] fix: list[str] is not interpreted as List[String!]! instead as List[String!] --- graphene_pydantic/converters.py | 17 +++++++++++------ tests/test_converters.py | 10 ++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/graphene_pydantic/converters.py b/graphene_pydantic/converters.py index ca3118b..5f63745 100644 --- a/graphene_pydantic/converters.py +++ b/graphene_pydantic/converters.py @@ -5,6 +5,7 @@ import enum import inspect import sys +import types import typing as T import uuid from typing import Type, get_origin @@ -28,8 +29,8 @@ from graphene.types.datetime import Date, DateTime, Time from pydantic import BaseModel from pydantic.fields import FieldInfo -from pydantic_core import PydanticUndefined from pydantic.networks import EmailStr +from pydantic_core import PydanticUndefined from .registry import Placeholder, Registry from .util import construct_union_class_name, evaluate_forward_ref @@ -37,7 +38,7 @@ PYTHON10 = sys.version_info >= (3, 10) PYTHON9 = sys.version_info >= (3, 9) if PYTHON10: - from types import UnionType + from types import NoneType, UnionType if PYTHON9: from typing import Annotated @@ -310,7 +311,7 @@ def convert_generic_python_type( registry: Registry, parent_type: T.Type = None, model: T.Type[BaseModel] = None, -) -> T.Union[Type[T.Union[BaseType, List]], Placeholder]: +) -> T.Union[Type[T.Union[BaseType, List]], List, Placeholder]: """ Convert annotated Python generic types into the most appropriate Graphene Field type -- e.g., turn `typing.Union` into a Graphene Union. @@ -348,10 +349,14 @@ def convert_generic_python_type( # Of course, we can only return a homogeneous type here, so we pick the # first of the wrapped types inner_type = inner_types[0] + inner_gql_type = find_graphene_type( + inner_types[0], field, registry, parent_type=parent_type, model=model + ) + is_required = not ( + isinstance(inner_type, types.UnionType) and NoneType in inner_type.__args__ + ) return List( - find_graphene_type( - inner_type, field, registry, parent_type=parent_type, model=model - ) + graphene.NonNull(inner_gql_type) if is_required else inner_gql_type, ) elif origin in (T.Dict, T.Mapping, collections.OrderedDict, dict) or issubclass( origin, collections.abc.Mapping diff --git a/tests/test_converters.py b/tests/test_converters.py index 6c18450..cb0e8f2 100644 --- a/tests/test_converters.py +++ b/tests/test_converters.py @@ -153,12 +153,20 @@ def test_decimal(monkeypatch): def test_iterables(): field = _convert_field_from_spec("attr", (T.List[int], [1, 2])) assert isinstance(field.type.of_type, graphene.types.List) + assert isinstance(field.type.of_type.of_type, graphene.types.NonNull) + assert field.type.of_type.of_type.of_type == graphene.types.Int + + field = _convert_field_from_spec("attr", (T.List[int | None], [1, 2])) + assert isinstance(field.type.of_type, graphene.types.List) + assert field.type.of_type.of_type == graphene.types.Int field = _convert_field_from_spec("attr", (list, [1, 2])) assert field.type.of_type == graphene.types.List field = _convert_field_from_spec("attr", (T.Set[int], {1, 2})) assert isinstance(field.type.of_type, graphene.types.List) + assert isinstance(field.type.of_type.of_type, graphene.types.NonNull) + assert field.type.of_type.of_type.of_type == graphene.types.Int field = _convert_field_from_spec("attr", (set, {1, 2})) assert field.type.of_type == graphene.types.List @@ -168,6 +176,8 @@ def test_iterables(): field = _convert_field_from_spec("attr", (T.Tuple[int, ...], (1, 2.2))) assert isinstance(field.type.of_type, graphene.types.List) + assert isinstance(field.type.of_type.of_type, graphene.types.NonNull) + assert field.type.of_type.of_type.of_type == graphene.types.Int field = _convert_field_from_spec("attr", (tuple, (1, 2))) assert field.type.of_type == graphene.types.List