def __new__(mcs, name, bases, attrs): if attrs.pop('abstract', False): return super(ObjectTypeMeta, mcs).__new__(mcs, name, bases, attrs) class_ref = WeakRefHolder() registry = mcs._get_registry() declared_fields = get_declared_fields(name, yank_potential_fields(attrs)) with no_implementation_registration(): object_type = GraphQLObjectType( name, fields=partial(mcs._build_field_map, class_ref, declared_fields), description=attrs.get('__doc__'), interfaces=mcs._get_interfaces() ) object_type.is_type_of = registry._create_is_type_of(object_type) cls = super(ObjectTypeMeta, mcs).__new__(mcs, name, bases, attrs) mcs._register(object_type, cls) cls._registry = registry cls.T = object_type class_ref.set(cls) return cls
def test_does_not_mutate_passed_field_definitions(): fields = { 'field1': GraphQLField(GraphQLString), 'field2': GraphQLField(GraphQLString, args={'id': GraphQLArgument(GraphQLString)}), } TestObject1 = GraphQLObjectType(name='Test1', fields=fields) TestObject2 = GraphQLObjectType(name='Test1', fields=fields) assert TestObject1.get_fields() == TestObject2.get_fields() assert fields == { 'field1': GraphQLField(GraphQLString), 'field2': GraphQLField(GraphQLString, args={'id': GraphQLArgument(GraphQLString)}), } input_fields = { 'field1': GraphQLInputObjectField(GraphQLString), 'field2': GraphQLInputObjectField(GraphQLString), } TestInputObject1 = GraphQLInputObjectType(name='Test1', fields=input_fields) TestInputObject2 = GraphQLInputObjectType(name='Test2', fields=input_fields) assert TestInputObject1.get_fields() == TestInputObject2.get_fields() assert input_fields == { 'field1': GraphQLInputObjectField(GraphQLString), 'field2': GraphQLInputObjectField(GraphQLString), }
def test_does_not_sort_fields_and_argument_keys_when_using_ordered_dict(): fields = OrderedDict([ ('b', GraphQLField(GraphQLString)), ('c', GraphQLField(GraphQLString)), ('a', GraphQLField(GraphQLString)), ('d', GraphQLField(GraphQLString, args=OrderedDict([ ('q', GraphQLArgument(GraphQLString)), ('x', GraphQLArgument(GraphQLString)), ('v', GraphQLArgument(GraphQLString)), ('a', GraphQLArgument(GraphQLString)), ('n', GraphQLArgument(GraphQLString)) ]))) ]) test_object = GraphQLObjectType(name='Test', fields=fields) ordered_fields = test_object.get_fields() assert list(ordered_fields.keys()) == ['b', 'c', 'a', 'd'] field_with_args = test_object.get_fields().get('d') assert [a.name for a in field_with_args.args] == ['q', 'x', 'v', 'a', 'n']
def test_sorts_fields_and_argument_keys_if_not_using_ordered_dict(): fields = { 'b': GraphQLField(GraphQLString), 'c': GraphQLField(GraphQLString), 'a': GraphQLField(GraphQLString), 'd': GraphQLField(GraphQLString, args={ 'q': GraphQLArgument(GraphQLString), 'x': GraphQLArgument(GraphQLString), 'v': GraphQLArgument(GraphQLString), 'a': GraphQLArgument(GraphQLString), 'n': GraphQLArgument(GraphQLString) }) } test_object = GraphQLObjectType(name='Test', fields=fields) ordered_fields = test_object.get_fields() assert list(ordered_fields.keys()) == ['a', 'b', 'c', 'd'] field_with_args = test_object.get_fields().get('d') assert [a.name for a in field_with_args.args] == ['a', 'n', 'q', 'v', 'x']
def test_raises_the_inline_operation_if_no_operation_is_provided(): doc = 'query Example { a } query OtherExample { a }' class Data(object): a = 'b' ast = parse(doc) Type = GraphQLObjectType('Type', { 'a': GraphQLField(GraphQLString) }) with raises(GraphQLError) as excinfo: execute(GraphQLSchema(Type), Data(), ast) assert 'Must provide operation name if query contains multiple operations' in str(excinfo.value)
def test_uses_the_only_operation_if_no_operation_is_provided(): doc = 'query Example { a }' class Data(object): a = 'b' ast = parse(doc) Type = GraphQLObjectType('Type', { 'a': GraphQLField(GraphQLString) }) result = execute(GraphQLSchema(Type), Data(), ast) assert not result.errors assert result.data == {'a': 'b'}
def test_exposes_descriptions_on_types_and_fields(): QueryRoot = GraphQLObjectType('QueryRoot', {}) schema = GraphQLSchema(QueryRoot) request = '''{ schemaType: __type(name: "__Schema") { name, description, fields { name, description } } } ''' result = graphql(schema, request) assert not result.errors assert sort_lists(result.data) == sort_lists({ 'schemaType': { 'name': '__Schema', 'description': 'A GraphQL Schema defines the capabilities of a ' + 'GraphQL server. It exposes all available types and ' + 'directives on the server, as well as the entry ' + 'points for query and mutation operations.', 'fields': [{ 'name': 'types', 'description': 'A list of all types supported by this server.' }, { 'name': 'queryType', 'description': 'The type that query operations will be rooted at.' }, { 'name': 'mutationType', 'description': 'If this server supports mutation, the type that ' + 'mutation operations will be rooted at.' }, { 'name': 'directives', 'description': 'A list of all directives supported by this server.' }] } })
def test_builds_a_schema_with_complex_field_values(): schema = GraphQLSchema(query=GraphQLObjectType( name='ComplexFields', fields=OrderedDict( [('string', GraphQLField(GraphQLString) ), ('listOfString', GraphQLField(GraphQLList(GraphQLString))), ('nonNullString', GraphQLField(GraphQLNonNull(GraphQLString))), ('nonNullListOfString', GraphQLField(GraphQLNonNull(GraphQLList(GraphQLString)))), ('nonNullListOfNonNullString', GraphQLField( GraphQLNonNull(GraphQLList(GraphQLNonNull(GraphQLString)))) )]))) _test_schema(schema)
def test_builds_a_schema_with_a_circular_type_reference(): DogType = GraphQLObjectType( name='Dog', fields=lambda: { 'bestFriend': GraphQLField(HumanType) } ) HumanType = GraphQLObjectType( name='Human', fields=lambda: { 'bestFriend': GraphQLField(DogType) } ) schema = GraphQLSchema(query=GraphQLObjectType( name='Circular', fields=OrderedDict([ ('dog', GraphQLField(DogType)), ('human', GraphQLField(HumanType)), ]) )) _test_schema(schema)
def test_print_enum(): RGBType = GraphQLEnumType(name='RGB', values=OrderedDict([ ('RED', GraphQLEnumValue(0)), ('GREEN', GraphQLEnumValue(1)), ('BLUE', GraphQLEnumValue(2)) ])) Root = GraphQLObjectType(name='Root', fields={'rgb': GraphQLField(RGBType)}) Schema = GraphQLSchema(Root) output = print_for_test(Schema) assert output == '''
def test_prints_multiple_interfaces(): FooType = GraphQLInterfaceType( name='Foo', resolve_type=lambda *_: None, fields={ 'str': GraphQLField(GraphQLString) } ) BaazType = GraphQLInterfaceType( name='Baaz', resolve_type=lambda *_: None, fields={ 'int': GraphQLField(GraphQLInt) } ) BarType = GraphQLObjectType( name='Bar', fields=OrderedDict([ ('str', GraphQLField(GraphQLString)), ('int', GraphQLField(GraphQLInt)) ]), interfaces=[FooType, BaazType] ) Root = GraphQLObjectType( name='Root', fields={ 'bar': GraphQLField(BarType) } ) Schema = GraphQLSchema(Root) output = print_for_test(Schema) assert output == '''
def test_fails_as_expected_on_the_type_root_field_without_an_arg(): TestType = GraphQLObjectType('TestType', { 'testField': GraphQLField(GraphQLString) }) schema = GraphQLSchema(TestType) request = ''' { __type { name } }''' result = graphql(schema, request) expected_error = {'message': ProvidedNonNullArguments.missing_field_arg_message('__type', 'name', 'String!'), 'locations': [dict(line=3, column=9)]} assert (expected_error in [format_error(error) for error in result.errors])
def test_fails_to_execute_a_query_containing_a_type_definition(): query = parse(''' { foo } type Query { foo: String } ''') schema = GraphQLSchema( GraphQLObjectType(name='Query', fields={'foo': GraphQLField(GraphQLString)})) with raises(GraphQLError) as excinfo: result = execute(schema, None, query) assert excinfo.value.message == 'GraphQL cannot execute a request containing a ObjectTypeDefinition.'
def test_prohibits_putting_non_object_types_in_unions(): bad_union_types = [ GraphQLInt, GraphQLNonNull(GraphQLInt), GraphQLList(GraphQLInt), InterfaceType, UnionType, EnumType, InputObjectType ] for x in bad_union_types: with raises(Exception) as excinfo: GraphQLSchema(GraphQLObjectType('Root', fields={'union': GraphQLField(GraphQLUnionType('BadUnion', [x]))})) assert 'BadUnion may only contain Object types, it cannot contain: ' + str(x) + '.' \ == str(excinfo.value)
def test_prints_input_type(): InputType = GraphQLInputObjectType( name='InputType', fields={'int': GraphQLInputObjectField(GraphQLInt)}) Root = GraphQLObjectType( name='Root', fields={ 'str': GraphQLField(GraphQLString, args={'argOne': GraphQLArgument(InputType)}) }) Schema = GraphQLSchema(Root) output = print_for_test(Schema) assert output == '''
def test_prints_custom_scalar(): OddType = GraphQLScalarType( name='Odd', serialize=lambda v: v if v % 2 == 1 else None ) Root = GraphQLObjectType( name='Root', fields={ 'odd': GraphQLField(OddType) } ) Schema = GraphQLSchema(Root) output = print_for_test(Schema) assert output == '''
def test_fails_on_a_deep_non_null(): schema = GraphQLSchema(query=GraphQLObjectType( name='Query', fields={ 'foo': GraphQLField( GraphQLList( GraphQLList(GraphQLList(GraphQLNonNull(GraphQLString))))) })) introspection = graphql(schema, introspection_query) with raises(Exception) as excinfo: build_client_schema(introspection.data) assert str( excinfo.value) == 'Decorated type deeper than introspection query.'
def test_builds_a_schema_with_field_arguments_with_default_values(): GeoType = GraphQLInputObjectType( name='Geo', fields=OrderedDict([ ('lat', GraphQLInputObjectField(GraphQLFloat)), ('lon', GraphQLInputObjectField(GraphQLFloat)), ]) ) schema = GraphQLSchema( query=GraphQLObjectType( name='ArgFields', fields=OrderedDict([ ('defaultInt', GraphQLField( GraphQLString, args={ 'intArg': GraphQLArgument( GraphQLInt, default_value=10 ) } )), ('defaultList', GraphQLField( GraphQLString, args={ 'listArg': GraphQLArgument( GraphQLList(GraphQLInt), default_value=[1, 2, 3] ) } )), ('defaultObject', GraphQLField( GraphQLString, args={ 'objArg': GraphQLArgument( GeoType, default_value={'lat': 37.485, 'lon': -122.148} ) } )) ]) ) ) _test_schema(schema)
def test_builds_a_schema_with_custom_directives(): schema = GraphQLSchema(query=GraphQLObjectType( name='Simple', description='This is a simple type', fields={ 'string': GraphQLField(type=GraphQLString, description='This is a string field') }, ), directives=[ GraphQLDirective( name='customDirective', description='This is a custom directive', on_field=True) ]) _test_schema(schema)
def test_identifies_deprecated_enum_values(): TestEnum = GraphQLEnumType( 'TestEnum', { 'NONDEPRECATED': 0, 'DEPRECATED': GraphQLEnumValue( 1, deprecation_reason='Removed in 1.0'), 'ALSONONDEPRECATED': 2 }) TestType = GraphQLObjectType('TestType', {'testEnum': GraphQLField(TestEnum)}) schema = GraphQLSchema(TestType) request = '''{__type(name: "TestEnum") { name enumValues(includeDeprecated: true) { name isDeprecated deprecationReason } } }''' result = graphql(schema, request) assert not result.errors assert sort_lists(result.data) == sort_lists({ '__type': { 'name': 'TestEnum', 'enumValues': [ { 'name': 'NONDEPRECATED', 'isDeprecated': False, 'deprecationReason': None }, { 'name': 'DEPRECATED', 'isDeprecated': True, 'deprecationReason': 'Removed in 1.0' }, { 'name': 'ALSONONDEPRECATED', 'isDeprecated': False, 'deprecationReason': None }, ] } })
def test_builds_a_schema_with_an_enum(): FoodEnum = GraphQLEnumType( name='Food', description='Varieties of food stuffs', values=OrderedDict([ ('VEGETABLES', GraphQLEnumValue(1, description='Foods that are vegetables.')), ('FRUITS', GraphQLEnumValue(2, description='Foods that are fruits.')), ('OILS', GraphQLEnumValue(3, description='Foods that are oils.')), ('DAIRY', GraphQLEnumValue(4, description='Foods that are dairy.')), ('MEAT', GraphQLEnumValue(5, description='Foods that are meat.')), ]) ) schema = GraphQLSchema( query=GraphQLObjectType( name='EnumFields', fields={ 'food': GraphQLField( FoodEnum, description='Repeats the arg you give it', args={ 'kind': GraphQLArgument( FoodEnum, description='what kind of food?' ) } ) } ) ) client_schema = _test_schema(schema) clientFoodEnum = client_schema.get_type('Food') assert isinstance(clientFoodEnum, GraphQLEnumType) assert clientFoodEnum.get_values() == [ GraphQLEnumValue(name='VEGETABLES', value='VEGETABLES', description='Foods that are vegetables.', deprecation_reason=None), GraphQLEnumValue(name='FRUITS', value='FRUITS', description='Foods that are fruits.', deprecation_reason=None), GraphQLEnumValue(name='OILS', value='OILS', description='Foods that are oils.', deprecation_reason=None), GraphQLEnumValue(name='DAIRY', value='DAIRY', description='Foods that are dairy.', deprecation_reason=None), GraphQLEnumValue(name='MEAT', value='MEAT', description='Foods that are meat.', deprecation_reason=None) ]
def test_respects_the_includedeprecated_parameter_for_enum_values(): TestEnum = GraphQLEnumType( 'TestEnum', { 'NONDEPRECATED': 0, 'DEPRECATED': GraphQLEnumValue( 1, deprecation_reason='Removed in 1.0'), 'ALSONONDEPRECATED': 2 }) TestType = GraphQLObjectType('TestType', {'testEnum': GraphQLField(TestEnum)}) schema = GraphQLSchema(TestType) request = '''{__type(name: "TestEnum") { name trueValues: enumValues(includeDeprecated: true) { name } falseValues: enumValues(includeDeprecated: false) { name } omittedValues: enumValues { name } } }''' result = graphql(schema, request) assert not result.errors assert sort_lists(result.data) == sort_lists({ '__type': { 'name': 'TestEnum', 'trueValues': [{ 'name': 'NONDEPRECATED' }, { 'name': 'DEPRECATED' }, { 'name': 'ALSONONDEPRECATED' }], 'falseValues': [{ 'name': 'NONDEPRECATED' }, { 'name': 'ALSONONDEPRECATED' }], 'omittedValues': [{ 'name': 'NONDEPRECATED' }, { 'name': 'ALSONONDEPRECATED' }], } })
def __init__(self, query_to_sqlalchemy_class): self._query_to_sqlalchemy_class = query_to_sqlalchemy_class available_attribute_parsers = [ '_parse_foreign_key', '_parse_integer', '_parse_string' ] def parse_attribute(query, attribute): for parser in available_attribute_parsers: getattr(self, parser)(query, attribute) for (query, sqlalchemy_class) in query_to_sqlalchemy_class.iteritems(): self._graphql_objects[query] = GraphQLObjectType( query, description='TODO: graphql should be introspective!', fields={}) for (query, sqlalchemy_class) in query_to_sqlalchemy_class.iteritems(): for column in inspect(sqlalchemy_class).columns: parse_attribute(query, column)
def test_respects_the_includedeprecated_parameter_for_fields(): TestType = GraphQLObjectType('TestType', OrderedDict([ ('nonDeprecated', GraphQLField(GraphQLString)), ('deprecated', GraphQLField(GraphQLString, deprecation_reason='Removed in 1.0')) ])) schema = GraphQLSchema(TestType) request = '''{__type(name: "TestType") { name trueFields: fields(includeDeprecated: true) { name } falseFields: fields(includeDeprecated: false) { name } omittedFields: fields { name } } }''' result = graphql(schema, request) assert not result.errors assert result.data == {'__type': { 'name': 'TestType', 'trueFields': [{'name': 'nonDeprecated'}, {'name': 'deprecated'}], 'falseFields': [{'name': 'nonDeprecated'}], 'omittedFields': [{'name': 'nonDeprecated'}], }}
def test_synchronous_executor_will_synchronously_resolve(): class Data(object): def promise(self): return 'I should work' DataType = GraphQLObjectType('DataType', { 'promise': GraphQLField(GraphQLString), }) doc = ''' query Example { promise } ''' schema = GraphQLSchema(query=DataType) executor = Executor([SynchronousExecutionMiddleware()]) result = executor.execute(schema, doc, Data(), operation_name='Example') assert not isinstance(result, Deferred) assert result.data == {"promise": 'I should work'} assert not result.errors
def test_threads_context_correctly(): doc = 'query Example { a }' class Data(object): context_thing = 'thing' ast = parse(doc) def resolver(context, *_): assert context.context_thing == 'thing' resolver.got_here = True resolver.got_here = False Type = GraphQLObjectType( 'Type', {'a': GraphQLField(GraphQLString, resolver=resolver)}) result = execute(GraphQLSchema(Type), Data(), ast, 'Example', {}) assert not result.errors assert resolver.got_here
def test_does_not_include_arguments_that_were_not_set(): schema = GraphQLSchema( GraphQLObjectType( 'Type', { 'field': GraphQLField( GraphQLString, resolver=lambda data, args, *_: args and json.dumps( args, sort_keys=True, separators=(',', ':')), args={ 'a': GraphQLArgument(GraphQLBoolean), 'b': GraphQLArgument(GraphQLBoolean), 'c': GraphQLArgument(GraphQLBoolean), 'd': GraphQLArgument(GraphQLInt), 'e': GraphQLArgument(GraphQLInt), }) })) ast = parse('{ field(a: true, c: false, e: 0) }') result = execute(schema, None, ast) assert result.data == {'field': '{"a":true,"c":false,"e":0}'}
async def test_asyncio_py35_executor_with_error(): doc = 'query Example { a, b }' async def resolver(context, *_): await asyncio.sleep(0.001) return 'hey' async def resolver_2(context, *_): await asyncio.sleep(0.003) raise Exception('resolver_2 failed!') Type = GraphQLObjectType('Type', { 'a': GraphQLField(GraphQLString, resolver=resolver), 'b': GraphQLField(GraphQLString, resolver=resolver_2) }) executor = Executor([AsyncioExecutionMiddleware()]) result = await executor.execute(GraphQLSchema(Type), doc) formatted_errors = list(map(format_error, result.errors)) assert formatted_errors == [{'locations': [{'line': 1, 'column': 20}], 'message': 'resolver_2 failed!'}] assert result.data == {'a': 'hey', 'b': None}
def internal_type(cls, schema): if cls._meta.is_interface: return GraphQLInterfaceType( cls._meta.type_name, description=cls._meta.description, resolve_type=partial(cls._resolve_type, schema), fields=partial(cls.get_fields, schema) ) elif cls._meta.is_union: return GraphQLUnionType( cls._meta.type_name, types=cls._meta.types, description=cls._meta.description, ) return GraphQLObjectType( cls._meta.type_name, description=cls._meta.description, interfaces=[schema.T(i) for i in cls._meta.interfaces], fields=partial(cls.get_fields, schema), is_type_of=getattr(cls, 'is_type_of', None) )
def test_avoids_recursion(): doc = ''' query Q { a ...Frag ...Frag } fragment Frag on Type { a, ...Frag } ''' class Data(object): a = 'b' ast = parse(doc) Type = GraphQLObjectType('Type', {'a': GraphQLField(GraphQLString)}) result = execute(GraphQLSchema(Type), Data(), ast, 'Q') assert not result.errors assert result.data == {'a': 'b'}
async def test_asyncio_py35_executor(): doc = 'query Example { a, b }' async def resolver(context, *_): await asyncio.sleep(0.001) return 'hey' async def resolver_2(context, *_): await asyncio.sleep(0.003) return 'hey2' Type = GraphQLObjectType( 'Type', { 'a': GraphQLField(GraphQLString, resolver=resolver), 'b': GraphQLField(GraphQLString, resolver=resolver_2) }) executor = Executor(GraphQLSchema(Type), [AsyncioExecutionMiddleware()]) result = await executor.execute(doc) assert not result.errors assert result.data == {'a': 'hey', 'b': 'hey2'}
def test_merges_parallel_fragments(): ast = parse(''' { a, ...FragOne, ...FragTwo } fragment FragOne on Type { b deep { b, deeper: deep { b } } } fragment FragTwo on Type { c deep { c, deeper: deep { c } } } ''') Type = GraphQLObjectType('Type', lambda: { 'a': GraphQLField(GraphQLString, resolver=lambda *_: 'Apple'), 'b': GraphQLField(GraphQLString, resolver=lambda *_: 'Banana'), 'c': GraphQLField(GraphQLString, resolver=lambda *_: 'Cherry'), 'deep': GraphQLField(Type, resolver=lambda *_: {}), }) schema = GraphQLSchema(query=Type) result = execute(schema, None, ast) assert not result.errors assert result.data == \ { 'a': 'Apple', 'b': 'Banana', 'c': 'Cherry', 'deep': { 'b': 'Banana', 'c': 'Cherry', 'deeper': { 'b': 'Banana', 'c': 'Cherry'}} }
def make_field(self): output_fields = self.get_output_fields() output_fields.update({ 'clientMutationId': GraphQLField(GraphQLString) }) output_type = GraphQLObjectType( self.name + 'Payload', fields=output_fields) input_fields = self.get_input_fields() input_fields.update({ 'clientMutationId': GraphQLInputObjectField(GraphQLString) }) input_arg = GraphQLArgument(GraphQLNonNull(GraphQLInputObjectType( name=self.name + 'Input', fields=input_fields))) return GraphQLField( output_type, args = { 'input': input_arg, }, resolver=self )