def is_type_of_used_to_resolve_runtime_type_for_union(): DogType = GraphQLObjectType( "Dog", { "name": GraphQLField(GraphQLString), "woofs": GraphQLField(GraphQLBoolean), }, is_type_of=get_is_type_of(Dog), ) CatType = GraphQLObjectType( "Cat", { "name": GraphQLField(GraphQLString), "meows": GraphQLField(GraphQLBoolean), }, is_type_of=get_is_type_of(Cat), ) PetType = GraphQLUnionType("Pet", [CatType, DogType]) schema = GraphQLSchema( GraphQLObjectType( "Query", { "pets": GraphQLField( GraphQLList(PetType), resolve=lambda *_args: [ Dog("Odie", True), Cat("Garfield", False), ], ) }, )) query = """ { pets { ... on Dog { name woofs } ... on Cat { name meows } } } """ result = graphql_sync(schema, query) assert result == ( { "pets": [ { "name": "Odie", "woofs": True }, { "name": "Garfield", "meows": False }, ] }, None, )
def define_sample_schema(): BlogImage = GraphQLObjectType( "Image", { "url": GraphQLField(GraphQLString), "width": GraphQLField(GraphQLInt), "height": GraphQLField(GraphQLInt), }, ) BlogArticle: GraphQLObjectType BlogAuthor = GraphQLObjectType( "Author", lambda: { "id": GraphQLField(GraphQLString), "name": GraphQLField(GraphQLString), "pic": GraphQLField( BlogImage, args={ "width": GraphQLArgument(GraphQLInt), "height": GraphQLArgument(GraphQLInt), }, ), "recentArticle": GraphQLField(BlogArticle), }, ) BlogArticle = GraphQLObjectType( "Article", lambda: { "id": GraphQLField(GraphQLString), "isPublished": GraphQLField(GraphQLBoolean), "author": GraphQLField(BlogAuthor), "title": GraphQLField(GraphQLString), "body": GraphQLField(GraphQLString), }, ) BlogQuery = GraphQLObjectType( "Query", { "article": GraphQLField(BlogArticle, args={"id": GraphQLArgument(GraphQLString)}), "feed": GraphQLField(GraphQLList(BlogArticle)), }, ) BlogMutation = GraphQLObjectType( "Mutation", {"writeArticle": GraphQLField(BlogArticle)}) BlogSubscription = GraphQLObjectType( "Subscription", { "articleSubscribe": GraphQLField(args={"id": GraphQLArgument(GraphQLString)}, type_=BlogArticle) }, ) schema = GraphQLSchema( BlogQuery, BlogMutation, BlogSubscription, description="Sample schema", ) kwargs = schema.to_kwargs() types = kwargs.pop("types") assert types == list(schema.type_map.values()) assert kwargs == { "query": BlogQuery, "mutation": BlogMutation, "subscription": BlogSubscription, "directives": specified_directives, "description": "Sample schema", "extensions": None, "ast_node": None, "extension_ast_nodes": [], "assume_valid": False, } assert print_schema(schema) == dedent(''' """Sample schema""" schema { query: Query mutation: Mutation subscription: Subscription } type Query { article(id: String): Article feed: [Article] } type Article { id: String isPublished: Boolean author: Author title: String body: String } type Author { id: String name: String pic(width: Int, height: Int): Image recentArticle: Article } type Image { url: String width: Int height: Int } type Mutation { writeArticle: Article } type Subscription { articleSubscribe(id: String): Article } ''')
) InboxType = GraphQLObjectType( "Inbox", { "total": GraphQLField(GraphQLInt, resolve=lambda inbox, _info: len(inbox["emails"])), "unread": GraphQLField( GraphQLInt, resolve=lambda inbox, _info: sum(1 for email in inbox["emails"] if email["unread"]), ), "emails": GraphQLField(GraphQLList(EmailType)), }, ) QueryType = GraphQLObjectType("Query", {"inbox": GraphQLField(InboxType)}) EmailEventType = GraphQLObjectType("EmailEvent", { "email": GraphQLField(EmailType), "inbox": GraphQLField(InboxType) }) async def anext(iterable): """Return the next item from an async iterator.""" return await iterable.__anext__()
CatOrDog = GraphQLUnionType('CatOrDog', [Dog, Cat]) Intelligent = GraphQLInterfaceType('Intelligent', { 'iq': GraphQLField(GraphQLInt), }) Human = GraphQLObjectType( name='Human', interfaces=[Being, Intelligent], is_type_of=lambda: None, fields={ 'name': GraphQLField(GraphQLString, { 'surname': GraphQLArgument(GraphQLBoolean), }), 'pets': GraphQLField(GraphQLList(Pet)), 'iq': GraphQLField(GraphQLInt), }, ) Alien = GraphQLObjectType( name='Alien', is_type_of=lambda *args: True, interfaces=[Being, Intelligent], fields={ 'iq': GraphQLField(GraphQLInt), 'name': GraphQLField(GraphQLString, { 'surname': GraphQLArgument(GraphQLBoolean), }), 'numEyes': GraphQLField(GraphQLInt), },
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 }, ) 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)
def converts_list_singletons(): assert ast_from_value( "FOO", GraphQLList(GraphQLString)) == StringValueNode(value="FOO")
'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]) def describe_type_system_schema(): def describe_type_map(): def includes_input_types_only_used_in_directives(): assert 'DirInput' in Schema.type_map assert 'WrappedDirInput' in Schema.type_map def describe_validity(): def describe_when_not_assumed_valid():
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, ) 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, ) 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, ) 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