mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-10 19:56:45 +03:00
fix: Input fields and Arguments can now be deprecated (#1472)
Non-required InputFields and arguments now support deprecation via setting the `deprecation_reason` argument upon creation.
This commit is contained in:
parent
d5dadb7b1b
commit
19ea63b9c5
|
@ -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,
|
||||
|
@ -51,12 +55,16 @@ class Argument(MountedType):
|
|||
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):
|
||||
|
@ -68,6 +76,7 @@ class Argument(MountedType):
|
|||
and self.type == other.type
|
||||
and self.default_value == other.default_value
|
||||
and self.description == other.description
|
||||
and self.deprecation_reason == other.deprecation_reason
|
||||
)
|
||||
|
||||
|
||||
|
|
|
@ -55,11 +55,14 @@ class InputField(MountedType):
|
|||
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
|
||||
|
|
|
@ -316,6 +316,7 @@ class TypeMap(dict):
|
|||
default_value=field.default_value,
|
||||
out_name=name,
|
||||
description=field.description,
|
||||
deprecation_reason=field.deprecation_reason,
|
||||
)
|
||||
else:
|
||||
args = {}
|
||||
|
@ -327,6 +328,7 @@ class TypeMap(dict):
|
|||
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(
|
||||
|
|
|
@ -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()
|
||||
|
@ -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)}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
from functools import partial
|
||||
|
||||
from pytest import raises
|
||||
|
||||
from ..inputfield import InputField
|
||||
from ..structures import NonNull
|
||||
from .utils import MyLazyType
|
||||
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue
Block a user