diff --git a/022-burette/magnum_opus_iii/magnumopus/graph.py b/022-burette/magnum_opus_iii/magnumopus/graph.py index c14b74c..e4d0f90 100644 --- a/022-burette/magnum_opus_iii/magnumopus/graph.py +++ b/022-burette/magnum_opus_iii/magnumopus/graph.py @@ -1,57 +1,46 @@ from quart import request, jsonify +from graphql import GraphQLSchema from ariadne import ObjectType, make_executable_schema, graphql -from ariadne.constants import PLAYGROUND_HTML +from .schemas import init_graph as init_graph_schemas +from .resources import init_graph as init_graph_resources -from .repositories import PANTRY_STORES - -PANTRY = PANTRY_STORES['list'] - -type_defs = """ +TYPE_DEFS = """ type Query { substances(nature: String!): [Substance] } - - type Substance { - nature: String!, - state: [String]! - } """ -query = ObjectType('Query') -substance = ObjectType('Substance') - -@query.field('substances') -def resolve_substances(obj, *_, nature='Unknown'): - return PANTRY.find_substances_by_nature(nature) - - -@substance.field('nature') -def resolve_nature(obj, *_): - return obj.nature - -@substance.field('state') -def resolve_state(obj, *_): - return obj.state - -schema = make_executable_schema(type_defs, query, substance) - -async def graphql_server(): - data = await request.get_json() - success, result = await graphql( - schema, - data, - context_value=request - ) - - return jsonify(result), (200 if success else 400) +class InjectorObjectType(ObjectType): + def __init__(self, *args, app=None, **kwargs): + super(InjectorObjectType, self).__init__(*args, **kwargs) + self._app = app + + def get_injector(self): + return self._app.extensions['injector'] + + def field(self, name: str): + g = super(InjectorObjectType, self).field(name) + def injected_resolver(f): + def _inject_resolver(*args, **kwargs): + self._app.logger.error(name) + inj = self.get_injector() + return inj.call_with_injection( + f, args=args, kwargs=kwargs + ) + return g(_inject_resolver) + return injected_resolver def init_app(app): - app.route('/graphql', methods=['GET'], endpoint='graphql_playground')( - lambda: (PLAYGROUND_HTML, 200) - ) + query = InjectorObjectType('Query', app=app) + + type_defs = [TYPE_DEFS] + init_graph_schemas(query) + resolvers = [query] + init_graph_resources(query) - app.route('/graphql', methods=['POST'], endpoint='graphql_server')( - graphql_server - ) + schema = make_executable_schema(type_defs, resolvers) - return [] + return [ + lambda binder: binder.bind( + GraphQLSchema, + to=schema + ) + ] diff --git a/022-burette/magnum_opus_iii/magnumopus/resources/__init__.py b/022-burette/magnum_opus_iii/magnumopus/resources/__init__.py index 7088c1e..cbe6bf9 100644 --- a/022-burette/magnum_opus_iii/magnumopus/resources/__init__.py +++ b/022-burette/magnum_opus_iii/magnumopus/resources/__init__.py @@ -1,7 +1,14 @@ from . import substance from . import alembic_instruction +from . import graph def init_app(app): substance.init_app(app) alembic_instruction.init_app(app) + graph.init_app(app) return [] + +def init_graph(graph): + resolvers = [] + resolvers += substance.init_graph(graph) + return resolvers diff --git a/022-burette/magnum_opus_iii/magnumopus/resources/graph.py b/022-burette/magnum_opus_iii/magnumopus/resources/graph.py new file mode 100644 index 0000000..7a44b5c --- /dev/null +++ b/022-burette/magnum_opus_iii/magnumopus/resources/graph.py @@ -0,0 +1,39 @@ +from quart import request, jsonify +from quart_openapi import Resource +from injector import inject +from typing import Dict +from ariadne import graphql +from ariadne.constants import PLAYGROUND_HTML +from graphql.type import GraphQLSchema +from ..injection import ViewInjectorMeta +from ..repositories.pantry import Pantry +from ..models import db + +class GraphResource(Resource): + @inject + def __init__(self, schema: GraphQLSchema): + super(GraphResource, self).__init__() + + self._schema = schema + + async def get(self): + return (PLAYGROUND_HTML, 200) + + async def post(self): + data = await request.get_json() + success, result = await graphql( + self._schema, + data, + context_value=request + ) + + return jsonify(result), (200 if success else 400) + + +def init_app(app): + class AppGraphResource(GraphResource, metaclass=ViewInjectorMeta): + get_app = lambda: app + + app.route('/graphql', endpoint='graphql')(AppGraphResource) + + return [] diff --git a/022-burette/magnum_opus_iii/magnumopus/resources/substance.py b/022-burette/magnum_opus_iii/magnumopus/resources/substance.py index 7c5ad88..2052a7b 100644 --- a/022-burette/magnum_opus_iii/magnumopus/resources/substance.py +++ b/022-burette/magnum_opus_iii/magnumopus/resources/substance.py @@ -2,6 +2,7 @@ from quart_openapi import Resource from injector import inject from typing import Dict +from ariadne import ObjectType from ..injection import ViewInjectorMeta from ..repositories.pantry import Pantry from ..models import db @@ -47,3 +48,22 @@ class AppSubstanceResource(SubstanceResource, metaclass=ViewInjectorMeta): get_app = lambda: app app.route('/substance', endpoint='SubstanceResource')(AppSubstanceResource) + +def init_graph(query): + substance = ObjectType('Substance') + + @query.field('substances') + @inject + def resolve_substances(obj, info, pantry: Pantry, *_, nature='Unknown'): + substances = pantry.find_substances_by_nature(nature) + return substances + + @substance.field('nature') + def resolve_nature(obj, *_): + return obj.nature + + @substance.field('state') + def resolve_state(obj, *_): + return obj.state + + return [substance] diff --git a/022-burette/magnum_opus_iii/magnumopus/schemas/__init__.py b/022-burette/magnum_opus_iii/magnumopus/schemas/__init__.py index 7b27dd7..58b0ef1 100644 --- a/022-burette/magnum_opus_iii/magnumopus/schemas/__init__.py +++ b/022-burette/magnum_opus_iii/magnumopus/schemas/__init__.py @@ -20,3 +20,10 @@ def configure_injector(binder): 'many': SubstanceSchema(many=True) } ) + +def init_graph(query): + from .substance_schema import init_graph as init_graph_substance + + return [ + init_graph_substance(query) + ] diff --git a/022-burette/magnum_opus_iii/magnumopus/schemas/substance_schema.py b/022-burette/magnum_opus_iii/magnumopus/schemas/substance_schema.py index 3f86c70..7c99105 100644 --- a/022-burette/magnum_opus_iii/magnumopus/schemas/substance_schema.py +++ b/022-burette/magnum_opus_iii/magnumopus/schemas/substance_schema.py @@ -5,6 +5,13 @@ from ..models.substance import Substance from ..services.assessor import assess_whether_substance_is_philosophers_stone +SUBSTANCE_GRAPH_SCHEMA = """ + type Substance { + nature: String!, + state: [String]! + } +""" + class SubstanceSchema(ma.SQLAlchemySchema): is_philosophers_stone = fields.Function( assess_whether_substance_is_philosophers_stone @@ -17,3 +24,6 @@ class Meta: id = fields.Integer() nature = fields.String() state = fields.Function(lambda model: model.state or []) + +def init_graph(query): + return SUBSTANCE_GRAPH_SCHEMA