Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Throw an error when using a Union or Interface as an argument type #1222

Merged
merged 3 commits into from
Sep 10, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
21 changes: 21 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
Release type: patch

This release adds a new exception called `InvalidFieldArgument` which is raised when a Union or Interface is used as an argument type.
For example this will raise an exception:
```python
import strawberry

@strawberry.type
class Noun:
text: str

@strawberry.type
class Verb:
text: str

Word = strawberry.union("Word", types=(Noun, Verb))

@strawberry.field
def add_word(word: Word) -> bool:
...
```
7 changes: 7 additions & 0 deletions strawberry/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,10 @@ def __init__(self):
message = 'Request data is missing a "query" value'

super().__init__(message)


class InvalidFieldArgument(Exception):
def __init__(self, field_name: str, argument_name: str, argument_type: str):
message = f'Argument "{argument_name}" on field "{field_name}" cannot be of type\
"{argument_type}"'
super().__init__(message)
19 changes: 19 additions & 0 deletions strawberry/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@

from strawberry.annotation import StrawberryAnnotation
from strawberry.arguments import UNSET, StrawberryArgument
from strawberry.exceptions import InvalidFieldArgument
from strawberry.type import StrawberryType
from strawberry.types.info import Info
from strawberry.union import StrawberryUnion
from strawberry.utils.mixins import GraphQLNameMixin

from .permission import BasePermission
Expand Down Expand Up @@ -102,6 +104,23 @@ def __call__(self, resolver: _RESOLVER_TYPE) -> "StrawberryField":
if not isinstance(resolver, StrawberryResolver):
resolver = StrawberryResolver(resolver)

for argument in resolver.arguments:
if isinstance(argument.type_annotation.annotation, str):
MAM-SYS marked this conversation as resolved.
Show resolved Hide resolved
continue
elif isinstance(argument.type, StrawberryUnion):
raise InvalidFieldArgument(
self.python_name,
argument.python_name,
"Union",
)
elif getattr(argument.type, "_type_definition", False):
if argument.type._type_definition.is_interface:
raise InvalidFieldArgument(
self.python_name,
argument.python_name,
"Interface",
)

self.base_resolver = resolver

return self
Expand Down
47 changes: 46 additions & 1 deletion tests/fields/test_arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import strawberry
from strawberry.arguments import UNSET
from strawberry.exceptions import MultipleStrawberryArgumentsError
from strawberry.exceptions import InvalidFieldArgument, MultipleStrawberryArgumentsError
from strawberry.type import StrawberryList, StrawberryOptional


Expand Down Expand Up @@ -420,3 +420,48 @@ def name( # type: ignore
assert argument.type == str
assert argument.description == "This is a description"
assert argument.type is str


def test_union_as_an_argument_type():
with pytest.raises(InvalidFieldArgument):

@strawberry.type
class Noun:
text: str

@strawberry.type
class Verb:
text: str

Word = strawberry.union("Word", types=(Noun, Verb))

@strawberry.field
def add_word(word: Word) -> bool:
return True


def test_interface_as_an_argument_type():
with pytest.raises(InvalidFieldArgument):

@strawberry.interface
class Adjective:
text: str

@strawberry.field
def add_adjective(adjective: Adjective) -> bool:
return True


def test_resolver_with_invalid_field_argument_type():
with pytest.raises(InvalidFieldArgument):

@strawberry.interface
class Adjective:
text: str

def add_adjective_resolver(adjective: Adjective) -> bool:
return True

@strawberry.type
class Mutation:
add_adjective: bool = strawberry.field(resolver=add_adjective_resolver)