diff --git a/requirements.txt b/requirements.txt index 4db8ee2..282a1c4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,7 +10,3 @@ pytest-cov ruff pre-commit httpx -graphene==2.1.9 -graphql-core==2.3.2 -graphql-relay==2.0.1 -graphql-server-core==2.0.0 diff --git a/responder/api.py b/responder/api.py index 6b839d2..4e089a4 100644 --- a/responder/api.py +++ b/responder/api.py @@ -22,7 +22,7 @@ from .background import BackgroundQueue from .formats import get_formats from .routes import Router from .statics import DEFAULT_API_THEME, DEFAULT_CORS_PARAMS, DEFAULT_SECRET_KEY -from .ext.schema import Schema as OpenAPISchema +from .ext.schema import OpenAPISchema as OpenAPISchema from .staticfiles import StaticFiles from .templates import Templates diff --git a/responder/cli.py b/responder/cli.py deleted file mode 100644 index 8c5548b..0000000 --- a/responder/cli.py +++ /dev/null @@ -1,43 +0,0 @@ -"""Responder. - -Usage: - responder - responder run [--build] [--debug] - responder build - responder --version - -Options: - -h --help Show this screen. - -v --version Show version. - -""" - -import os - -import docopt -from .__version__ import __version__ - - -def cli(): - args = docopt.docopt( - __doc__, argv=None, help=True, version=__version__, options_first=False - ) - - module = args[""] - build = args["build"] or args["--build"] - run = args["run"] - - if build: - os.system("npm run build") - - if run: - split_module = module.split(":") - - if len(split_module) > 1: - module = split_module[0] - prop = split_module[1] - else: - prop = "api" - - app = __import__(module) - getattr(app, prop).run() diff --git a/responder/core.py b/responder/core.py index df0848b..ac22195 100644 --- a/responder/core.py +++ b/responder/core.py @@ -1,3 +1,2 @@ from .api import API from .models import Request, Response -from .cli import cli diff --git a/responder/ext/__init__.py b/responder/ext/__init__.py index 130dc0a..e69de29 100644 --- a/responder/ext/__init__.py +++ b/responder/ext/__init__.py @@ -1 +0,0 @@ -from .graphql import GraphQLView diff --git a/responder/ext/graphql/__init__.py b/responder/ext/graphql/__init__.py deleted file mode 100644 index 36f3b32..0000000 --- a/responder/ext/graphql/__init__.py +++ /dev/null @@ -1,70 +0,0 @@ -import json -from functools import partial - -from graphql_server import default_format_error, encode_execution_results, json_encode - -from .templates import GRAPHIQL - - -class GraphQLView: - def __init__(self, *, api, schema): - self.api = api - self.schema = schema - - @staticmethod - async def _resolve_graphql_query(req): - # TODO: Get variables and operation_name from form data, params, request text? - - if "json" in req.mimetype: - json_media = await req.media("json") - return ( - json_media["query"], - json_media.get("variables"), - json_media.get("operationName"), - ) - - # Support query/q in form data. - # Form data is awaiting https://github.com/encode/starlette/pull/102 - # if "query" in req.media("form"): - # return req.media("form")["query"], None, None - # if "q" in req.media("form"): - # return req.media("form")["q"], None, None - - # Support query/q in params. - if "query" in req.params: - return req.params["query"], None, None - if "q" in req.params: - return req.params["q"], None, None - - # Otherwise, the request text is used (typical). - # TODO: Make some assertions about content-type here. - return req.text, None, None - - async def graphql_response(self, req, resp, schema): - show_graphiql = req.method == "get" and req.accepts("text/html") - - if show_graphiql: - resp.content = self.api.templates.render_string( - GRAPHIQL, endpoint=req.url.path - ) - return - - query, variables, operation_name = await self._resolve_graphql_query(req) - context = {"request": req, "response": resp} - result = schema.execute( - query, variables=variables, operation_name=operation_name, context=context - ) - result, status_code = encode_execution_results( - [result], - is_batch=False, - format_error=default_format_error, - encode=partial(json_encode, pretty=False), - ) - resp.media = json.loads(result) - return (query, result, status_code) - - async def on_request(self, req, resp): - await self.graphql_response(req, resp, self.schema) - - async def __call__(self, req, resp): - await self.on_request(req, resp) diff --git a/responder/ext/graphql/templates.py b/responder/ext/graphql/templates.py deleted file mode 100644 index ee0e2e0..0000000 --- a/responder/ext/graphql/templates.py +++ /dev/null @@ -1,145 +0,0 @@ -GRAPHIQL = """ -{% set GRAPHIQL_VERSION = '0.12.0' %} - - - - - - - - - - - - - - - -
Loading...
- - - -""".strip() diff --git a/responder/ext/schema/__init__.py b/responder/ext/schema/__init__.py index a9a10a1..e641ad6 100644 --- a/responder/ext/schema/__init__.py +++ b/responder/ext/schema/__init__.py @@ -8,11 +8,10 @@ from apispec import APISpec, yaml_utils from apispec.ext.marshmallow import MarshmallowPlugin from responder.statics import DEFAULT_API_THEME -from responder.staticfiles import StaticFiles from responder import status_codes -class Schema: +class OpenAPISchema: def __init__( self, app, diff --git a/tests/conftest.py b/tests/conftest.py index 33c6cdf..b38fb30 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,3 @@ -import graphene import responder from pathlib import Path import pytest @@ -47,17 +46,6 @@ def flask(): return app -@pytest.fixture -def schema(): - class Query(graphene.ObjectType): - hello = graphene.String(name=graphene.String(default_value="stranger")) - - def resolve_hello(self, info, name): - return f"Hello {name}" - - return graphene.Schema(query=Query) - - @pytest.fixture def template_path(tmpdir): # create a Jinja template file on the filesystem diff --git a/tests/test_responder.py b/tests/test_responder.py index 0a452b6..1f090e7 100644 --- a/tests/test_responder.py +++ b/tests/test_responder.py @@ -3,12 +3,12 @@ import yaml import random import responder import string -import io -from responder.routes import Router, Route, WebSocketRoute + + +from responder.routes import Route, WebSocketRoute from responder.templates import Templates from starlette.middleware.base import BaseHTTPMiddleware -from starlette.responses import PlainTextResponse from starlette.testclient import TestClient as StarletteTestClient @@ -136,13 +136,6 @@ def test_yaml_media(api): assert yaml.load(r.content, Loader=yaml.FullLoader) == dump -def test_graphql_schema_query_querying(api, schema): - api.add_route("/", responder.ext.GraphQLView(schema=schema, api=api)) - - r = api.requests.get("http://;/?q={ hello }", headers={"Accept": "json"}) - assert r.json() == {"data": {"hello": "Hello stranger"}} - - def test_argumented_routing(api): @api.route("/{name}") def hello(req, resp, *, name): @@ -266,21 +259,6 @@ def test_multiple_routes(api): assert r.text == "2" -def test_graphql_schema_json_query(api, schema): - api.add_route("/", responder.ext.GraphQLView(schema=schema, api=api)) - - r = api.requests.post("http://;/", json={"query": "{ hello }"}) - assert r.status_code < 300 - - -def test_graphiql(api, schema): - api.add_route("/", responder.ext.GraphQLView(schema=schema, api=api)) - - r = api.requests.get("http://;/", headers={"Accept": "text/html"}) - assert r.status_code < 300 - assert "GraphiQL" in r.text - - def test_json_uploads(api): @api.route("/") async def route(req, resp): @@ -348,7 +326,7 @@ def test_yaml_downloads(api): def test_schema_generation_explicit(): import responder - from responder.ext.schema import Schema as OpenAPISchema + from responder.ext.schema import OpenAPISchema as OpenAPISchema import marshmallow api = responder.API() @@ -413,7 +391,7 @@ def test_schema_generation(): def test_documentation_explicit(): import responder - from responder.ext.schema import Schema as OpenAPISchema + from responder.ext.schema import OpenAPISchema as OpenAPISchema import marshmallow