From 5c0f0b0d1ac9ce9f085aaf3e87b37b07bb358253 Mon Sep 17 00:00:00 2001 From: Jacob Allen Date: Sun, 6 Oct 2024 11:32:30 -0600 Subject: [PATCH] Fix codegen crash on nullable lists of non-scalars (#3653) Co-authored-by: Jacob Allen --- RELEASE.md | 3 +++ strawberry/codegen/query_codegen.py | 14 ++++++++------ tests/codegen/conftest.py | 1 + .../queries/nullable_list_of_non_scalars.graphql | 6 ++++++ .../python/nullable_list_of_non_scalars.py | 8 ++++++++ .../typescript/nullable_list_of_non_scalars.ts | 8 ++++++++ 6 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 RELEASE.md create mode 100644 tests/codegen/queries/nullable_list_of_non_scalars.graphql create mode 100644 tests/codegen/snapshots/python/nullable_list_of_non_scalars.py create mode 100644 tests/codegen/snapshots/typescript/nullable_list_of_non_scalars.ts diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000000..087ca107ed --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,3 @@ +Release type: patch + +Fixes an issue where the codegen tool would crash when working with a nullable list of types. diff --git a/strawberry/codegen/query_codegen.py b/strawberry/codegen/query_codegen.py index 92d93d98db..583f7fbe39 100644 --- a/strawberry/codegen/query_codegen.py +++ b/strawberry/codegen/query_codegen.py @@ -645,20 +645,22 @@ def _unwrap_type( ) -> Tuple[ Union[type, StrawberryType], Optional[Callable[[GraphQLType], GraphQLType]] ]: - wrapper = None + wrapper: Optional[Callable[[GraphQLType], GraphQLType]] = None if isinstance(type_, StrawberryOptional): - type_, wrapper = self._unwrap_type(type_.of_type) + type_, previous_wrapper = self._unwrap_type(type_.of_type) wrapper = ( GraphQLOptional - if wrapper is None - else lambda t: GraphQLOptional(wrapper(t)) # type: ignore[misc] + if previous_wrapper is None + else lambda t: GraphQLOptional(previous_wrapper(t)) # type: ignore[misc] ) elif isinstance(type_, StrawberryList): - type_, wrapper = self._unwrap_type(type_.of_type) + type_, previous_wrapper = self._unwrap_type(type_.of_type) wrapper = ( - GraphQLList if wrapper is None else lambda t: GraphQLList(wrapper(t)) + GraphQLList + if previous_wrapper is None + else lambda t: GraphQLList(previous_wrapper(t)) ) elif isinstance(type_, LazyType): diff --git a/tests/codegen/conftest.py b/tests/codegen/conftest.py index 1b7f80e467..d776a474fd 100644 --- a/tests/codegen/conftest.py +++ b/tests/codegen/conftest.py @@ -101,6 +101,7 @@ class Query: person: Person optional_person: Optional[Person] list_of_people: List[Person] + optional_list_of_people: Optional[List[Person]] enum: Color json: JSON union: PersonOrAnimal diff --git a/tests/codegen/queries/nullable_list_of_non_scalars.graphql b/tests/codegen/queries/nullable_list_of_non_scalars.graphql new file mode 100644 index 0000000000..8bdedbe6a2 --- /dev/null +++ b/tests/codegen/queries/nullable_list_of_non_scalars.graphql @@ -0,0 +1,6 @@ +query OperationName { + optionalListOfPeople { + name + age + } +} diff --git a/tests/codegen/snapshots/python/nullable_list_of_non_scalars.py b/tests/codegen/snapshots/python/nullable_list_of_non_scalars.py new file mode 100644 index 0000000000..f5efcaa7f8 --- /dev/null +++ b/tests/codegen/snapshots/python/nullable_list_of_non_scalars.py @@ -0,0 +1,8 @@ +from typing import List, Optional + +class OperationNameResultOptionalListOfPeople: + name: str + age: int + +class OperationNameResult: + optional_list_of_people: Optional[List[OperationNameResultOptionalListOfPeople]] diff --git a/tests/codegen/snapshots/typescript/nullable_list_of_non_scalars.ts b/tests/codegen/snapshots/typescript/nullable_list_of_non_scalars.ts new file mode 100644 index 0000000000..7498cac29d --- /dev/null +++ b/tests/codegen/snapshots/typescript/nullable_list_of_non_scalars.ts @@ -0,0 +1,8 @@ +type OperationNameResultOptionalListOfPeople = { + name: string + age: number +} + +type OperationNameResult = { + optional_list_of_people: OperationNameResultOptionalListOfPeople[] | undefined +}