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

Complete deprecated fields and arguments support #1472

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 13 additions & 4 deletions graphene/types/argument.py
Expand Up @@ -31,18 +31,22 @@ class Argument(MountedType):
type (class for a graphene.UnmountedType): must be a class (not an instance) of an
unmounted graphene type (ex. scalar or object) which is used for the type of this
argument in the GraphQL schema.
required (bool): indicates this argument as not null in the graphql schema. Same behavior
required (optional, bool): indicates this argument as not null in the graphql schema. Same behavior
as graphene.NonNull. Default False.
name (str): the name of the GraphQL argument. Defaults to parameter name.
description (str): the description of the GraphQL argument in the schema.
default_value (Any): The value to be provided if the user does not set this argument in
name (optional, str): the name of the GraphQL argument. Defaults to parameter name.
description (optional, str): the description of the GraphQL argument in the schema.
default_value (optional, Any): The value to be provided if the user does not set this argument in
the operation.
deprecation_reason (optional, str): Setting this value indicates that the argument is
depreciated and may provide instruction or reason on how for clients to proceed. Cannot be
set if the argument is required (see spec).
"""

def __init__(
self,
type_,
default_value=Undefined,
deprecation_reason=None,
description=None,
name=None,
required=False,
Expand All @@ -51,12 +55,16 @@ def __init__(
super(Argument, self).__init__(_creation_counter=_creation_counter)

if required:
assert (
deprecation_reason is None
), f"Argument {name} is required, cannot deprecate it."
type_ = NonNull(type_)

self.name = name
self._type = type_
self.default_value = default_value
self.description = description
self.deprecation_reason = deprecation_reason

@property
def type(self):
Expand All @@ -68,6 +76,7 @@ def __eq__(self, other):
and self.type == other.type
and self.default_value == other.default_value
and self.description == other.description
and self.deprecation_reason == other.deprecation_reason
)


Expand Down
5 changes: 4 additions & 1 deletion graphene/types/inputfield.py
Expand Up @@ -55,11 +55,14 @@ def __init__(
description=None,
required=False,
_creation_counter=None,
**extra_args
**extra_args,
):
super(InputField, self).__init__(_creation_counter=_creation_counter)
self.name = name
if required:
assert (
deprecation_reason is None
), f"InputField {name} is required, cannot deprecate it."
type_ = NonNull(type_)
self._type = type_
self.deprecation_reason = deprecation_reason
Expand Down
2 changes: 2 additions & 0 deletions graphene/types/schema.py
Expand Up @@ -316,6 +316,7 @@ def create_fields_for_type(self, graphene_type, is_input_type=False):
default_value=field.default_value,
out_name=name,
description=field.description,
deprecation_reason=field.deprecation_reason,
)
else:
args = {}
Expand All @@ -327,6 +328,7 @@ def create_fields_for_type(self, graphene_type, is_input_type=False):
out_name=arg_name,
description=arg.description,
default_value=arg.default_value,
deprecation_reason=arg.deprecation_reason,
)
subscribe = field.wrap_subscribe(
self.get_function_for_type(
Expand Down
40 changes: 38 additions & 2 deletions graphene/types/tests/test_argument.py
Expand Up @@ -18,8 +18,20 @@ def test_argument():


def test_argument_comparasion():
arg1 = Argument(String, name="Hey", description="Desc", default_value="default")
arg2 = Argument(String, name="Hey", description="Desc", default_value="default")
arg1 = Argument(
String,
name="Hey",
description="Desc",
default_value="default",
deprecation_reason="deprecated",
)
arg2 = Argument(
String,
name="Hey",
description="Desc",
default_value="default",
deprecation_reason="deprecated",
)

assert arg1 == arg2
assert arg1 != String()
Expand All @@ -40,6 +52,30 @@ def test_to_arguments():
}


def test_to_arguments_deprecated():
args = {"unmounted_arg": String(required=False, deprecation_reason="deprecated")}

my_args = to_arguments(args)
assert my_args == {
"unmounted_arg": Argument(
String, required=False, deprecation_reason="deprecated"
),
}


def test_to_arguments_required_deprecated():
args = {
"unmounted_arg": String(
required=True, name="arg", deprecation_reason="deprecated"
)
}

with raises(AssertionError) as exc_info:
to_arguments(args)

assert str(exc_info.value) == "Argument arg is required, cannot deprecate it."


def test_to_arguments_raises_if_field():
args = {"arg_string": Field(String)}

Expand Down
9 changes: 8 additions & 1 deletion graphene/types/tests/test_field.py
Expand Up @@ -128,13 +128,20 @@ def test_field_name_as_argument():

def test_field_source_argument_as_kw():
MyType = object()
field = Field(MyType, b=NonNull(True), c=Argument(None), a=NonNull(False))
deprecation_reason = "deprecated"
field = Field(
MyType,
b=NonNull(True),
c=Argument(None, deprecation_reason=deprecation_reason),
a=NonNull(False),
)
assert list(field.args) == ["b", "c", "a"]
assert isinstance(field.args["b"], Argument)
assert isinstance(field.args["b"].type, NonNull)
assert field.args["b"].type.of_type is True
assert isinstance(field.args["c"], Argument)
assert field.args["c"].type is None
assert field.args["c"].deprecation_reason == deprecation_reason
assert isinstance(field.args["a"], Argument)
assert isinstance(field.args["a"].type, NonNull)
assert field.args["a"].type.of_type is False
18 changes: 18 additions & 0 deletions graphene/types/tests/test_inputfield.py
@@ -1,5 +1,7 @@
from functools import partial

from pytest import raises

from ..inputfield import InputField
from ..structures import NonNull
from .utils import MyLazyType
Expand All @@ -12,6 +14,22 @@ def test_inputfield_required():
assert field.type.of_type == MyType


def test_inputfield_deprecated():
MyType = object()
deprecation_reason = "deprecated"
field = InputField(MyType, required=False, deprecation_reason=deprecation_reason)
assert isinstance(field.type, type(MyType))
assert field.deprecation_reason == deprecation_reason


def test_inputfield_required_deprecated():
MyType = object()
with raises(AssertionError) as exc_info:
InputField(MyType, name="input", required=True, deprecation_reason="deprecated")

assert str(exc_info.value) == "InputField input is required, cannot deprecate it."


def test_inputfield_with_lazy_type():
MyType = object()
field = InputField(lambda: MyType)
Expand Down