Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Release type: patch

Adds support for lazy unions.
6 changes: 6 additions & 0 deletions strawberry/schema/schema_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import dataclasses
import sys
import typing
from functools import partial, reduce
from typing import (
TYPE_CHECKING,
Annotated,
Any,
Callable,
Generic,
Expand Down Expand Up @@ -862,6 +864,10 @@ def from_type(self, type_: Union[StrawberryType, type]) -> GraphQLNullableType:
if compat.is_graphql_generic(type_):
raise MissingTypesForGenericError(type_)

# to handle lazy unions
if typing.get_origin(type_) is Annotated and len(typing.get_args(type_)) == 2:
type_ = typing.get_args(type_)[1]

Comment on lines 867 to 872
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It isn't the best place for this code. It would be better if resolving a lazy type would return a StrawberryUnion object in this case, but I couldn't make it work 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could be worth trying in another PR!

if isinstance(type_, EnumDefinition): # TODO: Replace with StrawberryEnum
return self.from_enum(type_)
if compat.is_input_type(type_): # TODO: Replace with StrawberryInputObject
Expand Down
90 changes: 90 additions & 0 deletions tests/schema/test_lazy_types/test_lazy_unions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import textwrap
from typing import Annotated, Union

import strawberry
from strawberry.printer import print_schema


@strawberry.type
class TypeA:
a: int


@strawberry.type
class TypeB:
b: int


ABUnion = Annotated[
Union[TypeA, TypeB], strawberry.union("ABUnion", types=[TypeA, TypeB])
]


TypeALazy = Annotated[
"TypeA", strawberry.lazy("tests.schema.test_lazy_types.test_lazy_unions")
]
TypeBLazy = Annotated[
"TypeB", strawberry.lazy("tests.schema.test_lazy_types.test_lazy_unions")
]
LazyABUnion = Annotated[
Union[
TypeALazy,
TypeBLazy,
],
strawberry.union("LazyABUnion", types=[TypeALazy, TypeBLazy]),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If a union does not define types, an error will be raised that union has to have at least one member

]


def test_lazy_union_with_non_lazy_members():
@strawberry.type
class Query:
ab: Annotated[
"ABUnion", strawberry.lazy("tests.schema.test_lazy_types.test_lazy_unions")
]

expected = """
union ABUnion = TypeA | TypeB
type Query {
ab: ABUnion!
}
type TypeA {
a: Int!
}
type TypeB {
b: Int!
}
"""

schema = strawberry.Schema(query=Query)
assert print_schema(schema) == textwrap.dedent(expected).strip()


def test_lazy_union_with_lazy_members():
@strawberry.type
class Query:
ab: Annotated[
"LazyABUnion",
strawberry.lazy("tests.schema.test_lazy_types.test_lazy_unions"),
]

expected = """
union LazyABUnion = TypeA | TypeB
type Query {
ab: LazyABUnion!
}
type TypeA {
a: Int!
}
type TypeB {
b: Int!
}
"""

schema = strawberry.Schema(query=Query)
assert print_schema(schema) == textwrap.dedent(expected).strip()
Loading