Currently EXPERIMENTAL.
gqltype is a GraphQL schema generator from python type annotations.
- simple definition of GraphQL schema via python type annotations
- builds schema based on
graphql-core>=3.0library - asgi friendly
Using pip
$ pip install gqltype
Using poetry
$ poetry add gqltype
Let's say we want to model the schema mentioned at the beginning of https://graphql.org/learn/schema/ tutorial.
from dataclasses import dataclass from enum import Enum from typing import List import gqltype class Episode(Enum): """Codename for the episodes""" NEWHOPE = "new hope" EMPIRE = "empire" JEDI = "jedi" @dataclass class Character: """An individual person within the Star Wars universe""" name: str appears_in: List[Episode] class LengthUnit(Enum): """Measure of length""" METER = "meter" INCH = "inch" @dataclass class Starship: """A single transport craft that has hyperdrive capability""" id: str name: str length: float def resolve_length(self, unit: LengthUnit = LengthUnit.METER) -> float: if unit == LengthUnit.INCH: return self.length / 0.0254 return self.length def get_character() -> Character: return Character(name="R2D2", appears_in=[Episode.JEDI, Episode.NEWHOPE]) async def get_starship() -> Starship: return Starship(id="F1000", name="Millennium Falcon", length=34.75) def add_character(name: str, appears_in: List[Episode]) -> Character: return Character(name=name, appears_in=appears_in) schema = gqltype.Schema( queries=[get_character, get_starship], mutations=[add_character] ) from graphql.utilities import print_schema print(print_schema(schema.build()))
It'll produce the following output
type Query { getCharacter: Character! getStarship: Starship! } """An individual person within the Star Wars universe""" type Character { appearsIn: [Episode!]! name: String! } """Codename for the episodes""" enum Episode { NEWHOPE EMPIRE JEDI } """A single transport craft that has hyperdrive capability""" type Starship { length(unit: LengthUnit! = METER): Float! id: ID! name: String! } """Measure of length""" enum LengthUnit { METER INCH } type Mutation { addCharacter(name: String!, appearsIn: [Episode!]!): Character! }
In order to run server with this schema we can use Starlette
if __name__ == "__main__": import uvicorn from gqltype.contrib.starlette import GraphQLApp from starlette.applications import Starlette from starlette.routing import Route app = Starlette(routes=[Route("/graphql", GraphQLApp(schema=schema))]) uvicorn.run(app)
Executing
{
getCharacter {
name
appearsIn
}
getStarship {
id
name
length(unit: INCH)
}
}gives
{
"data": {
"getCharacter": {
"name": "R2D2",
"appearsIn": [
"JEDI",
"NEWHOPE"
]
},
"getStarship": {
"id": "F1000",
"name": "Millennium Falcon",
"length": 1368.1102362204724
}
}
}-
sanity checks
- warn if class and resolve method specify different types
-
generic resolvers for certain types?
-
gqltype.F ? -- field definition
-
core part and high level part
-
business level
- validation for input values
- serialization of output values