mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-10-31 16:07:27 +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