From 7a0854978cd0cb25d4b78df8846e7e55bf718164 Mon Sep 17 00:00:00 2001 From: mamsi Date: Tue, 7 Sep 2021 23:49:24 +0430 Subject: [PATCH 1/3] Throw an error when using a Union or Interface as an argument type --- RELEASE.md | 22 ++++++++++++++++++++++ strawberry/exceptions.py | 6 ++++++ strawberry/field.py | 11 +++++++++++ tests/fields/test_arguments.py | 32 +++++++++++++++++++++++++++++++- 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 RELEASE.md diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000000..29f61e876e --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,22 @@ +Release type: patch + +This release adds a new exception called `InvalidArgument` and it will be raised when we use Union or Interface 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: + _word = word + return True +``` diff --git a/strawberry/exceptions.py b/strawberry/exceptions.py index 72e20823d2..9afd737ac6 100644 --- a/strawberry/exceptions.py +++ b/strawberry/exceptions.py @@ -169,3 +169,9 @@ def __init__(self): message = 'Request data is missing a "query" value' super().__init__(message) + + +class InvalidArgument(Exception): + def __init__(self, field_name: str, argument_type: str): + message = f'"{field_name}" is "{argument_type}" and invalid as an argument type' + super().__init__(message) diff --git a/strawberry/field.py b/strawberry/field.py index 9bc5d54542..06776135f1 100644 --- a/strawberry/field.py +++ b/strawberry/field.py @@ -18,8 +18,10 @@ from strawberry.annotation import StrawberryAnnotation from strawberry.arguments import UNSET, StrawberryArgument +from strawberry.exceptions import InvalidArgument 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 @@ -102,6 +104,15 @@ 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): + continue + elif isinstance(argument.type, StrawberryUnion): + raise InvalidArgument(argument.python_name, "Union") + elif getattr(argument.type, "_type_definition", False): + if argument.type._type_definition.is_interface: + raise InvalidArgument(argument.python_name, "Interface") + self.base_resolver = resolver return self diff --git a/tests/fields/test_arguments.py b/tests/fields/test_arguments.py index 940a0772f9..84bed58956 100644 --- a/tests/fields/test_arguments.py +++ b/tests/fields/test_arguments.py @@ -7,7 +7,7 @@ import strawberry from strawberry.arguments import UNSET -from strawberry.exceptions import MultipleStrawberryArgumentsError +from strawberry.exceptions import InvalidArgument, MultipleStrawberryArgumentsError from strawberry.type import StrawberryList, StrawberryOptional @@ -420,3 +420,33 @@ 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(InvalidArgument): + + @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(InvalidArgument): + + @strawberry.interface + class Adjective: + text: str + + @strawberry.field + def add_word(adjective: Adjective) -> bool: + return True From 801ec0faac643e83123cf8cf2d6f17856fb71177 Mon Sep 17 00:00:00 2001 From: mamsi Date: Wed, 8 Sep 2021 19:28:11 +0430 Subject: [PATCH 2/3] Better suggestions --- RELEASE.md | 13 ++++++------- strawberry/exceptions.py | 7 ++++--- strawberry/field.py | 14 +++++++++++--- tests/fields/test_arguments.py | 6 +++--- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index 29f61e876e..ea04ddc7a6 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,22 +1,21 @@ Release type: patch -This release adds a new exception called `InvalidArgument` and it will be raised when we use Union or Interface as an argument type +This release adds a new exception called `InvalidFieldArgument` which is raised when if a Union or Interface is used as an argument type. For example this will raise an exception: ```python -import strawberry - +import strawberry + @strawberry.type class Noun: text: str @strawberry.type class Verb: - text: str + text: str Word = strawberry.union("Word", types=(Noun, Verb)) @strawberry.field def add_word(word: Word) -> bool: - _word = word - return True -``` + ... +``` diff --git a/strawberry/exceptions.py b/strawberry/exceptions.py index 9afd737ac6..ce8cb8eafe 100644 --- a/strawberry/exceptions.py +++ b/strawberry/exceptions.py @@ -171,7 +171,8 @@ def __init__(self): super().__init__(message) -class InvalidArgument(Exception): - def __init__(self, field_name: str, argument_type: str): - message = f'"{field_name}" is "{argument_type}" and invalid as an argument type' +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) diff --git a/strawberry/field.py b/strawberry/field.py index 06776135f1..7f6da6d38b 100644 --- a/strawberry/field.py +++ b/strawberry/field.py @@ -18,7 +18,7 @@ from strawberry.annotation import StrawberryAnnotation from strawberry.arguments import UNSET, StrawberryArgument -from strawberry.exceptions import InvalidArgument +from strawberry.exceptions import InvalidFieldArgument from strawberry.type import StrawberryType from strawberry.types.info import Info from strawberry.union import StrawberryUnion @@ -108,10 +108,18 @@ def __call__(self, resolver: _RESOLVER_TYPE) -> "StrawberryField": if isinstance(argument.type_annotation.annotation, str): continue elif isinstance(argument.type, StrawberryUnion): - raise InvalidArgument(argument.python_name, "Union") + raise InvalidFieldArgument( + self.python_name, + argument.python_name, + "Union", + ) elif getattr(argument.type, "_type_definition", False): if argument.type._type_definition.is_interface: - raise InvalidArgument(argument.python_name, "Interface") + raise InvalidFieldArgument( + self.python_name, + argument.python_name, + "Interface", + ) self.base_resolver = resolver diff --git a/tests/fields/test_arguments.py b/tests/fields/test_arguments.py index 84bed58956..09d9708c46 100644 --- a/tests/fields/test_arguments.py +++ b/tests/fields/test_arguments.py @@ -7,7 +7,7 @@ import strawberry from strawberry.arguments import UNSET -from strawberry.exceptions import InvalidArgument, MultipleStrawberryArgumentsError +from strawberry.exceptions import InvalidFieldArgument, MultipleStrawberryArgumentsError from strawberry.type import StrawberryList, StrawberryOptional @@ -423,7 +423,7 @@ def name( # type: ignore def test_union_as_an_argument_type(): - with pytest.raises(InvalidArgument): + with pytest.raises(InvalidFieldArgument): @strawberry.type class Noun: @@ -441,7 +441,7 @@ def add_word(word: Word) -> bool: def test_interface_as_an_argument_type(): - with pytest.raises(InvalidArgument): + with pytest.raises(InvalidFieldArgument): @strawberry.interface class Adjective: From 80237721f9b955b37f897cdb6ed8acf6bcae069b Mon Sep 17 00:00:00 2001 From: mamsi Date: Fri, 10 Sep 2021 14:11:36 +0430 Subject: [PATCH 3/3] Add new test --- RELEASE.md | 2 +- tests/fields/test_arguments.py | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/RELEASE.md b/RELEASE.md index ea04ddc7a6..0cb77c5715 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,6 +1,6 @@ Release type: patch -This release adds a new exception called `InvalidFieldArgument` which is raised when if a Union or Interface is used as an argument type. +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 diff --git a/tests/fields/test_arguments.py b/tests/fields/test_arguments.py index 09d9708c46..c61a4d3c66 100644 --- a/tests/fields/test_arguments.py +++ b/tests/fields/test_arguments.py @@ -448,5 +448,20 @@ class Adjective: text: str @strawberry.field - def add_word(adjective: Adjective) -> bool: + 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)