-
-
Save jasonphillips/d80642fc33d98cb34bad131adfcf6ed8 to your computer and use it in GitHub Desktop.
import graphql | |
# build_executable schema | |
# | |
# accepts schema_definition (string) and resolvers (object) in style of graphql-tools | |
# returns a schema ready for execution | |
def build_executable_schema(schema_definition, resolvers): | |
ast = graphql.parse(schema_definition) | |
schema = graphql.build_ast_schema(ast) | |
for typeName in resolvers: | |
fieldType = schema.get_type(typeName) | |
for fieldName in resolvers[typeName]: | |
if fieldType is graphql.GraphQLScalarType: | |
fieldType.fields[fieldName].resolver = resolvers[typeName][fieldName] | |
continue | |
field = fieldType.fields[fieldName] | |
field.resolver = resolvers[typeName][fieldName] | |
if not fieldType.fields: continue | |
for remaining in fieldType.fields: | |
if not fieldType.fields[remaining].resolver: | |
fieldType.fields[remaining].resolver = \ | |
lambda value, info, _r=remaining, **args: value[_r] | |
return schema |
import graphql | |
import json | |
from graphql_tools import build_executable_schema | |
source_schema = """ | |
schema { | |
query: RootQuery | |
} | |
type RootQuery { | |
officers: [Officer] | |
} | |
type Officer { | |
title: String | |
first: String | |
last: String | |
uniform: Uniform | |
} | |
type Uniform { | |
pips: Float | |
} | |
""" | |
resolvers = { | |
'RootQuery': { | |
# returning direct values, but would normally load fetch db with some info.context | |
'officers': lambda value, info, **args: [ | |
dict(first='william', last='riker'), | |
dict(first='geordi', last='laforge'), | |
] | |
}, | |
'Officer': { | |
# only declaring the field here which is computed | |
'title': lambda value, info, **args: 'Officer: %(first)s %(last)s' % value, | |
# and the connection | |
'uniform': lambda value, info, **args: value['first']=='geordi' and {'i':2.5} or {'i':3}, | |
}, | |
'Uniform': { | |
'pips': lambda value, info, **args: value['i'], | |
} | |
} | |
my_schema = build_executable_schema(source_schema, resolvers) | |
executed = graphql.graphql(my_schema, """ | |
query Example { | |
officers { | |
first | |
last | |
title | |
uniform { pips } | |
} | |
} | |
""") | |
print(json.dumps(executed.data, indent=4)) |
{ | |
"officers": [ | |
{ | |
"first": "william", | |
"last": "riker", | |
"title": "Officer: william riker", | |
"uniform": { | |
"pips": 3.0 | |
} | |
}, | |
{ | |
"first": "geordi", | |
"last": "laforge", | |
"title": "Officer: geordi laforge", | |
"uniform": { | |
"pips": 2.5 | |
} | |
} | |
] | |
} |
How could I use it with graphene?
I've iterated on this idea a bit within a small project recently, and can hopefully find an opportunity from there to write it as a more complete package than the sketch above. I'll try to prioritize that in coming weeks and see what I can publish; will notify here when something comes to fruition.
(But as for usage with graphene, I'm not so sure -- this is more of an alternative to graphene's style of schema creation than an extension, as graphene's authors have likewise said, eg. here: graphql-python/graphene#704 )
Great Job!
I opened the issue graphql-python/graphene#704 .
I think it's a better idea to design schema by DSL format. I don't know much about why we have to get a extra graphene schema layer. Even though the graphene schema layer is necessary, we still must have a DSL => graphene schema
parser.
I'm quite confused that why there are two types of definition. Graphene schema definition graphene.types.schema.Schema
and graphql-core schema definition graphql.type.schema.GraphQLSchema
.
Since graphene.types.schema.Schema is extended from graphql.type.schema.GraphQLSchema
, how could I get graphene.types.schema.Schema
from graphq.parse(DSL file)?
And how to use with graphene?