def test_introspects_on_input_object(): TestInputObject = GraphQLInputObjectType('TestInputObject', OrderedDict([ ('a', GraphQLInputObjectField(GraphQLString, default_value='foo')), ('b', GraphQLInputObjectField(GraphQLList(GraphQLString))) ])) TestType = GraphQLObjectType('TestType', { 'field': GraphQLField( type=GraphQLString, args={'complex': GraphQLArgument(TestInputObject)}, resolver=lambda obj, info, **args: json.dumps(args.get('complex')) ) }) schema = GraphQLSchema(TestType) request = ''' { __schema { types { kind name inputFields { name type { ...TypeRef } defaultValue } } } } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } ''' result = graphql(schema, request) assert not result.errors assert {'kind': 'INPUT_OBJECT', 'name': 'TestInputObject', 'inputFields': [{'name': 'a', 'type': {'kind': 'SCALAR', 'name': 'String', 'ofType': None}, 'defaultValue': '"foo"'}, {'name': 'b', 'type': {'kind': 'LIST', 'name': None, 'ofType': {'kind': 'SCALAR', 'name': 'String', 'ofType': None}}, 'defaultValue': None}]} in result.data['__schema']['types']
DogOrHuman = GraphQLUnionType('DogOrHuman', [Dog, Human]) HumanOrAlien = GraphQLUnionType('HumanOrAlien', [Human, Alien]) FurColor = GraphQLEnumType('FurColor', { 'BROWN': GraphQLEnumValue(0), 'BLACK': GraphQLEnumValue(1), 'TAN': GraphQLEnumValue(2), 'SPOTTED': GraphQLEnumValue(3), }) ComplexInput = GraphQLInputObjectType('ComplexInput', { 'requiredField': GraphQLInputObjectField(GraphQLNonNull(GraphQLBoolean)), 'intField': GraphQLInputObjectField(GraphQLInt), 'stringField': GraphQLInputObjectField(GraphQLString), 'booleanField': GraphQLInputObjectField(GraphQLBoolean), 'stringListField': GraphQLInputObjectField(GraphQLList(GraphQLString)), }) ComplicatedArgs = GraphQLObjectType('ComplicatedArgs', { 'intArgField': GraphQLField(GraphQLString, { 'intArg': GraphQLArgument(GraphQLInt) }), 'nonNullIntArgField': GraphQLField(GraphQLString, { 'nonNullIntArg': GraphQLArgument(GraphQLNonNull(GraphQLInt)) }), 'stringArgField': GraphQLField(GraphQLString, { 'stringArg': GraphQLArgument(GraphQLString) }), 'booleanArgField': GraphQLField(GraphQLString, {
def introspects_on_input_object(): TestInputObject = GraphQLInputObjectType( 'TestInputObject', { 'a': GraphQLInputField(GraphQLString, default_value='tes\t de\fault'), 'b': GraphQLInputField(GraphQLList(GraphQLString)), 'c': GraphQLInputField(GraphQLString, default_value=None) }) TestType = GraphQLObjectType( 'TestType', { 'field': GraphQLField( GraphQLString, args={'complex': GraphQLArgument(TestInputObject)}, resolve=lambda obj, info, **args: repr(args.get('complex') )) }) schema = GraphQLSchema(TestType) request = """ { __type(name: "TestInputObject") { kind name inputFields { name type { ...TypeRef } defaultValue } } } fragment TypeRef on __Type { kind name ofType { kind name ofType { kind name ofType { kind name } } } } """ assert graphql_sync(schema, request) == ({ '__type': { 'kind': 'INPUT_OBJECT', 'name': 'TestInputObject', 'inputFields': [{ 'name': 'a', 'type': { 'kind': 'SCALAR', 'name': 'String', 'ofType': None }, 'defaultValue': '"tes\\t de\\fault"' }, { 'name': 'b', 'type': { 'kind': 'LIST', 'name': None, 'ofType': { 'kind': 'SCALAR', 'name': 'String', 'ofType': None }, }, 'defaultValue': None, }, { 'name': 'c', 'type': { 'kind': 'SCALAR', 'name': 'String', 'ofType': None }, 'defaultValue': 'null' }] } }, None)
"foo": GraphQLField(FooType), }, ) BizType = GraphQLObjectType( name="Biz", fields=lambda: {"fizz": GraphQLField(GraphQLString)}) SomeUnionType = GraphQLUnionType(name="SomeUnion", types=[FooType, BizType]) SomeEnumType = GraphQLEnumType(name="SomeEnum", values={ "ONE": GraphQLEnumValue(1), "TWO": GraphQLEnumValue(2) }) SomeInputType = GraphQLInputObjectType( "SomeInput", lambda: {"fooArg": GraphQLInputField(GraphQLString)}) FooDirective = GraphQLDirective( name="foo", args={"input": GraphQLArgument(SomeInputType)}, is_repeatable=True, locations=[ DirectiveLocation.SCHEMA, DirectiveLocation.SCALAR, DirectiveLocation.OBJECT, DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.ARGUMENT_DEFINITION, DirectiveLocation.INTERFACE, DirectiveLocation.UNION, DirectiveLocation.ENUM, DirectiveLocation.ENUM_VALUE,
TestComplexScalar = GraphQLScalarType( name='ComplexScalar', serialize=lambda v: 'SerializedValue' if v == 'DeserializedValue' else None, parse_value=lambda v: 'DeserializedValue' if v == 'SerializedValue' else None, parse_literal=lambda v: 'DeserializedValue' if v.value == 'SerializedValue' else None ) class my_special_dict(dict): pass TestInputObject = GraphQLInputObjectType('TestInputObject', OrderedDict([ ('a', GraphQLInputObjectField(GraphQLString)), ('b', GraphQLInputObjectField(GraphQLList(GraphQLString))), ('c', GraphQLInputObjectField(GraphQLNonNull(GraphQLString))), ('d', GraphQLInputObjectField(TestComplexScalar)) ])) TestCustomInputObject = GraphQLInputObjectType('TestCustomInputObject', OrderedDict([ ('a', GraphQLInputObjectField(GraphQLString)), ]), container_type=my_special_dict) def stringify(obj): return json.dumps(obj, sort_keys=True) def input_to_json(obj, info, **args): input = args.get('input') if input:
"BROWN": GraphQLEnumValue(0), "BLACK": GraphQLEnumValue(1), "TAN": GraphQLEnumValue(2), "SPOTTED": GraphQLEnumValue(3), "NO_FUR": GraphQLEnumValue(), "UNKNOWN": None, }, ) ComplexInput = GraphQLInputObjectType( "ComplexInput", { "requiredField": GraphQLInputField(GraphQLNonNull(GraphQLBoolean)), "nonNullField": GraphQLInputField( GraphQLNonNull(GraphQLBoolean), default_value=False ), "intField": GraphQLInputField(GraphQLInt), "stringField": GraphQLInputField(GraphQLString), "booleanField": GraphQLInputField(GraphQLBoolean), "stringListField": GraphQLInputField(GraphQLList(GraphQLString)), }, ) ComplicatedArgs = GraphQLObjectType( "ComplicatedArgs", { "intArgField": GraphQLField( GraphQLString, {"intArg": GraphQLArgument(GraphQLInt)} ), "nonNullIntArgField": GraphQLField( GraphQLString,
"stars": GraphQLField( GraphQLNonNull(GraphQLInt), description="The number of stars this review gave, 1-5", ), "commentary": GraphQLField(GraphQLString, description="Comment about the movie"), }, ) reviewInputType = GraphQLInputObjectType( "ReviewInput", description="The input object sent when someone is creating a new review", fields={ "stars": GraphQLInputObjectField(GraphQLInt, description="0-5 stars"), "commentary": GraphQLInputObjectField( GraphQLString, description="Comment about the movie, optional"), }, ) queryType = GraphQLObjectType( "Query", fields=lambda: { "hero": GraphQLField( characterInterface, args={ "episode": GraphQLArgument(
assert ast.value == "SerializedValue" return parse_serialized_value(ast.value) TestComplexScalar = GraphQLScalarType( name="ComplexScalar", parse_value=parse_serialized_value, parse_literal=parse_literal_value, ) TestInputObject = GraphQLInputObjectType( "TestInputObject", { "a": GraphQLInputField(GraphQLString), "b": GraphQLInputField(GraphQLList(GraphQLString)), "c": GraphQLInputField(GraphQLNonNull(GraphQLString)), "d": GraphQLInputField(TestComplexScalar), }, ) TestCustomInputObject = GraphQLInputObjectType( "TestCustomInputObject", {"x": GraphQLInputField(GraphQLFloat), "y": GraphQLInputField(GraphQLFloat)}, out_type=lambda value: f"(x|y) = ({value['x']}|{value['y']})", ) TestNestedInputObject = GraphQLInputObjectType( "TestNestedInputObject", {
GraphQLField, GraphQLInterfaceType, GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLInputObjectType, GraphQLInputField, GraphQLDirective, GraphQLArgument, GraphQLList, ) InterfaceType = GraphQLInterfaceType( "Interface", {"fieldName": GraphQLField(GraphQLString)}) DirectiveInputType = GraphQLInputObjectType( "DirInput", {"field": GraphQLInputField(GraphQLString)}) WrappedDirectiveInputType = GraphQLInputObjectType( "WrappedDirInput", {"field": GraphQLInputField(GraphQLString)}) Directive = GraphQLDirective( name="dir", locations=[DirectiveLocation.OBJECT], args={ "arg": GraphQLArgument(DirectiveInputType), "argList": GraphQLArgument(GraphQLList(WrappedDirectiveInputType)), }, ) Schema = GraphQLSchema( query=GraphQLObjectType(
TestComplexScalar = GraphQLScalarType( name="ComplexScalar", serialize=lambda value: "SerializedValue" if value == "DeserializedValue" else None, parse_value=lambda value: "DeserializedValue" if value == "SerializedValue" else None, parse_literal=lambda ast, _variables=None: "DeserializedValue" if ast.value == "SerializedValue" else None, ) TestInputObject = GraphQLInputObjectType( "TestInputObject", { "a": GraphQLInputField(GraphQLString), "b": GraphQLInputField(GraphQLList(GraphQLString)), "c": GraphQLInputField(GraphQLNonNull(GraphQLString)), "d": GraphQLInputField(TestComplexScalar), }, ) TestNestedInputObject = GraphQLInputObjectType( "TestNestedInputObject", { "na": GraphQLInputField(GraphQLNonNull(TestInputObject)), "nb": GraphQLInputField(GraphQLNonNull(GraphQLString)), }, ) TestEnum = GraphQLEnumType( "TestEnum",
def describe_value_from_ast(): @fixture def test_case(type_, value_text, expected): value_node = parse_value(value_text) assert value_from_ast(value_node, type_) == expected @fixture def test_case_expect_nan(type_, value_text): value_node = parse_value(value_text) assert isnan(value_from_ast(value_node, type_)) @fixture def test_case_with_vars(variables, type_, value_text, expected): value_node = parse_value(value_text) assert value_from_ast(value_node, type_, variables) == expected def rejects_empty_input(): # noinspection PyTypeChecker assert value_from_ast(None, GraphQLBoolean) is INVALID def converts_according_to_input_coercion_rules(): test_case(GraphQLBoolean, 'true', True) test_case(GraphQLBoolean, 'false', False) test_case(GraphQLInt, '123', 123) test_case(GraphQLFloat, '123', 123) test_case(GraphQLFloat, '123.456', 123.456) test_case(GraphQLString, '"abc123"', 'abc123') test_case(GraphQLID, '123456', '123456') test_case(GraphQLID, '"123456"', '123456') def does_not_convert_when_input_coercion_rules_reject_a_value(): test_case(GraphQLBoolean, '123', INVALID) test_case(GraphQLInt, '123.456', INVALID) test_case(GraphQLInt, 'true', INVALID) test_case(GraphQLInt, '"123"', INVALID) test_case(GraphQLFloat, '"123"', INVALID) test_case(GraphQLString, '123', INVALID) test_case(GraphQLString, 'true', INVALID) test_case(GraphQLID, '123.456', INVALID) test_enum = GraphQLEnumType( 'TestColor', { 'RED': 1, 'GREEN': 2, 'BLUE': 3, 'NULL': None, 'INVALID': INVALID, 'NAN': nan }) def converts_enum_values_according_to_input_coercion_rules(): test_case(test_enum, 'RED', 1) test_case(test_enum, 'BLUE', 3) test_case(test_enum, 'YELLOW', INVALID) test_case(test_enum, '3', INVALID) test_case(test_enum, '"BLUE"', INVALID) test_case(test_enum, 'null', None) test_case(test_enum, 'NULL', None) test_case(test_enum, 'INVALID', INVALID) # nan is not equal to itself, needs a special test case test_case_expect_nan(test_enum, 'NAN') # Boolean! non_null_bool = GraphQLNonNull(GraphQLBoolean) # [Boolean] list_of_bool = GraphQLList(GraphQLBoolean) # [Boolean!] list_of_non_null_bool = GraphQLList(non_null_bool) # [Boolean]! non_null_list_of_bool = GraphQLNonNull(list_of_bool) # [Boolean!]! non_null_list_of_non_mull_bool = GraphQLNonNull(list_of_non_null_bool) def coerces_to_null_unless_non_null(): test_case(GraphQLBoolean, 'null', None) test_case(non_null_bool, 'null', INVALID) def coerces_lists_of_values(): test_case(list_of_bool, 'true', [True]) test_case(list_of_bool, '123', INVALID) test_case(list_of_bool, 'null', None) test_case(list_of_bool, '[true, false]', [True, False]) test_case(list_of_bool, '[true, 123]', INVALID) test_case(list_of_bool, '[true, null]', [True, None]) test_case(list_of_bool, '{ true: true }', INVALID) def coerces_non_null_lists_of_values(): test_case(non_null_list_of_bool, 'true', [True]) test_case(non_null_list_of_bool, '123', INVALID) test_case(non_null_list_of_bool, 'null', INVALID) test_case(non_null_list_of_bool, '[true, false]', [True, False]) test_case(non_null_list_of_bool, '[true, 123]', INVALID) test_case(non_null_list_of_bool, '[true, null]', [True, None]) def coerces_lists_of_non_null_values(): test_case(list_of_non_null_bool, 'true', [True]) test_case(list_of_non_null_bool, '123', INVALID) test_case(list_of_non_null_bool, 'null', None) test_case(list_of_non_null_bool, '[true, false]', [True, False]) test_case(list_of_non_null_bool, '[true, 123]', INVALID) test_case(list_of_non_null_bool, '[true, null]', INVALID) def coerces_non_null_lists_of_non_null_values(): test_case(non_null_list_of_non_mull_bool, 'true', [True]) test_case(non_null_list_of_non_mull_bool, '123', INVALID) test_case(non_null_list_of_non_mull_bool, 'null', INVALID) test_case(non_null_list_of_non_mull_bool, '[true, false]', [True, False]) test_case(non_null_list_of_non_mull_bool, '[true, 123]', INVALID) test_case(non_null_list_of_non_mull_bool, '[true, null]', INVALID) test_input_obj = GraphQLInputObjectType( 'TestInput', { 'int': GraphQLInputField(GraphQLInt, default_value=42), 'bool': GraphQLInputField(GraphQLBoolean), 'requiredBool': GraphQLInputField(non_null_bool) }) def coerces_input_objects_according_to_input_coercion_rules(): test_case(test_input_obj, 'null', None) test_case(test_input_obj, '123', INVALID) test_case(test_input_obj, '[]', INVALID) test_case(test_input_obj, '{ int: 123, requiredBool: false }', { 'int': 123, 'requiredBool': False, }) test_case(test_input_obj, '{ bool: true, requiredBool: false }', { 'int': 42, 'bool': True, 'requiredBool': False, }) test_case(test_input_obj, '{ int: true, requiredBool: true }', INVALID) test_case(test_input_obj, '{ requiredBool: null }', INVALID) test_case(test_input_obj, '{ bool: true }', INVALID) def accepts_variable_values_assuming_already_coerced(): test_case_with_vars({}, GraphQLBoolean, '$var', INVALID) test_case_with_vars({'var': True}, GraphQLBoolean, '$var', True) test_case_with_vars({'var': None}, GraphQLBoolean, '$var', None) def asserts_variables_are_provided_as_items_in_lists(): test_case_with_vars({}, list_of_bool, '[ $foo ]', [None]) test_case_with_vars({}, list_of_non_null_bool, '[ $foo ]', INVALID) test_case_with_vars({'foo': True}, list_of_non_null_bool, '[ $foo ]', [True]) # Note: variables are expected to have already been coerced, so we # do not expect the singleton wrapping behavior for variables. test_case_with_vars({'foo': True}, list_of_non_null_bool, '$foo', True) test_case_with_vars({'foo': [True]}, list_of_non_null_bool, '$foo', [True]) def omits_input_object_fields_for_unprovided_variables(): test_case_with_vars({}, test_input_obj, '{ int: $foo, bool: $foo, requiredBool: true }', { 'int': 42, 'requiredBool': True }) test_case_with_vars({}, test_input_obj, '{ requiredBool: $foo }', INVALID) test_case_with_vars({'foo': True}, test_input_obj, '{ requiredBool: $foo }', { 'int': 42, 'requiredBool': True })
def schema_with_input_field_of_type(input_field_type): BadInputObjectType = GraphQLInputObjectType('BadInputObject', { 'badField': GraphQLInputField(input_field_type)}) return GraphQLSchema(GraphQLObjectType('Query', { 'f': GraphQLField(GraphQLString, args={ 'badArg': GraphQLArgument(BadInputObjectType)})}))
SomeObjectType = GraphQLObjectType( name='SomeObject', fields=lambda: {'f': GraphQLField(SomeObjectType)}, interfaces=[SomeInterfaceType]) SomeUnionType = GraphQLUnionType( name='SomeUnion', types=[SomeObjectType]) SomeEnumType = GraphQLEnumType( name='SomeEnum', values={'ONLY': GraphQLEnumValue()}) SomeInputObjectType = GraphQLInputObjectType( name='SomeInputObject', fields={'val': GraphQLInputField(GraphQLString, default_value='hello')}) def with_modifiers(types): return types + [ GraphQLList(t) for t in types] + [ GraphQLNonNull(t) for t in types] + [ GraphQLNonNull(GraphQLList(t)) for t in types] output_types = with_modifiers([ GraphQLString, SomeScalarType, SomeEnumType, SomeObjectType,
def describe_value_from_ast(): def _test_case(type_, value_text, expected): value_node = parse_value(value_text) value = value_from_ast(value_node, type_) if isinstance(expected, float) and isnan(expected): assert isnan(value) else: assert value == expected def _test_case_with_vars(variables, type_, value_text, expected): value_node = parse_value(value_text) assert value_from_ast(value_node, type_, variables) == expected def rejects_empty_input(): # noinspection PyTypeChecker assert value_from_ast(None, GraphQLBoolean) is INVALID def converts_according_to_input_coercion_rules(): _test_case(GraphQLBoolean, "true", True) _test_case(GraphQLBoolean, "false", False) _test_case(GraphQLInt, "123", 123) _test_case(GraphQLFloat, "123", 123) _test_case(GraphQLFloat, "123.456", 123.456) _test_case(GraphQLString, '"abc123"', "abc123") _test_case(GraphQLID, "123456", "123456") _test_case(GraphQLID, '"123456"', "123456") def does_not_convert_when_input_coercion_rules_reject_a_value(): _test_case(GraphQLBoolean, "123", INVALID) _test_case(GraphQLInt, "123.456", INVALID) _test_case(GraphQLInt, "true", INVALID) _test_case(GraphQLInt, '"123"', INVALID) _test_case(GraphQLFloat, '"123"', INVALID) _test_case(GraphQLString, "123", INVALID) _test_case(GraphQLString, "true", INVALID) _test_case(GraphQLID, "123.456", INVALID) test_enum = GraphQLEnumType( "TestColor", { "RED": 1, "GREEN": 2, "BLUE": 3, "NULL": None, "NAN": nan, "NO_CUSTOM_VALUE": INVALID, }, ) def converts_enum_values_according_to_input_coercion_rules(): _test_case(test_enum, "RED", 1) _test_case(test_enum, "BLUE", 3) _test_case(test_enum, "YELLOW", INVALID) _test_case(test_enum, "3", INVALID) _test_case(test_enum, '"BLUE"', INVALID) _test_case(test_enum, "null", None) _test_case(test_enum, "NULL", None) _test_case(test_enum, "NAN", nan) _test_case(test_enum, "NO_CUSTOM_VALUE", "NO_CUSTOM_VALUE") # Boolean! non_null_bool = GraphQLNonNull(GraphQLBoolean) # [Boolean] list_of_bool = GraphQLList(GraphQLBoolean) # [Boolean!] list_of_non_null_bool = GraphQLList(non_null_bool) # [Boolean]! non_null_list_of_bool = GraphQLNonNull(list_of_bool) # [Boolean!]! non_null_list_of_non_mull_bool = GraphQLNonNull(list_of_non_null_bool) def coerces_to_null_unless_non_null(): _test_case(GraphQLBoolean, "null", None) _test_case(non_null_bool, "null", INVALID) def coerces_lists_of_values(): _test_case(list_of_bool, "true", [True]) _test_case(list_of_bool, "123", INVALID) _test_case(list_of_bool, "null", None) _test_case(list_of_bool, "[true, false]", [True, False]) _test_case(list_of_bool, "[true, 123]", INVALID) _test_case(list_of_bool, "[true, null]", [True, None]) _test_case(list_of_bool, "{ true: true }", INVALID) def coerces_non_null_lists_of_values(): _test_case(non_null_list_of_bool, "true", [True]) _test_case(non_null_list_of_bool, "123", INVALID) _test_case(non_null_list_of_bool, "null", INVALID) _test_case(non_null_list_of_bool, "[true, false]", [True, False]) _test_case(non_null_list_of_bool, "[true, 123]", INVALID) _test_case(non_null_list_of_bool, "[true, null]", [True, None]) def coerces_lists_of_non_null_values(): _test_case(list_of_non_null_bool, "true", [True]) _test_case(list_of_non_null_bool, "123", INVALID) _test_case(list_of_non_null_bool, "null", None) _test_case(list_of_non_null_bool, "[true, false]", [True, False]) _test_case(list_of_non_null_bool, "[true, 123]", INVALID) _test_case(list_of_non_null_bool, "[true, null]", INVALID) def coerces_non_null_lists_of_non_null_values(): _test_case(non_null_list_of_non_mull_bool, "true", [True]) _test_case(non_null_list_of_non_mull_bool, "123", INVALID) _test_case(non_null_list_of_non_mull_bool, "null", INVALID) _test_case(non_null_list_of_non_mull_bool, "[true, false]", [True, False]) _test_case(non_null_list_of_non_mull_bool, "[true, 123]", INVALID) _test_case(non_null_list_of_non_mull_bool, "[true, null]", INVALID) test_input_obj = GraphQLInputObjectType( "TestInput", { "int": GraphQLInputField(GraphQLInt, default_value=42), "bool": GraphQLInputField(GraphQLBoolean), "requiredBool": GraphQLInputField(non_null_bool), }, ) def coerces_input_objects_according_to_input_coercion_rules(): _test_case(test_input_obj, "null", None) _test_case(test_input_obj, "123", INVALID) _test_case(test_input_obj, "[]", INVALID) _test_case( test_input_obj, "{ int: 123, requiredBool: false }", { "int": 123, "requiredBool": False }, ) _test_case( test_input_obj, "{ bool: true, requiredBool: false }", { "int": 42, "bool": True, "requiredBool": False }, ) _test_case(test_input_obj, "{ int: true, requiredBool: true }", INVALID) _test_case(test_input_obj, "{ requiredBool: null }", INVALID) _test_case(test_input_obj, "{ bool: true }", INVALID) def accepts_variable_values_assuming_already_coerced(): _test_case_with_vars({}, GraphQLBoolean, "$var", INVALID) _test_case_with_vars({"var": True}, GraphQLBoolean, "$var", True) _test_case_with_vars({"var": None}, GraphQLBoolean, "$var", None) def asserts_variables_are_provided_as_items_in_lists(): _test_case_with_vars({}, list_of_bool, "[ $foo ]", [None]) _test_case_with_vars({}, list_of_non_null_bool, "[ $foo ]", INVALID) _test_case_with_vars({"foo": True}, list_of_non_null_bool, "[ $foo ]", [True]) # Note: variables are expected to have already been coerced, so we # do not expect the singleton wrapping behavior for variables. _test_case_with_vars({"foo": True}, list_of_non_null_bool, "$foo", True) _test_case_with_vars({"foo": [True]}, list_of_non_null_bool, "$foo", [True]) def omits_input_object_fields_for_unprovided_variables(): _test_case_with_vars( {}, test_input_obj, "{ int: $foo, bool: $foo, requiredBool: true }", { "int": 42, "requiredBool": True }, ) _test_case_with_vars({}, test_input_obj, "{ requiredBool: $foo }", INVALID) _test_case_with_vars( {"foo": True}, test_input_obj, "{ requiredBool: $foo }", { "int": 42, "requiredBool": True }, ) def transforms_names_using_out_name(): # This is an extension of GraphQL.js. complex_input_obj = GraphQLInputObjectType( "Complex", { "realPart": GraphQLInputField(GraphQLFloat, out_name="real_part"), "imagPart": GraphQLInputField( GraphQLFloat, default_value=0, out_name="imag_part"), }, ) _test_case(complex_input_obj, "{ realPart: 1 }", { "real_part": 1, "imag_part": 0 }) def transforms_values_with_out_type(): # This is an extension of GraphQL.js. complex_input_obj = GraphQLInputObjectType( "Complex", { "real": GraphQLInputField(GraphQLFloat), "imag": GraphQLInputField(GraphQLFloat), }, out_type=lambda value: complex(value["real"], value["imag"]), ) _test_case(complex_input_obj, "{ real: 1, imag: 2 }", 1 + 2j)
SomeInterfaceType = GraphQLInterfaceType( name="SomeInterface", fields=lambda: {"f": GraphQLField(SomeObjectType)}) SomeObjectType = GraphQLObjectType( name="SomeObject", fields=lambda: {"f": GraphQLField(SomeObjectType)}, interfaces=[SomeInterfaceType], ) SomeUnionType = GraphQLUnionType(name="SomeUnion", types=[SomeObjectType]) SomeEnumType = GraphQLEnumType(name="SomeEnum", values={"ONLY": GraphQLEnumValue()}) SomeInputObjectType = GraphQLInputObjectType( name="SomeInputObject", fields={"val": GraphQLInputField(GraphQLString, default_value="hello")}, ) def with_modifiers( types: List[GraphQLNamedType] ) -> List[Union[GraphQLNamedType, GraphQLWrappingType]]: types = cast(List[Union[GraphQLNamedType, GraphQLWrappingType]], types) return (types + [GraphQLList(t) for t in types] + [GraphQLNonNull(t) for t in types] + [GraphQLNonNull(GraphQLList(t)) for t in types]) output_types: List[GraphQLOutputType] = with_modifiers([ GraphQLString, SomeScalarType,
def describe_value_from_ast(): def _test_case(type_, value_text, expected): value_node = parse_value(value_text) assert value_from_ast(value_node, type_) == expected def _test_case_expect_nan(type_, value_text): value_node = parse_value(value_text) assert isnan(value_from_ast(value_node, type_)) def _test_case_with_vars(variables, type_, value_text, expected): value_node = parse_value(value_text) assert value_from_ast(value_node, type_, variables) == expected def rejects_empty_input(): # noinspection PyTypeChecker assert value_from_ast(None, GraphQLBoolean) is INVALID def converts_according_to_input_coercion_rules(): _test_case(GraphQLBoolean, "true", True) _test_case(GraphQLBoolean, "false", False) _test_case(GraphQLInt, "123", 123) _test_case(GraphQLFloat, "123", 123) _test_case(GraphQLFloat, "123.456", 123.456) _test_case(GraphQLString, '"abc123"', "abc123") _test_case(GraphQLID, "123456", "123456") _test_case(GraphQLID, '"123456"', "123456") def does_not_convert_when_input_coercion_rules_reject_a_value(): _test_case(GraphQLBoolean, "123", INVALID) _test_case(GraphQLInt, "123.456", INVALID) _test_case(GraphQLInt, "true", INVALID) _test_case(GraphQLInt, '"123"', INVALID) _test_case(GraphQLFloat, '"123"', INVALID) _test_case(GraphQLString, "123", INVALID) _test_case(GraphQLString, "true", INVALID) _test_case(GraphQLID, "123.456", INVALID) test_enum = GraphQLEnumType( "TestColor", { "RED": 1, "GREEN": 2, "BLUE": 3, "NULL": None, "INVALID": INVALID, "NAN": nan }, ) def converts_enum_values_according_to_input_coercion_rules(): _test_case(test_enum, "RED", 1) _test_case(test_enum, "BLUE", 3) _test_case(test_enum, "YELLOW", INVALID) _test_case(test_enum, "3", INVALID) _test_case(test_enum, '"BLUE"', INVALID) _test_case(test_enum, "null", None) _test_case(test_enum, "NULL", None) _test_case(test_enum, "INVALID", INVALID) # nan is not equal to itself, needs a special test case _test_case_expect_nan(test_enum, "NAN") # Boolean! non_null_bool = GraphQLNonNull(GraphQLBoolean) # [Boolean] list_of_bool = GraphQLList(GraphQLBoolean) # [Boolean!] list_of_non_null_bool = GraphQLList(non_null_bool) # [Boolean]! non_null_list_of_bool = GraphQLNonNull(list_of_bool) # [Boolean!]! non_null_list_of_non_mull_bool = GraphQLNonNull(list_of_non_null_bool) def coerces_to_null_unless_non_null(): _test_case(GraphQLBoolean, "null", None) _test_case(non_null_bool, "null", INVALID) def coerces_lists_of_values(): _test_case(list_of_bool, "true", [True]) _test_case(list_of_bool, "123", INVALID) _test_case(list_of_bool, "null", None) _test_case(list_of_bool, "[true, false]", [True, False]) _test_case(list_of_bool, "[true, 123]", INVALID) _test_case(list_of_bool, "[true, null]", [True, None]) _test_case(list_of_bool, "{ true: true }", INVALID) def coerces_non_null_lists_of_values(): _test_case(non_null_list_of_bool, "true", [True]) _test_case(non_null_list_of_bool, "123", INVALID) _test_case(non_null_list_of_bool, "null", INVALID) _test_case(non_null_list_of_bool, "[true, false]", [True, False]) _test_case(non_null_list_of_bool, "[true, 123]", INVALID) _test_case(non_null_list_of_bool, "[true, null]", [True, None]) def coerces_lists_of_non_null_values(): _test_case(list_of_non_null_bool, "true", [True]) _test_case(list_of_non_null_bool, "123", INVALID) _test_case(list_of_non_null_bool, "null", None) _test_case(list_of_non_null_bool, "[true, false]", [True, False]) _test_case(list_of_non_null_bool, "[true, 123]", INVALID) _test_case(list_of_non_null_bool, "[true, null]", INVALID) def coerces_non_null_lists_of_non_null_values(): _test_case(non_null_list_of_non_mull_bool, "true", [True]) _test_case(non_null_list_of_non_mull_bool, "123", INVALID) _test_case(non_null_list_of_non_mull_bool, "null", INVALID) _test_case(non_null_list_of_non_mull_bool, "[true, false]", [True, False]) _test_case(non_null_list_of_non_mull_bool, "[true, 123]", INVALID) _test_case(non_null_list_of_non_mull_bool, "[true, null]", INVALID) test_input_obj = GraphQLInputObjectType( "TestInput", { "int": GraphQLInputField(GraphQLInt, default_value=42), "bool": GraphQLInputField(GraphQLBoolean), "requiredBool": GraphQLInputField(non_null_bool), }, ) def coerces_input_objects_according_to_input_coercion_rules(): _test_case(test_input_obj, "null", None) _test_case(test_input_obj, "123", INVALID) _test_case(test_input_obj, "[]", INVALID) _test_case( test_input_obj, "{ int: 123, requiredBool: false }", { "int": 123, "requiredBool": False }, ) _test_case( test_input_obj, "{ bool: true, requiredBool: false }", { "int": 42, "bool": True, "requiredBool": False }, ) _test_case(test_input_obj, "{ int: true, requiredBool: true }", INVALID) _test_case(test_input_obj, "{ requiredBool: null }", INVALID) _test_case(test_input_obj, "{ bool: true }", INVALID) def accepts_variable_values_assuming_already_coerced(): _test_case_with_vars({}, GraphQLBoolean, "$var", INVALID) _test_case_with_vars({"var": True}, GraphQLBoolean, "$var", True) _test_case_with_vars({"var": None}, GraphQLBoolean, "$var", None) def asserts_variables_are_provided_as_items_in_lists(): _test_case_with_vars({}, list_of_bool, "[ $foo ]", [None]) _test_case_with_vars({}, list_of_non_null_bool, "[ $foo ]", INVALID) _test_case_with_vars({"foo": True}, list_of_non_null_bool, "[ $foo ]", [True]) # Note: variables are expected to have already been coerced, so we # do not expect the singleton wrapping behavior for variables. _test_case_with_vars({"foo": True}, list_of_non_null_bool, "$foo", True) _test_case_with_vars({"foo": [True]}, list_of_non_null_bool, "$foo", [True]) def omits_input_object_fields_for_unprovided_variables(): _test_case_with_vars( {}, test_input_obj, "{ int: $foo, bool: $foo, requiredBool: true }", { "int": 42, "requiredBool": True }, ) _test_case_with_vars({}, test_input_obj, "{ requiredBool: $foo }", INVALID) _test_case_with_vars( {"foo": True}, test_input_obj, "{ requiredBool: $foo }", { "int": 42, "requiredBool": True }, )
BlogMutation = GraphQLObjectType('Mutation', {'writeArticle': GraphQLField(BlogArticle)}) BlogSubscription = GraphQLObjectType( 'Subscription', { 'articleSubscribe': GraphQLField(args={'id': GraphQLArgument(GraphQLString)}, type_=BlogArticle) }) ObjectType = GraphQLObjectType('Object', {}) InterfaceType = GraphQLInterfaceType('Interface') UnionType = GraphQLUnionType('Union', [ObjectType], resolve_type=lambda: None) EnumType = GraphQLEnumType('Enum', {'foo': GraphQLEnumValue()}) InputObjectType = GraphQLInputObjectType('InputObject', {}) ScalarType = GraphQLScalarType('Scalar', serialize=lambda: None, parse_value=lambda: None, parse_literal=lambda: None) def schema_with_field_type(type_: GraphQLOutputType) -> GraphQLSchema: return GraphQLSchema(query=GraphQLObjectType( 'Query', {'field': GraphQLField(type_)}), types=[type_]) def describe_type_system_example(): def defines_a_query_only_schema(): BlogSchema = GraphQLSchema(BlogQuery)
BizType = GraphQLObjectType( name='Biz', fields=lambda: { 'fizz': GraphQLField(GraphQLString)}) SomeUnionType = GraphQLUnionType( name='SomeUnion', types=[FooType, BizType]) SomeEnumType = GraphQLEnumType( name='SomeEnum', values={ 'ONE': GraphQLEnumValue(1), 'TWO': GraphQLEnumValue(2)}) SomeInputType = GraphQLInputObjectType('SomeInput', lambda: { 'fooArg': GraphQLInputField(GraphQLString)}) FooDirective = GraphQLDirective( name='foo', args={'input': GraphQLArgument(SomeInputType)}, locations=[ DirectiveLocation.SCHEMA, DirectiveLocation.SCALAR, DirectiveLocation.OBJECT, DirectiveLocation.FIELD_DEFINITION, DirectiveLocation.ARGUMENT_DEFINITION, DirectiveLocation.INTERFACE, DirectiveLocation.UNION, DirectiveLocation.ENUM, DirectiveLocation.ENUM_VALUE, DirectiveLocation.INPUT_OBJECT,
def accepts_an_input_object_type_with_fields(): input_obj_type = GraphQLInputObjectType( 'SomeInputObject', {'f': GraphQLInputField(GraphQLString)}) assert input_obj_type.fields['f'].type is GraphQLString
return time + timedelta(days=days) def resolve_latest(root, _info, times): return max(times) def resolve_seconds(root, _info, interval): print(f"interval={interval!r}") return (interval["end"] - interval["start"]).total_seconds() IntervalInputType = GraphQLInputObjectType( "IntervalInput", fields={ "start": GraphQLInputField(DatetimeScalar), "end": GraphQLInputField(DatetimeScalar), }, ) queryType = GraphQLObjectType( name="RootQueryType", fields={ "shiftDays": GraphQLField( DatetimeScalar, args={ "time": GraphQLArgument(DatetimeScalar), "days": GraphQLArgument(GraphQLInt), }, resolve=resolve_shift_days,
from graphql.language.parser import parse from graphql.type import (GraphQLArgument, GraphQLField, GraphQLInputObjectField, GraphQLInputObjectType, GraphQLList, GraphQLNonNull, GraphQLObjectType, GraphQLScalarType, GraphQLSchema, GraphQLString) TestComplexScalar = GraphQLScalarType( name='ComplexScalar', serialize=lambda v: 'SerializedValue' if v == 'DeserializedValue' else None, parse_value=lambda v: 'DeserializedValue' if v == 'SerializedValue' else None, parse_literal=lambda v: 'DeserializedValue' if v.value == 'SerializedValue' else None ) TestInputObject = GraphQLInputObjectType('TestInputObject', { 'a': GraphQLInputObjectField(GraphQLString), 'b': GraphQLInputObjectField(GraphQLList(GraphQLString)), 'c': GraphQLInputObjectField(GraphQLNonNull(GraphQLString)), 'd': GraphQLInputObjectField(TestComplexScalar) }) stringify = lambda obj: json.dumps(obj, sort_keys=True) def input_to_json(obj, args, context, info): input = args.get('input') if input: return stringify(input) TestNestedInputObject = GraphQLInputObjectType( name='TestNestedInputObject', fields={
def accepts_an_input_object_type_with_a_field_function(): input_obj_type = GraphQLInputObjectType( "SomeInputObject", lambda: {"f": GraphQLInputField(GraphQLString)}) assert input_obj_type.fields["f"].type is GraphQLString
def describe_ast_from_value(): def converts_boolean_values_to_asts(): assert ast_from_value(True, GraphQLBoolean) == BooleanValueNode(value=True) assert ast_from_value(False, GraphQLBoolean) == BooleanValueNode(value=False) assert ast_from_value(Undefined, GraphQLBoolean) is None assert ast_from_value(None, GraphQLBoolean) == NullValueNode() assert ast_from_value(0, GraphQLBoolean) == BooleanValueNode(value=False) assert ast_from_value(1, GraphQLBoolean) == BooleanValueNode(value=True) non_null_boolean = GraphQLNonNull(GraphQLBoolean) assert ast_from_value( 0, non_null_boolean) == BooleanValueNode(value=False) def converts_int_values_to_int_asts(): assert ast_from_value(-1, GraphQLInt) == IntValueNode(value="-1") assert ast_from_value(123.0, GraphQLInt) == IntValueNode(value="123") assert ast_from_value(1e4, GraphQLInt) == IntValueNode(value="10000") # GraphQL spec does not allow coercing non-integer values to Int to # avoid accidental data loss. with raises(GraphQLError) as exc_info: assert ast_from_value(123.5, GraphQLInt) msg = str(exc_info.value) assert msg == "Int cannot represent non-integer value: 123.5" # Note: outside the bounds of 32bit signed int. with raises(GraphQLError) as exc_info: assert ast_from_value(1e40, GraphQLInt) msg = str(exc_info.value) assert msg == "Int cannot represent non 32-bit signed integer value: 1e+40" with raises(GraphQLError) as exc_info: ast_from_value(nan, GraphQLInt) msg = str(exc_info.value) assert msg == "Int cannot represent non-integer value: nan" def converts_float_values_to_float_asts(): # luckily in Python we can discern between float and int assert ast_from_value(-1, GraphQLFloat) == FloatValueNode(value="-1") assert ast_from_value(123.0, GraphQLFloat) == FloatValueNode(value="123") assert ast_from_value(123.5, GraphQLFloat) == FloatValueNode(value="123.5") assert ast_from_value(1e4, GraphQLFloat) == FloatValueNode(value="10000") assert ast_from_value(1e40, GraphQLFloat) == FloatValueNode(value="1e+40") def converts_string_values_to_string_asts(): assert ast_from_value("hello", GraphQLString) == StringValueNode(value="hello") assert ast_from_value("VALUE", GraphQLString) == StringValueNode(value="VALUE") assert ast_from_value( "VA\nLUE", GraphQLString) == StringValueNode(value="VA\nLUE") assert ast_from_value(123, GraphQLString) == StringValueNode(value="123") assert ast_from_value(False, GraphQLString) == StringValueNode(value="false") assert ast_from_value(None, GraphQLString) == NullValueNode() assert ast_from_value(Undefined, GraphQLString) is None def converts_id_values_to_int_or_string_asts(): assert ast_from_value("hello", GraphQLID) == StringValueNode(value="hello") assert ast_from_value("VALUE", GraphQLID) == StringValueNode(value="VALUE") # Note: EnumValues cannot contain non-identifier characters assert ast_from_value("VA\nLUE", GraphQLID) == StringValueNode(value="VA\nLUE") # Note: IntValues are used when possible. assert ast_from_value(-1, GraphQLID) == IntValueNode(value="-1") assert ast_from_value(123, GraphQLID) == IntValueNode(value="123") assert ast_from_value("123", GraphQLID) == IntValueNode(value="123") assert ast_from_value("01", GraphQLID) == StringValueNode(value="01") with raises(GraphQLError) as exc_info: assert ast_from_value(False, GraphQLID) assert str(exc_info.value) == "ID cannot represent value: False" assert ast_from_value(None, GraphQLID) == NullValueNode() assert ast_from_value(Undefined, GraphQLString) is None def converts_using_serialize_from_a_custom_scalar_type(): pass_through_scalar = GraphQLScalarType( "PassThroughScalar", serialize=lambda value: value, ) assert ast_from_value( "value", pass_through_scalar) == StringValueNode(value="value") with raises(TypeError) as exc_info: assert ast_from_value(nan, pass_through_scalar) assert str(exc_info.value) == "Cannot convert value to AST: nan." with raises(TypeError) as exc_info: ast_from_value(inf, pass_through_scalar) assert str(exc_info.value) == "Cannot convert value to AST: inf." return_null_scalar = GraphQLScalarType( "ReturnNullScalar", serialize=lambda value: None, ) assert ast_from_value("value", return_null_scalar) is None class SomeClass: pass return_custom_class_scalar = GraphQLScalarType( "ReturnCustomClassScalar", serialize=lambda value: SomeClass(), ) with raises(TypeError) as exc_info: ast_from_value("value", return_custom_class_scalar) msg = str(exc_info.value) assert msg == "Cannot convert value to AST: <SomeClass instance>." def does_not_convert_non_null_values_to_null_value(): non_null_boolean = GraphQLNonNull(GraphQLBoolean) assert ast_from_value(None, non_null_boolean) is None complex_value = {"someArbitrary": "complexValue"} my_enum = GraphQLEnumType("MyEnum", { "HELLO": None, "GOODBYE": None, "COMPLEX": complex_value }) def converts_string_values_to_enum_asts_if_possible(): assert ast_from_value("HELLO", my_enum) == EnumValueNode(value="HELLO") assert ast_from_value(complex_value, my_enum) == EnumValueNode(value="COMPLEX") # Note: case sensitive with raises(GraphQLError) as exc_info: ast_from_value("hello", my_enum) assert exc_info.value.message == "Enum 'MyEnum' cannot represent value: 'hello'" # Note: not a valid enum value with raises(GraphQLError) as exc_info: ast_from_value("UNKNOWN_VALUE", my_enum) assert (exc_info.value.message == "Enum 'MyEnum' cannot represent value: 'UNKNOWN_VALUE'") def converts_list_values_to_list_asts(): assert ast_from_value( ["FOO", "BAR"], GraphQLList(GraphQLString)) == ListValueNode(values=[ StringValueNode(value="FOO"), StringValueNode(value="BAR") ]) assert ast_from_value(["HELLO", "GOODBYE"], GraphQLList(my_enum)) == ListValueNode(values=[ EnumValueNode(value="HELLO"), EnumValueNode(value="GOODBYE") ]) def list_generator(): yield 1 yield 2 yield 3 assert ast_from_value( list_generator(), GraphQLList(GraphQLInt)) == (ListValueNode(values=[ IntValueNode(value="1"), IntValueNode(value="2"), IntValueNode(value="3"), ])) def converts_list_singletons(): assert ast_from_value( "FOO", GraphQLList(GraphQLString)) == StringValueNode(value="FOO") def skips_invalid_list_items(): ast = ast_from_value(["FOO", None, "BAR"], GraphQLList(GraphQLNonNull(GraphQLString))) assert ast == ListValueNode(values=[ StringValueNode(value="FOO"), StringValueNode(value="BAR") ]) input_obj = GraphQLInputObjectType( "MyInputObj", { "foo": GraphQLInputField(GraphQLFloat), "bar": GraphQLInputField(my_enum) }, ) def converts_input_objects(): assert ast_from_value({ "foo": 3, "bar": "HELLO" }, input_obj) == ObjectValueNode(fields=[ ObjectFieldNode(name=NameNode(value="foo"), value=FloatValueNode(value="3")), ObjectFieldNode(name=NameNode(value="bar"), value=EnumValueNode(value="HELLO")), ]) def converts_input_objects_with_explicit_nulls(): assert ast_from_value({ "foo": None }, input_obj) == ObjectValueNode(fields=[ ObjectFieldNode(name=NameNode(value="foo"), value=NullValueNode()) ]) def does_not_convert_non_object_values_as_input_objects(): assert ast_from_value(5, input_obj) is None
def describe_value_from_ast(): def _value_from(value_text, type_, variables=None): ast = parse_value(value_text) return value_from_ast(ast, type_, variables) def rejects_empty_input(): # noinspection PyTypeChecker assert value_from_ast(None, GraphQLBoolean) is Undefined def converts_according_to_input_coercion_rules(): assert _value_from("true", GraphQLBoolean) is True assert _value_from("false", GraphQLBoolean) is False assert _value_from("123", GraphQLInt) == 123 assert _value_from("123", GraphQLFloat) == 123 assert _value_from("123.456", GraphQLFloat) == 123.456 assert _value_from('"abc123"', GraphQLString) == "abc123" assert _value_from("123456", GraphQLID) == "123456" assert _value_from('"123456"', GraphQLID) == "123456" def does_not_convert_when_input_coercion_rules_reject_a_value(): assert _value_from("123", GraphQLBoolean) is Undefined assert _value_from("123.456", GraphQLInt) is Undefined assert _value_from("true", GraphQLInt) is Undefined assert _value_from('"123"', GraphQLInt) is Undefined assert _value_from('"123"', GraphQLFloat) is Undefined assert _value_from("123", GraphQLString) is Undefined assert _value_from("true", GraphQLString) is Undefined assert _value_from("123.456", GraphQLID) is Undefined def convert_using_parse_literal_from_a_custom_scalar_type(): def pass_through_parse_literal(node, _vars=None): assert node.kind == "string_value" return node.value pass_through_scalar = GraphQLScalarType( "PassThroughScalar", parse_literal=pass_through_parse_literal, parse_value=lambda value: value, # pragma: no cover ) assert _value_from('"value"', pass_through_scalar) == "value" def throw_parse_literal(_node, _vars=None): raise RuntimeError("Test") throw_scalar = GraphQLScalarType( "ThrowScalar", parse_literal=throw_parse_literal, parse_value=lambda value: value, # pragma: no cover ) assert _value_from("value", throw_scalar) is Undefined return_undefined_scalar = GraphQLScalarType( "ReturnUndefinedScalar", parse_literal=lambda _node, _vars=None: Undefined, parse_value=lambda value: value, # pragma: no cover ) assert _value_from("value", return_undefined_scalar) is Undefined def converts_enum_values_according_to_input_coercion_rules(): test_enum = GraphQLEnumType( "TestColor", { "RED": 1, "GREEN": 2, "BLUE": 3, "NULL": None, "NAN": nan, "NO_CUSTOM_VALUE": Undefined, }, ) assert _value_from("RED", test_enum) == 1 assert _value_from("BLUE", test_enum) == 3 assert _value_from("YELLOW", test_enum) is Undefined assert _value_from("3", test_enum) is Undefined assert _value_from('"BLUE"', test_enum) is Undefined assert _value_from("null", test_enum) is None assert _value_from("NULL", test_enum) is None assert _value_from("NULL", GraphQLNonNull(test_enum)) is None assert isnan(_value_from("NAN", test_enum)) assert _value_from("NO_CUSTOM_VALUE", test_enum) is Undefined # Boolean! non_null_bool = GraphQLNonNull(GraphQLBoolean) # [Boolean] list_of_bool = GraphQLList(GraphQLBoolean) # [Boolean!] list_of_non_null_bool = GraphQLList(non_null_bool) # [Boolean]! non_null_list_of_bool = GraphQLNonNull(list_of_bool) # [Boolean!]! non_null_list_of_non_mull_bool = GraphQLNonNull(list_of_non_null_bool) def coerces_to_null_unless_non_null(): assert _value_from("null", GraphQLBoolean) is None assert _value_from("null", non_null_bool) is Undefined def coerces_lists_of_values(): assert _value_from("true", list_of_bool) == [True] assert _value_from("123", list_of_bool) is Undefined assert _value_from("null", list_of_bool) is None assert _value_from("[true, false]", list_of_bool) == [True, False] assert _value_from("[true, 123]", list_of_bool) is Undefined assert _value_from("[true, null]", list_of_bool) == [True, None] assert _value_from("{ true: true }", list_of_bool) is Undefined def coerces_non_null_lists_of_values(): assert _value_from("true", non_null_list_of_bool) == [True] assert _value_from("123", non_null_list_of_bool) is Undefined assert _value_from("null", non_null_list_of_bool) is Undefined assert _value_from("[true, false]", non_null_list_of_bool) == [True, False] assert _value_from("[true, 123]", non_null_list_of_bool) is Undefined assert _value_from("[true, null]", non_null_list_of_bool) == [True, None] def coerces_lists_of_non_null_values(): assert _value_from("true", list_of_non_null_bool) == [True] assert _value_from("123", list_of_non_null_bool) is Undefined assert _value_from("null", list_of_non_null_bool) is None assert _value_from("[true, false]", list_of_non_null_bool) == [True, False] assert _value_from("[true, 123]", list_of_non_null_bool) is Undefined assert _value_from("[true, null]", list_of_non_null_bool) is Undefined def coerces_non_null_lists_of_non_null_values(): assert _value_from("true", non_null_list_of_non_mull_bool) == [True] assert _value_from("123", non_null_list_of_non_mull_bool) is Undefined assert _value_from("null", non_null_list_of_non_mull_bool) is Undefined assert _value_from("[true, false]", non_null_list_of_non_mull_bool) == [ True, False, ] assert _value_from("[true, 123]", non_null_list_of_non_mull_bool) is Undefined assert _value_from("[true, null]", non_null_list_of_non_mull_bool) is Undefined test_input_obj = GraphQLInputObjectType( "TestInput", { "int": GraphQLInputField(GraphQLInt, default_value=42), "bool": GraphQLInputField(GraphQLBoolean), "requiredBool": GraphQLInputField(non_null_bool), }, ) def coerces_input_objects_according_to_input_coercion_rules(): assert _value_from("null", test_input_obj) is None assert _value_from("[]", test_input_obj) is Undefined assert _value_from("123", test_input_obj) is Undefined assert _value_from("{ int: 123, requiredBool: false }", test_input_obj) == { "int": 123, "requiredBool": False, } assert _value_from("{ bool: true, requiredBool: false }", test_input_obj) == { "int": 42, "bool": True, "requiredBool": False, } assert (_value_from("{ int: true, requiredBool: true }", test_input_obj) is Undefined) assert _value_from("{ requiredBool: null }", test_input_obj) is Undefined assert _value_from("{ bool: true }", test_input_obj) is Undefined def accepts_variable_values_assuming_already_coerced(): assert _value_from("$var", GraphQLBoolean, {}) is Undefined assert _value_from("$var", GraphQLBoolean, {"var": True}) is True assert _value_from("$var", GraphQLBoolean, {"var": None}) is None assert _value_from("$var", non_null_bool, {"var": None}) is Undefined def asserts_variables_are_provided_as_items_in_lists(): assert _value_from("[ $foo ]", list_of_bool, {}) == [None] assert _value_from("[ $foo ]", list_of_non_null_bool, {}) is Undefined assert _value_from("[ $foo ]", list_of_non_null_bool, {"foo": True}) == [True] # Note: variables are expected to have already been coerced, so we # do not expect the singleton wrapping behavior for variables. assert _value_from("$foo", list_of_non_null_bool, {"foo": True}) is True assert _value_from("$foo", list_of_non_null_bool, {"foo": [True]}) == [True] def omits_input_object_fields_for_unprovided_variables(): assert _value_from("{ int: $foo, bool: $foo, requiredBool: true }", test_input_obj, {}) == { "int": 42, "requiredBool": True } assert _value_from("{ requiredBool: $foo }", test_input_obj, {}) is Undefined assert _value_from("{ requiredBool: $foo }", test_input_obj, {"foo": True}) == { "int": 42, "requiredBool": True, } def transforms_names_using_out_name(): # This is an extension of GraphQL.js. complex_input_obj = GraphQLInputObjectType( "Complex", { "realPart": GraphQLInputField(GraphQLFloat, out_name="real_part"), "imagPart": GraphQLInputField( GraphQLFloat, default_value=0, out_name="imag_part"), }, ) assert _value_from("{ realPart: 1 }", complex_input_obj) == { "real_part": 1, "imag_part": 0, } def transforms_values_with_out_type(): # This is an extension of GraphQL.js. complex_input_obj = GraphQLInputObjectType( "Complex", { "real": GraphQLInputField(GraphQLFloat), "imag": GraphQLInputField(GraphQLFloat), }, out_type=lambda value: complex(value["real"], value["imag"]), ) assert _value_from("{ real: 1, imag: 2 }", complex_input_obj) == 1 + 2j
def describe_for_graphql_input_object(): TestInputObject = GraphQLInputObjectType( "TestInputObject", { "foo": GraphQLInputField(GraphQLNonNull(GraphQLInt)), "bar": GraphQLInputField(GraphQLInt), }, ) def returns_no_error_for_a_valid_input(): result = _coerce_value({"foo": 123}, TestInputObject) assert expect_value(result) == {"foo": 123} def returns_an_error_for_a_non_dict_value(): result = _coerce_value(123, TestInputObject) assert expect_errors(result) == [ ("Expected type 'TestInputObject' to be a dict.", [], 123) ] def returns_an_error_for_an_invalid_field(): result = _coerce_value({"foo": nan}, TestInputObject) assert expect_errors(result) == [( "Int cannot represent non-integer value: nan", ["foo"], nan, )] def returns_multiple_errors_for_multiple_invalid_fields(): result = _coerce_value({ "foo": "abc", "bar": "def" }, TestInputObject) assert expect_errors(result) == [ ( "Int cannot represent non-integer value: 'abc'", ["foo"], "abc", ), ( "Int cannot represent non-integer value: 'def'", ["bar"], "def", ), ] def returns_error_for_a_missing_required_field(): result = _coerce_value({"bar": 123}, TestInputObject) assert expect_errors(result) == [( "Field 'foo' of required type 'Int!' was not provided.", [], { "bar": 123 }, )] def returns_error_for_an_unknown_field(): result = _coerce_value({ "foo": 123, "unknownField": 123 }, TestInputObject) assert expect_errors(result) == [( "Field 'unknownField' is not defined by type 'TestInputObject'.", [], { "foo": 123, "unknownField": 123 }, )] def returns_error_for_a_misspelled_field(): result = _coerce_value({"foo": 123, "bart": 123}, TestInputObject) assert expect_errors(result) == [( "Field 'bart' is not defined by type 'TestInputObject'." " Did you mean 'bar'?", [], { "foo": 123, "bart": 123 }, )] def transforms_names_using_out_name(): # This is an extension of GraphQL.js. ComplexInputObject = GraphQLInputObjectType( "Complex", { "realPart": GraphQLInputField(GraphQLFloat, out_name="real_part"), "imagPart": GraphQLInputField( GraphQLFloat, default_value=0, out_name="imag_part"), }, ) result = _coerce_value({"realPart": 1}, ComplexInputObject) assert expect_value(result) == {"real_part": 1, "imag_part": 0} def transforms_values_with_out_type(): # This is an extension of GraphQL.js. ComplexInputObject = GraphQLInputObjectType( "Complex", { "real": GraphQLInputField(GraphQLFloat), "imag": GraphQLInputField(GraphQLFloat), }, out_type=lambda value: complex(value["real"], value["imag"]), ) result = _coerce_value({"real": 1, "imag": 2}, ComplexInputObject) assert expect_value(result) == 1 + 2j
parse_literal=lambda v: "DeserializedValue" if v.value == "SerializedValue" else None, ) class my_special_dict(dict): pass TestInputObject = GraphQLInputObjectType( "TestInputObject", OrderedDict( [ ("a", GraphQLInputObjectField(GraphQLString)), ("b", GraphQLInputObjectField(GraphQLList(GraphQLString))), ("c", GraphQLInputObjectField(GraphQLNonNull(GraphQLString))), ("d", GraphQLInputObjectField(TestComplexScalar)), ] ), ) TestCustomInputObject = GraphQLInputObjectType( "TestCustomInputObject", OrderedDict([("a", GraphQLInputObjectField(GraphQLString))]), container_type=my_special_dict, ) def stringify(obj):
'BROWN': GraphQLEnumValue(0), 'BLACK': GraphQLEnumValue(1), 'TAN': GraphQLEnumValue(2), 'SPOTTED': GraphQLEnumValue(3), 'NO_FUR': GraphQLEnumValue(), 'UNKNOWN': None }) ComplexInput = GraphQLInputObjectType( 'ComplexInput', { 'requiredField': GraphQLInputField(GraphQLNonNull(GraphQLBoolean)), 'nonNullField': GraphQLInputField(GraphQLNonNull(GraphQLBoolean), default_value=False), 'intField': GraphQLInputField(GraphQLInt), 'stringField': GraphQLInputField(GraphQLString), 'booleanField': GraphQLInputField(GraphQLBoolean), 'stringListField': GraphQLInputField(GraphQLList(GraphQLString)) }) ComplicatedArgs = GraphQLObjectType( 'ComplicatedArgs', { 'intArgField': GraphQLField(GraphQLString, {'intArg': GraphQLArgument(GraphQLInt)}), 'nonNullIntArgField': GraphQLField( GraphQLString,
{"writeArticle": GraphQLField(BlogArticle)}) BlogSubscription = GraphQLObjectType( "Subscription", { "articleSubscribe": GraphQLField(args={"id": GraphQLArgument(GraphQLString)}, type_=BlogArticle) }, ) ObjectType = GraphQLObjectType("Object", {}) InterfaceType = GraphQLInterfaceType("Interface") UnionType = GraphQLUnionType("Union", [ObjectType], resolve_type=lambda: None) EnumType = GraphQLEnumType("Enum", {"foo": GraphQLEnumValue()}) InputObjectType = GraphQLInputObjectType("InputObject", {}) ScalarType = GraphQLScalarType( "Scalar", serialize=lambda: None, parse_value=lambda: None, parse_literal=lambda: None, ) def schema_with_field_type(type_: GraphQLOutputType) -> GraphQLSchema: return GraphQLSchema(query=GraphQLObjectType( "Query", {"field": GraphQLField(type_)}), types=[type_]) def describe_type_system_example():
from pytest import raises from graphql.language import DirectiveLocation from graphql.type import (GraphQLField, GraphQLInterfaceType, GraphQLObjectType, GraphQLSchema, GraphQLString, GraphQLInputObjectType, GraphQLInputField, GraphQLDirective, GraphQLArgument, GraphQLList) InterfaceType = GraphQLInterfaceType( 'Interface', {'fieldName': GraphQLField(GraphQLString)}) DirectiveInputType = GraphQLInputObjectType( 'DirInput', {'field': GraphQLInputField(GraphQLString)}) WrappedDirectiveInputType = GraphQLInputObjectType( 'WrappedDirInput', {'field': GraphQLInputField(GraphQLString)}) Directive = GraphQLDirective(name='dir', locations=[DirectiveLocation.OBJECT], args={ 'arg': GraphQLArgument(DirectiveInputType), 'argList': GraphQLArgument( GraphQLList(WrappedDirectiveInputType)) }) Schema = GraphQLSchema(query=GraphQLObjectType( 'Query', {'getObject': GraphQLField(InterfaceType, resolve=lambda: {})}), directives=[Directive])